如何在WebView中获取每个请求的服务器响应代码

时间:2016-04-13 11:39:02

标签: ios objective-c webview

我通过WebView管理授权逻辑:

  • 用户点击应用
  • 中的登录按钮
  • 我打开WebView并加载登录网页(由网址开启)
  • 用户提供他们的登录名和密码>点击页面上的登录按钮
  • 下一页在WebView中打开 - 授权访问确认页面
  • 用户必须点击网页上的授权访问按钮
  • 在尝试在WebView中打开此redirect_uri URL之后
  • 我在请求中捕获此redirect_uri并关闭WebView

我在WebView委托方法shouldStartLoadWithRequest:中检查所有请求(以捕获redirect_uri)。

问题:如何管理WebView中打开的每个页面请求的服务器响应?

关键是我们在auth服务器上遇到一些问题,并且不时显示错误页面。所以我想抓住这些页面并关闭WebView以获取此类案例。

3 个答案:

答案 0 :(得分:3)

通过WKWebView找到解决方案。 我以与UIWebView在我的项目中工作相同的方式连接它。

然后我实际使用了来自WKNavigationDelegate协议的两种方法:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler

代码示例:

第一种方法是检查当前请求是否实际上是我们应该处理的redirect_uri

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSLog(@"request: %@", navigationAction.request);

    // check whether this request should be stopped - if this is redirect_uri (like user is already authorized)
    if (...) {
        self.webView.navigationDelegate = nil;

        // do what is needed to send authorization data back
        self.completionBlock(...);

        // close current view controller
        [self dismissViewControllerAnimated:YES completion:nil];

        // stop executing current request
        decisionHandler(WKNavigationActionPolicyCancel);

    } else {
        // otherwise allow current request
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

第二种方法是分析来自服务器的响应,在这里我们可以验证状态代码以便处理任何错误

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;

    // filter the responses, in order to verify only the response from specific domain
    if ([[NSString stringWithFormat:[[response URL] absoluteString]] containsString:@"some.domain.com/"]) {

        NSInteger statusCode = [response statusCode];

        // check what is the status code
        if (statusCode == 200 ||
            statusCode == 301 ||
            statusCode == 302) {

            // allow response as everything is ok
            decisionHandler(WKNavigationResponsePolicyAllow);

        } else {
            // handle the error (e.g. any of 4xx or any others)

            self.webView.navigationDelegate = nil;

            // send needed info back
            self.completionBlock(...);

            // close current view controller
            [self dismissViewControllerAnimated:YES completion:nil];

            // stop current response
            decisionHandler(WKNavigationResponsePolicyCancel);
        }

    } else {
        // current response is not from our domain, so allow it
        decisionHandler(WKNavigationResponsePolicyAllow);
    }
}

答案 1 :(得分:0)

实施以下委托方法可能适合您。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSCachedURLResponse *urlResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request];
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) urlResponse.response;
    NSInteger statusCode = httpResponse.statusCode;
    NSLog(@"%@",statusCode);
}

答案 2 :(得分:0)

在 swift 中,您可以尝试将 URLResponse 转换为 HTTPURLResponse 以获取 statusCode 字段。

extension MyController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse,
                 decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
       
        if let httpResponse = navigationResponse.response as? HTTPURLResponse {
            let statusCode = httpResponse.statusCode
            //....
        }
        decisionHandler(.allow)
}

}