Home > iOS Development > How to Detect and Handle HTTP Status Codes in UIWebViews

How to Detect and Handle HTTP Status Codes in UIWebViews

Imagine you have the following problem: You want to load a url in a UIWebView. But the resource at that url requires authentication, and if the user is not authenticated the web page responds with a “403 Not Authenticated” without showing any other instructions on how to login or where to go next etc. Ideally you’d want to redirect the user to a page where she can log in and continue to browse the url. The problem is UIWebView does not provide any properties or methods for inspecting HTTP status codes. One workaround is to intercept the UIWebView request loading process and check whether the user is authenticated or not by loading the same url using an NSURLConnection and inspecting the response, then you can behave accordingly.

In order to check the url, we implement this UIWebViewDelegate method:

- (BOOL)           webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
            navigationType:(UIWebViewNavigationType)navigationType

If session is not checked before, we prevent the request from loading by returning NO and start loading the same request using an NSURLConnection, otherwise we just return YES and the web view continues to load the request.

 
We inspect the response in NSURLConnection delegate method:

- (void) connection:(NSURLConnection *)connection
 didReceiveResponse:(NSURLResponse *)response

The response is actually an NSHTTPURLResponse instance and it provides a method for getting the HTTP status code “- (int) statusCode”. After learning whether or not the user is authenticated we cancel the connection since we don’t need the actual response data. If the user is authenticated we get a “200 OK” and start loading the initial url, otherwise we get a “403 Not Authenticated” and redirect the user to the login page instead of leaving her alone with the empty useless 403 page.

 
Demo project shows an example situation by trying to load a Google+ photo album url. Here I used this workaround for solving an authentication related problem but the idea is applicable to any problem where you need to know with what HTTP status code the server responds. It might be redirecting the web view to another url if your main url responds with a “503 Service Unavailable” or providing alternate content when the server responds with a “404 Not Found” and so on. You got the idea.

In the end, usability is important. Good usability and providing a nice user experience is not always about the visual design of the product/software. It’s also about the functional behaviour and consistency of the product. Think of an app that looks stunningly beautiful in design but does not work, will it make any sense? No, right? So please try not to leave your users alone with an empty 403 or 404 page, having no idea what to do / where to go next – unless your app itself is not a web browser.

 
Here is the github readonly url, git clone it to your local repo:

git://github.com/ardalahmet/UIWebViewHttpStatusCodeHandling.git

 
or download the Xcode project from github:
https://github.com/ardalahmet/UIWebViewHttpStatusCodeHandling/

 
Some screenshots from the demo app running on the iPhone simulator:

Screenshot 1

Screenshot 1

 

Screenshot 2

Screenshot 2

  1. August 22nd, 2011 at 18:39 | #1

    This free iPhone app may also come in handy as a pocket reference for looking up HTTP status codes: http://itunes.apple.com/us/app/http-codes/id301355875?mt=8

  2. J
    July 6th, 2012 at 18:07 | #2

    If I understand this code correctly, it is doing two requests for each url: one by the web view, and one by the url connection request. That would assume that all your urls are idempotent, and furthermore you don’t care about making double requests. IMHO, such an assumption seems to be naive to me.

  3. J
    July 6th, 2012 at 18:34 | #3

    @J

    To add on to what I said in the last comment, you can accomplish what you are seeking by doing all url requests with NSURLConnection, and when you get the response data back using didReceiveData and connectionDidFinishLoading, you can call the UIWebView’s loadData method. This will handle both http and html-meta/javascript redirects.

  4. July 6th, 2012 at 23:11 | #4

    Hi @J ,

    I applied this work-around at the time because I was using UIWebView here for just showing a single page to the user at the end of a photo album upload task. What you suggest can also be prefered as a solution, and should work just as fine I suppose.

    Cheers.

  5. September 8th, 2012 at 19:36 | #5

    Hi Ahmet,

    Your solution save my day (and my week too). But I have more doubts. I’m trying to handle the authorization request with “didReceiveAuthenticationChallenge” delegate method, since my servers works with NTLM and Kerberos authentication.

    It is possible with this solution? Can you help me?

    Thanks in advance and thanks a lot for this post.

  6. September 10th, 2012 at 08:10 | #6

    Hi @Fer ,

    You can use the same technique for handling the authentication in your NSURLConnection request. However, in order to actually load content into the UIWebView after authentication, you might need to load the response in NSURLConnection delegate methods and then display the response in UIWebView with

    [webView loadData:htmlResponse MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:[NSURL URLWithString:@""]];

    Hope this helps,
    Cheers.

  7. September 10th, 2012 at 11:53 | #7

    Ok, I did this and works perfectly (with any issues). The main issue is that if in the page loaded by loadData has embebed contents, the Authentication does not work for this embebed content.

    Thanks again!!

  8. Arsh
    March 1st, 2013 at 12:59 | #8

    Hi Ahmet, Nice tutorial, I need NTLM for a webview? Could you please help me out?

  1. No trackbacks yet.