使用WKWebView拦截请求

Pol*_*Pol 13 objective-c ios

现在,我使用UIWebViewcanInitWithRequest:NSURLProtocol我可以拦截所有请求,并用它做我想做的.

在新的WKWebView这种方法没有,我没有发现类似的东西.

有人解决了这个问题吗?

Pol*_*Pol 17

我发现五年后这个问题仍然引起人们的好奇,所以我描述了我是如何解决它的以及我遇到的一些主要问题。正如许多在这里回答的人一样,我已经实施WKURLSchemeHandler并使用了新方案。

首先,wkwebview 启动的 URL 不能是 HTTP(或 HTTPS),而是您的新方案之一。

例子

mynewscheme://your-server-application.com

在您的WKWebViewConfigurationconf中,我设置了处理程序:

[conf setURLSchemeHandler:[CustomSchemeHandler new] forURLScheme:@"mynewscheme"];
[conf setURLSchemeHandler:[CustomSchemeHandler new] forURLScheme:@"mynewschemesecure"];
Run Code Online (Sandbox Code Playgroud)

CustomSchemeHandler我已经实现了webView:startURLSchemeTask:webView:stopURLSchemeTask:.

就我而言,我检查请求是否是针对我刚刚在本地保存的文件,否则我会使用http(或https)更改实际协议(“mynewscheme”或“mynewschemesecure”),然后我自己发出请求。

至此我解决了“拦截问题”。

通过这种新方式,我们有了带有我的新方案的 webview“位置”(location.href通过 javascript),并随之开始了新的问题。

  • 第一个问题是我的应用程序主要使用 javascript 工作,并且document.cookie已经停止工作。我正在使用 Cordova 框架,所以我开发了一个插件来设置和获取 cookie 来替换 document.cookie (我必须这样做,因为显然,我还有 http header set-cookie)。

  • 第二个问题是我遇到了很多“跨域”问题,然后我更改了相对网址中的所有网址(或使用新方案)

  • 第三个问题是浏览器自动处理服务器端口80和443,忽略它们,但现在已经停止(可能是因为“不是http位置”)。在我的服务器代码中我必须处理这个问题。

写下这几行我承认这似乎是一个很容易解决的问题,但我确保找到一个解决方法,如何解决它并与无限量的代码集成一直很困难。解决方案的每一步都对应着一个新问题。


use*_*377 6

有很多方法可以实现拦截器请求。

  1. 设置本地代理,使用 WKNavigationDelegate

    -[ViewController webView:decidePolicyForNavigationAction:decisionHandler:]
    
    Run Code Online (Sandbox Code Playgroud)

    加载新请求并转发到本地服务器,在本地服务器端你可以做一些事情(例如缓存)。

  2. 私有 API。使用 WKBrowsingContextController 和自定义 URLProtocol

    Class cls = NSClassFromString(@"WKBrowsingContextController");
    SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:");
    if ([(id)cls respondsToSelector:sel]) {
        // ? http ? https ???? NSURLProtocol ??
        [(id)cls performSelector:sel withObject:@"http"];
        [(id)cls performSelector:sel withObject:@"https"];
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用 KVO 获取系统 http/https 处理程序。(ios 11, *)

    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    URLSchemeHandler *schemeHandler = [[URLSchemeHandler alloc] init];
    [configuration setURLSchemeHandler:schemeHandler forURLScheme:@"test"];
    NSMutableDictionary *handlers = [configuration valueForKey:@"_urlSchemeHandlers"];
    handlers[@"http"] = schemeHandler;
    handlers[@"https"] = schemeHandler;
    
    Run Code Online (Sandbox Code Playgroud)

    您可能需要处理 CORS 和要剥离的帖子正文的所有三种方式,您可以覆盖更改浏览器的选项请求( Preflighted_requests),您可以自定义 http 标头来替换要删除的帖子正文的 http 正文。

  • 3/ 自 macOS 10.14(也可能是 iOS 12)起不再工作,因为 WKWebViewConfiguration 不在 ivar 中存储 url 方案处理程序。一切都在较低(核心 webkit、C++)级别处理。这太糟糕了 :) (2认同)

Kum*_*ddy 5

在 iOS 11 中,WKWebView 提出了名为WKURLSchemeHandler 的自定义方案处理程序,您可以使用它来拦截自定义事件。有关更多信息,请查看此项目。 https://github.com/BKRApps/KRWebView

  • 我们无法使用 WKURLSchemeHandler 处理 https 和 http。 (3认同)

Mat*_*ley 5

您可以在iOS 8.0以后的WKWebView上拦截请求,decidePolicyFor: navigationAction:方法是实现WKNavigationDelegate

 func webView(_ webView: WKWebView, decidePolicyFor 
       navigationAction: WKNavigationAction, 
       decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {

    //link to intercept www.example.com

    // navigation types: linkActivated, formSubmitted, 
    //                   backForward, reload, formResubmitted, other

    if navigationAction.navigationType == .linkActivated {
        if webView.url!.absoluteString == "http://www.example.com" {
            //do stuff

            //this tells the webview to cancel the request
            decisionHandler(.cancel)
            return
        }
    }

    //this tells the webview to allow the request
    decisionHandler(.allow)

}
Run Code Online (Sandbox Code Playgroud)

  • 不要使用 webView.url!.absoluteString 而是使用 navigationAction.request.url!.absoluteString (3认同)