Recently I saw a lot of friends do some interception to open in seconds, here are a few solutions to cause problems and solve the direction

NSURLProtocol

This solution resolves interception requests

+ (BOOL)canInitWithRequest:(NSURLRequest*)requestCopy the code

Intercept resources in the above method

- (void)startLoadingCopy the code

Replace in this method.

Issues involved

Question 1

+ (BOOL)canInitWithRequest:(NSURLRequest*)request interception all requests are intercepted without distinction, so there are many unknown factors


+ (void)registerPrefix:(NSString *)prefixUrlKey prefixUrl:(NSString *)prefixUrl{    NSCParameterAssert(prefixUrlKey);    NSCParameterAssert(prefixUrl);    if (BUisEmptyString(prefixUrlKey) || BUisEmptyString(prefixUrl)) {        return;    }    [self doInitialize];    @synchronized(prefixDict) {        [prefixDict setObject:prefixUrl forKey:prefixUrlKey];
    }}Copy the code

Problem 2. The request for WKWebview was intercepted, causing body loss

This problem is a headache for students, but if you are an app, there are many solutions

Method 1: Get the body using HTTPBodyStream and assign it to it

- (NSMutableURLRequest *)getMutablePostRequestIncludeBody {    NSMutableURLRequest * req = [self mutableCopy];    if ([self.HTTPMethod isEqualToString:@"POST"]) {        if(! self.HTTPBody) { NSInteger maxLength = 1024; uint8_t d[maxLength]; NSInputStream *stream = self.HTTPBodyStream; NSMutableData *data = [[NSMutableData alloc] init]; [stream open]; BOOL endOfStreamReached = NO; [stream hasBytesAvailable]) will always return YES when processing image fileswhileThere's an endless loop.while(! endOfStreamReached) { NSInteger bytesRead = [streamread:d maxLength:maxLength];                if(bytesRead == 0) {// At the end of the file read endofstreamreach = YES; }else if(bytesRead == -1) {// File read error endOfStreamReached = YES; }else if(stream.streamError == nil) { [data appendBytes:(void *)d length:bytesRead]; } } req.HTTPBody = [data copy]; [stream close]; }}returnreq; }Copy the code

Method 2: Inject the intercepting JS code into the WK container so that the corresponding request is intercepted by the client

hookAjax
hookFetchCopy the code

Method 3: The request scheme of the front-end is customized and forwarded by the client

[NSURLProtocol registerClass:[XXURLProtocol class]];
[NSURLProtocol wk_registerScheme:@"xxscheme"];

WKURLSchemeTask

This solution only supports iOS11 and above, but can solve the problem of body loss

- (void)webView:(WKWebView *)webView startURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask

The above method starts intercepting and populating the data internally

However, students using this scheme found a problem, which can only intercept custom scheme, HTTP and HTTPS interception will crash, as shown in the following figure



Finally find an official API that doesn’t work…

Never mind, the solution is as follows:

Method 1. The front-end students modify scheme, all request schmes are changed to custom, so that you can customize interception.

Front OS: somebody else Android nothing you let me change… How to fit…

Em, that won’t tear, so…

Method 2. We hook the corresponding interception method and modify the interception rule.

In the code

+ (void)_hookHandlesURLScheme { xx_WebViewClassMethodSwizzle(self, @selector(handlesURLScheme:), @selector(xx_handlesURLScheme:)); }+ (BOOL)xx_handlesURLScheme:(NSString *)name {if ([name isEqualToString:@"http"] ||        [name isEqualToString:@"https"]) {        return NO;    }    return[self xx_handlesURLScheme:name]; }Copy the code

Understand it… You hook it up and you can do whatever you want


Of course… When you have all the methods implemented and you find that your functionality can run and successfully intercept, you will find a problem.



Knowing what will happen next…

Please leave a message to contact me.

Tips are welcome.