Bogdan Laukhin Bogdan Laukhin - 4 months ago 91
iOS Question

How to get server response code for each request in WebView

I have authorization logic managed via WebView:


  • user click on login button in app

  • I open WebView with loading login webpage (opened by url address)

  • user provide their login and password > click on login button on page

  • next page is opened in WebView - authorize access confirmation page

  • user has to click on authorize access button on webpage

  • after this redirect_uri URL will be tried to be opened in WebView

  • I catch this redirect_uri in request and close WebView



I inspect all requests (in order to catch redirect_uri) in WebView delegate method
shouldStartLoadWithRequest:
.

Question: how can I manage server response for each request for page opened in WebView?

The point is that we have some problems with auth server and time to time it shows error pages. So I want to catch such pages and close WebView for such cases.

Answer

found the solution via WKWebView. I connected it the same way as UIWebView worked in my project.

And then I actually use 2 methods from WKNavigationDelegate protocol:

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

and

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

Example of code:

first method is to check whether current request is actually our redirect_uri that we should handle:

- (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);
    }
}

second method is to analyse response from server, and here we can verify the status code in order to handle any errors

- (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);
    }
}
Comments