48
48
public class WebViewLocalServer {
49
49
private static String TAG = "WebViewAssetServer" ;
50
50
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" ;
55
51
private final static String httpScheme = "http" ;
56
52
private final static String httpsScheme = "https" ;
53
+ public final static String fileStart = "/_app_file_" ;
54
+ public final static String contentStart = "/_app_content_" ;
57
55
58
56
private final UriMatcher uriMatcher ;
59
57
private final AndroidProtocolHandler protocolHandler ;
60
58
private final String authority ;
61
59
// Whether we're serving local files or proxying (for example, when doing livereload on a
62
60
// non-local endpoint (will be false in that case)
63
- private final boolean isLocal ;
64
61
private boolean isAsset ;
65
62
// Whether to route all requests to paths without extensions back to `index.html`
66
63
private final boolean html5mode ;
67
64
private ConfigXmlParser parser ;
68
65
69
- public String getAuthority () { return authority ; }
70
-
71
66
/**
72
67
* A handler that produces responses for paths on the virtual asset server.
73
68
* <p>
@@ -169,18 +164,7 @@ public Uri getHttpsPrefix() {
169
164
this .html5mode = html5mode ;
170
165
this .parser = parser ;
171
166
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
- }
167
+ this .authority = authority ;
184
168
}
185
169
186
170
private static Uri parseAndVerifyUrl (String url ) {
@@ -226,24 +210,40 @@ public WebResourceResponse shouldInterceptRequest(Uri uri) {
226
210
return null ;
227
211
}
228
212
229
- if (this .isLocal ) {
213
+ if (isLocalFile ( uri ) || uri . getAuthority (). equals ( this .authority ) ) {
230
214
Log .d ("SERVER" , "Handling local request: " + uri .toString ());
231
215
return handleLocalRequest (uri , handler );
232
216
} else {
233
217
return handleProxyRequest (uri , handler );
234
218
}
235
219
}
236
220
221
+ private boolean isLocalFile (Uri uri ) {
222
+ String path = uri .getPath ();
223
+ if (path .startsWith (contentStart ) || path .startsWith (fileStart )) {
224
+ return true ;
225
+ }
226
+ return false ;
227
+ }
228
+
237
229
private WebResourceResponse handleLocalRequest (Uri uri , PathHandler handler ) {
238
230
String path = uri .getPath ();
231
+
232
+ if (isLocalFile (uri )) {
233
+ InputStream responseStream = new LollipopLazyInputStream (handler , uri );
234
+ String mimeType = getMimeType (path , responseStream );
235
+ return createWebResourceResponse (mimeType , handler .getEncoding (),
236
+ handler .getStatusCode (), handler .getReasonPhrase (), handler .getResponseHeaders (), responseStream );
237
+ }
238
+
239
239
if (path .equals ("/" ) || (!uri .getLastPathSegment ().contains ("." ) && html5mode )) {
240
240
InputStream stream ;
241
241
String launchURL = parser .getLaunchUrl ();
242
242
String launchFile = launchURL .substring (launchURL .lastIndexOf ("/" ) + 1 , launchURL .length ());
243
243
try {
244
244
String startPath = this .basePath + "/" + launchFile ;
245
245
if (isAsset ) {
246
- stream = protocolHandler .openAsset (startPath , "" );
246
+ stream = protocolHandler .openAsset (startPath );
247
247
} else {
248
248
stream = protocolHandler .openFile (startPath );
249
249
}
@@ -367,10 +367,9 @@ void register(Uri uri, PathHandler handler) {
367
367
*
368
368
* @param assetPath the local path in the application's asset folder which will be made
369
369
* available by the server (for example "/www").
370
- * @return prefixes under which the assets are hosted.
371
370
*/
372
- public AssetHostingDetails hostAssets (String assetPath ) {
373
- return hostAssets (authority , assetPath , "" , true , true );
371
+ public void hostAssets (String assetPath ) {
372
+ hostAssets (authority , assetPath , "" , true , true );
374
373
}
375
374
376
375
@@ -384,11 +383,10 @@ public AssetHostingDetails hostAssets(String assetPath) {
384
383
* @param virtualAssetPath the path on the local server under which the assets should be hosted.
385
384
* @param enableHttp whether to enable hosting using the http scheme.
386
385
* @param enableHttps whether to enable hosting using the https scheme.
387
- * @return prefixes under which the assets are hosted.
388
386
*/
389
- public AssetHostingDetails hostAssets (final String assetPath , final String virtualAssetPath ,
387
+ public void hostAssets (final String assetPath , final String virtualAssetPath ,
390
388
boolean enableHttp , boolean enableHttps ) {
391
- return hostAssets (authority , assetPath , virtualAssetPath , enableHttp ,
389
+ hostAssets (authority , assetPath , virtualAssetPath , enableHttp ,
392
390
enableHttps );
393
391
}
394
392
@@ -403,36 +401,39 @@ public AssetHostingDetails hostAssets(final String assetPath, final String virtu
403
401
* @param virtualAssetPath the path on the local server under which the assets should be hosted.
404
402
* @param enableHttp whether to enable hosting using the http scheme.
405
403
* @param enableHttps whether to enable hosting using the https scheme.
406
- * @return prefixes under which the assets are hosted.
407
404
*/
408
- public AssetHostingDetails hostAssets (final String domain ,
405
+ public void hostAssets (final String domain ,
409
406
final String assetPath , final String virtualAssetPath ,
410
407
boolean enableHttp , boolean enableHttps ) {
411
408
this .isAsset = true ;
412
409
this .basePath = assetPath ;
413
- Uri .Builder uriBuilder = new Uri .Builder ();
414
- uriBuilder .scheme (httpScheme );
415
- uriBuilder .authority (domain );
416
- uriBuilder .path (virtualAssetPath );
410
+
411
+ createHostingDetails ();
412
+ }
413
+
414
+ private void createHostingDetails () {
415
+ final String assetPath = this .basePath ;
417
416
418
417
if (assetPath .indexOf ('*' ) != -1 ) {
419
418
throw new IllegalArgumentException ("assetPath cannot contain the '*' character." );
420
419
}
421
- if (virtualAssetPath .indexOf ('*' ) != -1 ) {
422
- throw new IllegalArgumentException (
423
- "virtualAssetPath cannot contain the '*' character." );
424
- }
425
-
426
- Uri httpPrefix = null ;
427
- Uri httpsPrefix = null ;
428
420
429
421
PathHandler handler = new PathHandler () {
430
422
@ Override
431
423
public InputStream handle (Uri url ) {
432
- InputStream stream ;
433
- String path = url .getPath (). replaceFirst ( virtualAssetPath , assetPath ) ;
424
+ InputStream stream = null ;
425
+ String path = url .getPath ();
434
426
try {
435
- stream = protocolHandler .openAsset (path , assetPath );
427
+ if (path .startsWith (contentStart )) {
428
+ stream = protocolHandler .openContentUrl (url );
429
+ } else if (path .startsWith (fileStart ) || !isAsset ) {
430
+ if (!path .startsWith (fileStart )) {
431
+ path = basePath + url .getPath ();
432
+ }
433
+ stream = protocolHandler .openFile (path );
434
+ } else {
435
+ stream = protocolHandler .openAsset (assetPath + path );
436
+ }
436
437
} catch (IOException e ) {
437
438
Log .e (TAG , "Unable to open asset URL: " + url );
438
439
return null ;
@@ -442,18 +443,20 @@ public InputStream handle(Uri url) {
442
443
}
443
444
};
444
445
445
- if (enableHttp ) {
446
- httpPrefix = uriBuilder .build ();
447
- register (Uri .withAppendedPath (httpPrefix , "/" ), handler );
448
- register (Uri .withAppendedPath (httpPrefix , "**" ), handler );
449
- }
450
- if (enableHttps ) {
451
- uriBuilder .scheme (httpsScheme );
452
- httpsPrefix = uriBuilder .build ();
453
- register (Uri .withAppendedPath (httpsPrefix , "/" ), handler );
454
- register (Uri .withAppendedPath (httpsPrefix , "**" ), handler );
455
- }
456
- return new AssetHostingDetails (httpPrefix , httpsPrefix );
446
+ registerUriForScheme (httpScheme , handler , authority );
447
+ registerUriForScheme (httpsScheme , handler , authority );
448
+
449
+ }
450
+
451
+ private void registerUriForScheme (String scheme , PathHandler handler , String authority ) {
452
+ Uri .Builder uriBuilder = new Uri .Builder ();
453
+ uriBuilder .scheme (scheme );
454
+ uriBuilder .authority (authority );
455
+ uriBuilder .path ("" );
456
+ Uri uriPrefix = uriBuilder .build ();
457
+
458
+ register (Uri .withAppendedPath (uriPrefix , "/" ), handler );
459
+ register (Uri .withAppendedPath (uriPrefix , "**" ), handler );
457
460
}
458
461
459
462
/**
@@ -545,62 +548,16 @@ public InputStream handle(Uri url) {
545
548
*
546
549
* @param basePath the local path in the application's data folder which will be made
547
550
* available by the server (for example "/www").
548
- * @return prefixes under which the assets are hosted.
549
551
*/
550
- public AssetHostingDetails hostFiles (String basePath ) {
551
- return hostFiles (basePath , true , true );
552
+ public void hostFiles (String basePath ) {
553
+ hostFiles (basePath , true , true );
552
554
}
553
555
554
- public AssetHostingDetails hostFiles (final String basePath , boolean enableHttp ,
556
+ public void hostFiles (final String basePath , boolean enableHttp ,
555
557
boolean enableHttps ) {
556
558
this .isAsset = false ;
557
559
this .basePath = basePath ;
558
- Uri .Builder uriBuilder = new Uri .Builder ();
559
- uriBuilder .scheme (httpScheme );
560
- uriBuilder .authority (authority );
561
- uriBuilder .path ("" );
562
-
563
- Uri httpPrefix = null ;
564
- Uri httpsPrefix = null ;
565
-
566
- PathHandler handler = new PathHandler () {
567
- @ Override
568
- public InputStream handle (Uri url ) {
569
- InputStream stream ;
570
- try {
571
- if (url .getPath ().startsWith ("/_file_/" )) {
572
- stream = protocolHandler .openFile ( url .getPath ().replace ("/_file_/" , "" ));
573
- } else {
574
- stream = protocolHandler .openFile (basePath + url .getPath ());
575
- }
576
- } catch (IOException e ) {
577
- Log .e (TAG , "Unable to open asset URL: " + url );
578
- return null ;
579
- }
580
-
581
- String mimeType = null ;
582
- try {
583
- mimeType = URLConnection .guessContentTypeFromStream (stream );
584
- } catch (Exception ex ) {
585
- Log .e (TAG , "Unable to get mime type" + url );
586
- }
587
-
588
- return stream ;
589
- }
590
- };
591
-
592
- if (enableHttp ) {
593
- httpPrefix = uriBuilder .build ();
594
- register (Uri .withAppendedPath (httpPrefix , "/" ), handler );
595
- register (Uri .withAppendedPath (httpPrefix , "**" ), handler );
596
- }
597
- if (enableHttps ) {
598
- uriBuilder .scheme (httpsScheme );
599
- httpsPrefix = uriBuilder .build ();
600
- register (Uri .withAppendedPath (httpsPrefix , "/" ), handler );
601
- register (Uri .withAppendedPath (httpsPrefix , "**" ), handler );
602
- }
603
- return new AssetHostingDetails (httpPrefix , httpsPrefix );
560
+ createHostingDetails ();
604
561
}
605
562
606
563
/**
0 commit comments