2828import java .io .InputStream ;
2929import java .net .HttpURLConnection ;
3030import java .net .SocketTimeoutException ;
31- import java .net .URL ;
32- import java .net .URLConnection ;
3331import java .util .HashMap ;
3432import java .util .Map ;
3533import java .util .UUID ;
34+ import java .util .List ;
35+
36+ import java .net .URL ;
37+ import java .net .URLConnection ;
3638
3739/**
3840 * Helper class meant to be used with the android.webkit.WebView class to enable hosting assets,
@@ -53,6 +55,7 @@ public class WebViewLocalServer {
5355 public final static String httpsScheme = "https" ;
5456 public final static String fileStart = "/_app_file_" ;
5557 public final static String contentStart = "/_app_content_" ;
58+ public final static String proxyStart = "/_local_proxy_" ;
5659
5760 private final UriMatcher uriMatcher ;
5861 private final AndroidProtocolHandler protocolHandler ;
@@ -219,18 +222,29 @@ public WebResourceResponse shouldInterceptRequest(Uri uri, WebResourceRequest re
219222 synchronized (uriMatcher ) {
220223 handler = (PathHandler ) uriMatcher .match (uri );
221224 }
225+
222226 if (handler == null ) {
223227 return null ;
224228 }
225229
226230 if (isLocalFile (uri ) || uri .getAuthority ().equals (this .authority )) {
227231 Log .d ("SERVER" , "Handling local request: " + uri .toString ());
228- return handleLocalRequest (uri , handler , request );
232+
233+ if (isLocalProxySource (uri )) {
234+ return handleLocalProxyRequest (uri , request );
235+ } else {
236+ return handleLocalRequest (uri , handler , request );
237+ }
229238 } else {
230239 return handleProxyRequest (uri , handler );
231240 }
232241 }
233242
243+ private boolean isLocalProxySource (Uri uri ) {
244+ String path = uri .getPath ();
245+ return path .startsWith (proxyStart );
246+ }
247+
234248 private boolean isLocalFile (Uri uri ) {
235249 String path = uri .getPath ();
236250 if (path .startsWith (contentStart ) || path .startsWith (fileStart )) {
@@ -239,6 +253,44 @@ private boolean isLocalFile(Uri uri) {
239253 return false ;
240254 }
241255
256+ private WebResourceResponse handleLocalProxyRequest (Uri uri , WebResourceRequest request ) {
257+ String fixedUri = uri .toString ().replaceFirst ("http://localhost/_local_proxy_/" , "" ); // Fix the url by removing the proxy schema
258+
259+ try {
260+ URL httpsUrl = new URL (fixedUri );
261+ URLConnection connection = httpsUrl .openConnection ();
262+ HttpURLConnection httpConnection = (HttpURLConnection )connection ;
263+
264+ Map <String , String > headers = new HashMap <String , String >();
265+ if (request != null && request .getRequestHeaders ().get ("Range" ) != null ) {
266+ String rangeString = request .getRequestHeaders ().get ("Range" );
267+ httpConnection .addRequestProperty ("Range" , rangeString );
268+
269+ String contentHeader = connection .getHeaderFields ().get ("Content-Length" ).get (0 );
270+
271+ int contentLength = Integer .parseInt (contentHeader );
272+ String [] parts = rangeString .split ("=" );
273+ String [] streamParts = parts [1 ].split ("-" );
274+ String fromRange = streamParts [0 ];
275+ int range = contentLength - 1 ;
276+
277+ headers .put ("Accept-Ranges" , "bytes" );
278+ headers .put ("Content-Length" , contentHeader );
279+ headers .put ("Content-Range" , "bytes " + fromRange + "-" + range + "/" + contentLength );
280+ }
281+
282+ // Bypass CORS
283+ headers .put ("Access-Control-Allow-Origin" , "*" );
284+ headers .put ("Access-Control-Allow-Methods" , "GET, POST, DELETE, PUT, OPTIONS" );
285+ headers .put ("Access-Control-Allow-Headers" , "agent, user-data, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers" );
286+
287+ return new WebResourceResponse (connection .getContentType (), connection .getContentEncoding (),
288+ httpConnection .getResponseCode (), httpConnection .getResponseMessage (), headers , httpConnection .getInputStream ());
289+
290+ } catch (Exception e ) {
291+ return null ;
292+ }
293+ }
242294
243295 private WebResourceResponse handleLocalRequest (Uri uri , PathHandler handler , WebResourceRequest request ) {
244296 String path = uri .getPath ();
@@ -265,6 +317,7 @@ private WebResourceResponse handleLocalRequest(Uri uri, PathHandler handler, Web
265317 return createWebResourceResponse (mimeType , handler .getEncoding (),
266318 statusCode , handler .getReasonPhrase (), tempResponseHeaders , responseStream );
267319 }
320+
268321 if (isLocalFile (uri )) {
269322 InputStream responseStream = new LollipopLazyInputStream (handler , uri );
270323 String mimeType = getMimeType (path , responseStream );
0 commit comments