1. The background

After the author switched the UIWebView in the App to WKWebView, some functions have been strengthened, including the annoying Cookie has been solved well, but the resource request interception in the offline package and webView has always been a worry, there is no very elegant solution.

The spread of custom HTTPS, HTTP interception scheme, can achieve part of the function. But there are big disadvantages,

  1. Calling proprietary apis, auditing, and later version upgrades have potential pitfalls
  2. XHR requests the problem of missing the body, so wrap a layer of myXHR instead of XHR
  3. Intercepts the body argument in the form request.

Caching and resource interception are the basic functions that webView frameworks are supposed to provide. AppHost also tries to implement them in a more elegant way, so it tries to use the new interface provided in iOS11+.

2. WKURLSchemeHandler checklist

WKURLSchemeHandler is introduced when WWDC 2017 Customized Loading in WKWebView. The Customized Loading is illustrated at that time.

Remember the phrase “loading custom images as an example”.

In combination with our requirements, we need to load local resources, intercept requests, and make Ajax requests, all of which contain the correct ** Cookie **. We need to solve the following sub-problems;

– User-defined scheme. Which schemes can be defined?

Based on my own testing and reading the source code, the following types of protocols are not available

static const StringVectorFunction functions[] {
            builtinSecureSchemes,
            builtinSchemesWithUniqueOrigins,
            builtinEmptyDocumentSchemes,
            builtinCanDisplayOnlyIfCanRequestSchemes,
            builtinCORSEnabledSchemes,
        };
Copy the code

Conclusion: None of the known conventions can be defined, including HTTPS, HTTP, about, and of course data, blob, FTP, etc. If you do, You will get an error ” HTTPS ‘is a URL scheme that WKWebView handles natively’

– Custom scheme, which HTML elements trigger custom requests?

The following table is organized according to tags collected by the author in common HTML elements that trigger resource downloads or navigation logic.

The label Domain is the HTTP case Domain is HTTPS Whether to trigger decidePolicyForNavigation

(This means webKit is buggy)
Img SRC
The script SRC
The href link
Iframe SRC
Background-image syntax of CSS
CSS cursor syntax
The data attribute of the object tag
SRC attribute of the audio label
The source attribute of the video tag
A Href attribute for the tag 😈
XHR url
form post 😈
form get 😈

To sum up; In MDN terms, mixed passive/display content is triggered in any case, mixed active content is not triggered under HTTPS.

Neither XHR requests nor mixed active content under HTTPS can be triggered because of two mechanisms;

  1. Mixed activity content is restricted CSP, which is basically impossible to bypass at present.
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; script-src 'self' apphost: ;" >Copy the code

Apphost ://a.js file is still prevented from loading. (Maybe my posture is wrong)

  1. XHR cannot be sent because of the SAME-Origin policy.

Definition of an originSection

Two URLs have the same origin if the protocol, port (if specified), and host are the same for both.

– Custom scheme, can cookies be included?

The author searched online and read the norms and practices of cookies in RFC6265, and drew the following conclusions.

  1. A custom scheme can carry cookies and share cookies with other protocols in the same domain. That’s impressive, and then actually not quite — preliminary tests,http.https.ftpScheme is actually perfectly fine,This includes setting session-level cookies. Otherwise, setting session cookies for custom schemes fails, and persistent cookies are possible. I didn’t think!

– Can a custom scheme send POST requests?

Yes. In cases where the WebKit implementation is buggy, a FORM can be used to send post requests. Not only that, but using the Form post, you can successfully send the body to native, which is amazing.

– Custom scheme that can intercept XHR requests? Is the body of the POST request missing?

In fact, it can be intercepted. In the table above, ❌ is used for both HTTP and HTTPS, but that is because domain is a standard protocol. If it is

[self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"apphost://test.com/index.2.html"]];
Copy the code

Then the XHR can still be sent, but unfortunately the body is still missing from the XHR.

3 the practice

Given the above premises. We have a simple offline package rendering scheme.

  1. Change the domain of the loading page to a custom protocol such as Apphost;
[self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"apphost://test.com/index.2.html"]];
Copy the code
  1. The loaded HTML file uses all the resources of the application://user/a.pngThe opposite way of writing it. This allows both HTTP and custom protocols to work.
  2. HTML ajax request using absolute path, modify the back end of the Response header, the use of cross-Origin Resource Sharing (CORS) technology, with the ajax request to add several parameters, you can also achieve the request with cookies

This way, you can intercept basically any type you could intercept in the days of traditional UIWebview. But the disadvantages are also obvious.

  • IOS 11+ is required
  • HTTPS has limited support
  • Minor changes to XHR JS code
  • Most seriously, session-level cookies are not supported.

In the AppHost framework, the author does not adopt this approach, but adopts the way of reading HTML and parsing static resources to realize the function of loading offline package, while not affecting the session level Cookie setting.

In general, WKURLSchemeHandler can be used in limited scenarios. It can’t intercept HTTP requests. Some methods combine NSURLSession, download HTML first, and then proxy, which will slow down the loading speed of webView.

Conclusion: WKURLSchemeHandler is best used for loading local images, otherwise unstable, so use with caution.

4. Note

  1. AppHost. Framework is a library extracted from JSBridge by the author in the rich and strict selection work of netease to realize the communication between Native and H5. Many common functions are built in, which can be used out of the box in the case of simple business, and flexible customization is allowed in complex situations. Open source is expected by the end of April

Reference 5.

  1. The definition of network – scheme
  2. Cookie domain in RFC6265
  3. Preflighted requests
  4. About Ajax carrying cookies across domains
  5. Test demo source