原理简单说就是hook XMLHTTPRequest的send方法和open函数,而后在里面重组url和body参数,而后从新发起请求,这边有个难点,就是send和open是异步的,因此须要等hook到open中的参数后再发起请求。web
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函数