4848public class WebViewLocalServer {
4949 private static String TAG = "WebViewAssetServer" ;
5050 private String basePath ;
51- /**
52- * capacitorapp.net is reserved by the Ionic team for use in local capacitor apps.
53- */
54- public final static String knownUnusedAuthority = "capacitorapp.net" ;
5551 private final static String httpScheme = "http" ;
5652 private final static String httpsScheme = "https" ;
53+ public final static String ionicFileScheme = "app-file" ;
54+ public final static String ionicContentScheme = "app-content" ;
5755
5856 private final UriMatcher uriMatcher ;
5957 private final AndroidProtocolHandler protocolHandler ;
6058 private final String authority ;
6159 // Whether we're serving local files or proxying (for example, when doing livereload on a
6260 // non-local endpoint (will be false in that case)
63- private final boolean isLocal ;
6461 private boolean isAsset ;
6562 // Whether to route all requests to paths without extensions back to `index.html`
6663 private final boolean html5mode ;
@@ -169,18 +166,7 @@ public Uri getHttpsPrefix() {
169166 this .html5mode = html5mode ;
170167 this .parser = parser ;
171168 this .protocolHandler = new AndroidProtocolHandler (context .getApplicationContext ());
172- if (authority != null ) {
173- this .authority = authority ;
174- if (authority .startsWith ("localhost" )) {
175- this .isLocal = true ;
176- } else {
177- this .isLocal = false ;
178- }
179-
180- } else {
181- this .isLocal = true ;
182- this .authority = UUID .randomUUID ().toString () + "" + knownUnusedAuthority ;
183- }
169+ this .authority = authority ;
184170 }
185171
186172 private static Uri parseAndVerifyUrl (String url ) {
@@ -234,24 +220,38 @@ public WebResourceResponse shouldInterceptRequest(Uri uri) {
234220 return null ;
235221 }
236222
237- if (this .isLocal ) {
223+ if (isLocalFile ( uri ) || uri . getAuthority (). equals ( this .authority ) ) {
238224 Log .d ("SERVER" , "Handling local request: " + uri .toString ());
239225 return handleLocalRequest (uri , handler );
240226 } else {
241227 return handleProxyRequest (uri , handler );
242228 }
243229 }
244230
231+ private boolean isLocalFile (Uri uri ) {
232+ if (uri .getScheme ().equals (ionicContentScheme ) || uri .getScheme ().equals (ionicFileScheme )) {
233+ return true ;
234+ }
235+ return false ;
236+ }
245237 private WebResourceResponse handleLocalRequest (Uri uri , PathHandler handler ) {
246238 String path = uri .getPath ();
239+
240+ if (isLocalFile (uri )) {
241+ InputStream responseStream = new LollipopLazyInputStream (handler , uri );
242+ String mimeType = getMimeType (path , responseStream );
243+ return createWebResourceResponse (mimeType , handler .getEncoding (),
244+ handler .getStatusCode (), handler .getReasonPhrase (), handler .getResponseHeaders (), responseStream );
245+ }
246+
247247 if (path .equals ("/" ) || (!uri .getLastPathSegment ().contains ("." ) && html5mode )) {
248248 InputStream stream ;
249249 String launchURL = parser .getLaunchUrl ();
250250 String launchFile = launchURL .substring (launchURL .lastIndexOf ("/" ) + 1 , launchURL .length ());
251251 try {
252252 String startPath = this .basePath + "/" + launchFile ;
253253 if (isAsset ) {
254- stream = protocolHandler .openAsset (startPath , "" );
254+ stream = protocolHandler .openAsset (startPath );
255255 } else {
256256 stream = protocolHandler .openFile (startPath );
257257 }
@@ -267,15 +267,10 @@ private WebResourceResponse handleLocalRequest(Uri uri, PathHandler handler) {
267267
268268 int periodIndex = path .lastIndexOf ("." );
269269 if (periodIndex >= 0 ) {
270- String ext = path .substring (path .lastIndexOf ("." ), path .length ());
271-
272270 InputStream responseStream = new LollipopLazyInputStream (handler , uri );
273- InputStream stream = responseStream ;
274-
275- String mimeType = getMimeType (path , stream );
276-
271+ String mimeType = getMimeType (path , responseStream );
277272 return createWebResourceResponse (mimeType , handler .getEncoding (),
278- handler .getStatusCode (), handler .getReasonPhrase (), handler .getResponseHeaders (), stream );
273+ handler .getStatusCode (), handler .getReasonPhrase (), handler .getResponseHeaders (), responseStream );
279274 }
280275
281276 return null ;
@@ -375,31 +370,12 @@ void register(Uri uri, PathHandler handler) {
375370 *
376371 * @param assetPath the local path in the application's asset folder which will be made
377372 * available by the server (for example "/www").
378- * @return prefixes under which the assets are hosted.
379373 */
380- public AssetHostingDetails hostAssets (String assetPath ) {
381- return hostAssets (authority , assetPath , "" , true , true );
374+ public void hostAssets (String assetPath ) {
375+ hostAssets (authority , assetPath );
382376 }
383377
384378
385- /**
386- * Hosts the application's assets on an http(s):// URL. Assets from the local path
387- * <code>assetPath/...</code> will be available under
388- * <code>http(s)://{uuid}.androidplatform.net/{virtualAssetPath}/...</code>.
389- *
390- * @param assetPath the local path in the application's asset folder which will be made
391- * available by the server (for example "/www").
392- * @param virtualAssetPath the path on the local server under which the assets should be hosted.
393- * @param enableHttp whether to enable hosting using the http scheme.
394- * @param enableHttps whether to enable hosting using the https scheme.
395- * @return prefixes under which the assets are hosted.
396- */
397- public AssetHostingDetails hostAssets (final String assetPath , final String virtualAssetPath ,
398- boolean enableHttp , boolean enableHttps ) {
399- return hostAssets (authority , assetPath , virtualAssetPath , enableHttp ,
400- enableHttps );
401- }
402-
403379 /**
404380 * Hosts the application's assets on an http(s):// URL. Assets from the local path
405381 * <code>assetPath/...</code> will be available under
@@ -408,39 +384,39 @@ public AssetHostingDetails hostAssets(final String assetPath, final String virtu
408384 * @param domain custom domain on which the assets should be hosted (for example "example.com").
409385 * @param assetPath the local path in the application's asset folder which will be made
410386 * available by the server (for example "/www").
411- * @param virtualAssetPath the path on the local server under which the assets should be hosted.
412- * @param enableHttp whether to enable hosting using the http scheme.
413- * @param enableHttps whether to enable hosting using the https scheme.
414387 * @return prefixes under which the assets are hosted.
415388 */
416- public AssetHostingDetails hostAssets (final String domain ,
417- final String assetPath , final String virtualAssetPath ,
418- boolean enableHttp , boolean enableHttps ) {
389+ public void hostAssets (final String domain ,
390+ final String assetPath ) {
419391 this .isAsset = true ;
420392 this .basePath = assetPath ;
421- Uri .Builder uriBuilder = new Uri .Builder ();
422- uriBuilder .scheme (httpScheme );
423- uriBuilder .authority (domain );
424- uriBuilder .path (virtualAssetPath );
393+
394+ createHostingDetails ();
395+ }
396+
397+ private void createHostingDetails () {
398+ final String assetPath = this .basePath ;
425399
426400 if (assetPath .indexOf ('*' ) != -1 ) {
427401 throw new IllegalArgumentException ("assetPath cannot contain the '*' character." );
428402 }
429- if (virtualAssetPath .indexOf ('*' ) != -1 ) {
430- throw new IllegalArgumentException (
431- "virtualAssetPath cannot contain the '*' character." );
432- }
433-
434- Uri httpPrefix = null ;
435- Uri httpsPrefix = null ;
436403
437404 PathHandler handler = new PathHandler () {
438405 @ Override
439406 public InputStream handle (Uri url ) {
440- InputStream stream ;
441- String path = url .getPath ().replaceFirst (virtualAssetPath , assetPath );
407+ InputStream stream = null ;
408+ String path = url .getPath ();
409+ if (!isAsset ) {
410+ path = basePath + url .getPath ();
411+ }
442412 try {
443- stream = protocolHandler .openAsset (path , assetPath );
413+ if ((url .getScheme ().equals (httpScheme ) || url .getScheme ().equals (httpsScheme )) && isAsset ) {
414+ stream = protocolHandler .openAsset (assetPath + path );
415+ } else if (url .getScheme ().equals (ionicFileScheme ) || !isAsset ) {
416+ stream = protocolHandler .openFile (path );
417+ } else if (url .getScheme ().equals (ionicContentScheme )) {
418+ stream = protocolHandler .openContentUrl (url );
419+ }
444420 } catch (IOException e ) {
445421 Log .e (TAG , "Unable to open asset URL: " + url );
446422 return null ;
@@ -450,18 +426,22 @@ public InputStream handle(Uri url) {
450426 }
451427 };
452428
453- if (enableHttp ) {
454- httpPrefix = uriBuilder .build ();
455- register (Uri .withAppendedPath (httpPrefix , "/" ), handler );
456- register (Uri .withAppendedPath (httpPrefix , "**" ), handler );
457- }
458- if (enableHttps ) {
459- uriBuilder .scheme (httpsScheme );
460- httpsPrefix = uriBuilder .build ();
461- register (Uri .withAppendedPath (httpsPrefix , "/" ), handler );
462- register (Uri .withAppendedPath (httpsPrefix , "**" ), handler );
463- }
464- return new AssetHostingDetails (httpPrefix , httpsPrefix );
429+ registerUriForScheme (httpScheme , handler , authority );
430+ registerUriForScheme (httpsScheme , handler , authority );
431+ registerUriForScheme (ionicFileScheme , handler , "" );
432+ registerUriForScheme (ionicContentScheme , handler , "" );
433+
434+ }
435+
436+ private void registerUriForScheme (String scheme , PathHandler handler , String authority ) {
437+ Uri .Builder uriBuilder = new Uri .Builder ();
438+ uriBuilder .scheme (scheme );
439+ uriBuilder .authority (authority );
440+ uriBuilder .path ("" );
441+ Uri uriPrefix = uriBuilder .build ();
442+
443+ register (Uri .withAppendedPath (uriPrefix , "/" ), handler );
444+ register (Uri .withAppendedPath (uriPrefix , "**" ), handler );
465445 }
466446
467447 /**
@@ -553,62 +533,11 @@ public InputStream handle(Uri url) {
553533 *
554534 * @param basePath the local path in the application's data folder which will be made
555535 * available by the server (for example "/www").
556- * @return prefixes under which the assets are hosted.
557536 */
558- public AssetHostingDetails hostFiles (String basePath ) {
559- return hostFiles (basePath , true , true );
560- }
561-
562- public AssetHostingDetails hostFiles (final String basePath , boolean enableHttp ,
563- boolean enableHttps ) {
537+ public void hostFiles (final String basePath ) {
564538 this .isAsset = false ;
565539 this .basePath = basePath ;
566- Uri .Builder uriBuilder = new Uri .Builder ();
567- uriBuilder .scheme (httpScheme );
568- uriBuilder .authority (authority );
569- uriBuilder .path ("" );
570-
571- Uri httpPrefix = null ;
572- Uri httpsPrefix = null ;
573-
574- PathHandler handler = new PathHandler () {
575- @ Override
576- public InputStream handle (Uri url ) {
577- InputStream stream ;
578- try {
579- if (url .getPath ().startsWith ("/_file_/" )) {
580- stream = protocolHandler .openFile ( url .getPath ().replace ("/_file_/" , "" ));
581- } else {
582- stream = protocolHandler .openFile (basePath + url .getPath ());
583- }
584- } catch (IOException e ) {
585- Log .e (TAG , "Unable to open asset URL: " + url );
586- return null ;
587- }
588-
589- String mimeType = null ;
590- try {
591- mimeType = URLConnection .guessContentTypeFromStream (stream );
592- } catch (Exception ex ) {
593- Log .e (TAG , "Unable to get mime type" + url );
594- }
595-
596- return stream ;
597- }
598- };
599-
600- if (enableHttp ) {
601- httpPrefix = uriBuilder .build ();
602- register (Uri .withAppendedPath (httpPrefix , "/" ), handler );
603- register (Uri .withAppendedPath (httpPrefix , "**" ), handler );
604- }
605- if (enableHttps ) {
606- uriBuilder .scheme (httpsScheme );
607- httpsPrefix = uriBuilder .build ();
608- register (Uri .withAppendedPath (httpsPrefix , "/" ), handler );
609- register (Uri .withAppendedPath (httpsPrefix , "**" ), handler );
610- }
611- return new AssetHostingDetails (httpPrefix , httpsPrefix );
540+ createHostingDetails ();
612541 }
613542
614543 /**
0 commit comments