思考NSURLProtocol沒法攔截WKWebview請求的解決思路

1.hook XMLHTTPRequest

原理簡單說就是hook XMLHTTPRequest的send方法和open函數,而後在裏面重組url和body參數,而後從新發起請求,這邊有個難點,就是send和open是異步的,因此須要等hook到open中的參數後再發起請求。web

2.WKURLSchemeHandler

WKURLSchemeHandler是iOS11就推出的,用於處理自定義請求的方案,不過並不能處理HTTP、HTTPS等常規scheme。可是如今有另一個方法,就是去 WKWebview的initWithFrame:方法,而後設置一個WKURLSchemeHandler給WKWebview實例,這樣就能截獲WKWebview的HTTP和HTTPS請求了。範例以下瀏覽器

//
//  ViewController.m
//  WKWebviewURLSchemeHandlerProject
//
//  Created by jerrold on 2019/3/5.
//  Copyright © 2019 jerrold. All rights reserved.
//

#import "ViewController.h"
#import <WebKit/WebKit.h>

@interface CustomURLSchemeHandler : NSObject<WKURLSchemeHandler>
@end

@implementation CustomURLSchemeHandler
//這裏攔截到URLScheme爲customScheme的請求後,讀取本地圖片test.jpg,並返回給WKWebView顯示
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask{
    NSURLRequest *request = urlSchemeTask.request;
    //在下面處理攔截到的HTTP和HTTPS請求,處理完後再次發起請求, 注意要處理didReceiveResponse:  didReceiveData: didFinish三個方法回調
    if ([request.URL.scheme containsString:@"https"]) {
        
    }else if ([request.URL.scheme containsString:@"http"]){
        
    }
//    UIImage *image = [UIImage imageNamed:@"test.jpg"];
//    NSData *data = UIImageJPEGRepresentation(image, 1.0);
//    NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:@"image/jpeg" expectedContentLength:data.length textEncodingName:nil];
//    [urlSchemeTask didReceiveResponse:response];
//    [urlSchemeTask didReceiveData:data];
//    [urlSchemeTask didFinish];
}


- (void)webView:(WKWebView *)webVie stopURLSchemeTask:(id)urlSchemeTask {
}
@end
@interface ViewController ()

@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //以下是以APP爲視角寫的處理WKWebview請求的方式,若是要AOP,就須要hook WKWebview的initwithFrame方法,在裏面處理WKWebview的請求
    WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];
    CustomURLSchemeHandler *handler = [[CustomURLSchemeHandler alloc]init];
    NSMutableDictionary *handlers = [configuration valueForKey:@"_urlSchemeHandlers"];
    handlers[@"https"] = handler;//修改handler,將HTTP和HTTPS也一塊兒攔截
    handlers[@"http"] = handler;
    WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
    self.view = webView;
    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.test.com"]]];
}
@end
複製代碼

不過,這種方案和第一種有共性,就是利用了私有API,極可能致使被ban,畢竟apple最近審查很是嚴苛。可是起碼比第一種方案好,不用擔憂body大小的問題,不用擔憂影響瀏覽器性能。bash

參考文獻app

1.WebKitでPrivateAPI使ってProxyを実裝する異步

2.Intercepting UIWebView & WKWebView — Custom URL Scheme handling函數

3.iOS 11 WKWebView新特性性能

相關文章
相關標籤/搜索