karosLi / KKJSBridge

一站式解决 WKWebView 支持离线包,Ajax/Fetch 请求,表单请求和 Cookie 同步的问题 (基于 Ajax Hook,Fetch Hook 和 Cookie Hook)
MIT License
693 stars 120 forks source link

请问下如何以最小的代码侵入使用自己的NSURLProtocol做资源拦截呢? #33

Open Lee0820 opened 4 years ago

Lee0820 commented 4 years ago

之前项目里都是用的原生的WKWebView,主要目的是拦截h5里的请求,现在想用您这个框架解决拦截过程中body丢失的问题,如果用外部代理代码改动量很大,自己新建一个NSURLProtocol好像还是需要使用到KKJSBridgeEngine,能否就这种情况简单给个示例,感谢!

karosLi commented 4 years ago

不使用 KKJSBridgeEngine 的话,是不会自动处理 body 丢失的问题的。所以还是需要集成。

你可以使用这个版本(1.1.5-beta9)来做集成,对于资源拦截,你只需要注册自己的资源拦截的 NSURLProtocol 即可。

例如:

// 注册 HtmlURLProtocol,使用离线包
[NSURLProtocol registerClass:HtmlURLProtocol.class];
// 具体拦截逻辑
#import "HtmlURLProtocol.h"

static NSString * const kKKJSBridgeNSURLProtocolKey = @"kKKJSBridgeNSURLProtocolKey1";

@interface HtmlURLProtocol () <NSURLSessionDelegate>

@property (nonatomic, strong) NSURLSessionDataTask *customTask;
@property (nonatomic, copy) NSString *requestId;
@property (nonatomic, copy) NSString *requestHTTPMethod;

@end

@implementation HtmlURLProtocol

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    // 看看是否已经处理过了,防止无限循环
    if ([NSURLProtocol propertyForKey:kKKJSBridgeNSURLProtocolKey inRequest:request]) {
        return NO;
    }

    NSLog(@"HtmlURLProtocol %@", request.URL.absoluteString);
    return YES;
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
    return [super requestIsCacheEquivalent:a toRequest:b];
}

- (instancetype)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client {
    self = [super initWithRequest:request cachedResponse:cachedResponse client:client];
    if (self) {

    }
    return self;
}

- (void)startLoading {
    NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
    //给我们处理过的请求设置一个标识符, 防止无限循环,
    [NSURLProtocol setProperty:@YES forKey:kKKJSBridgeNSURLProtocolKey inRequest:mutableReqeust];

    // 处理离线资源,或者替换资源的样式
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
    self.customTask = [session dataTaskWithRequest:mutableReqeust];
    [self.customTask resume];
}

- (void)stopLoading {
    if (self.customTask != nil) {
        [self.customTask  cancel];
        self.customTask = nil;
    }
}

#pragma mark - NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    if (error) {
        [self.client URLProtocol:self didFailWithError:error];
    } else {
        [self.client URLProtocolDidFinishLoading:self];
    }
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    [self.client URLProtocol:self didLoadData:data];
}

@end
karosLi commented 4 years ago

弹框?你这个链接我在Chrome打开也没有弹框