Specifying HTTP referer in embedded UIWebView
Asked Answered
S

2

13

In my app, I allow the user to open up an external page in an embedded UIWebView. Is it possible for me to set the referer header that's sent with that request? I'd like for my app to get the 'cred' when the user opens up these external pages.

Sharpie answered 27/10, 2011 at 8:17 Comment(0)
M
20

Set the referer using - setValue:forHTTPHeaderField:

NSMutableURLRequest* request = ...;
[request setValue:@"https://myapp.com" forHTTPHeaderField: @"Referer"];

But note that according to the HTTP RFC you shouldn't, because your app is not addressable using a URI:

The Referer field MUST NOT be sent if the Request-URI was obtained from a source that does not have its own URI, such as input from the user keyboard.

... unless you are using a custom protocol binded to your app (myapp://blah.com/blah).

You can create one and call loadRequest: manually or intercepting a normal request made by the user.

- (BOOL) webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType) navigationType 
{
    NSDictionary *headers = [request allHTTPHeaderFields];
    BOOL hasReferer = [headers objectForKey:@"Referer"]!=nil;
    if (hasReferer) {
        // .. is this my referer?
        return YES;
    } else {
        // relaunch with a modified request
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                NSURL *url = [request URL];
                NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
                [request setHTTPMethod:@"GET"];
                [request setValue:@"https://whatever.com" forHTTPHeaderField: @"Referer"];
                [self.webView loadRequest:request];
            });
        });
        return NO;
    }
}
Mainsheet answered 27/10, 2011 at 8:32 Comment(7)
Thanks for the note from the RFC. I wasn't aware of that. The screen that my user is on when they open up the external link in the browser has its own URI, so I don't that applies to me.Sharpie
Where do I get the NSMutableURLRequest instance from? The UIWebViewDelegate doesn't give me the Mutable version. I found some references saying I could reliably cast it, but I'm wondering if there's a nicer way.Sharpie
I don't know if that is kosher, but you can intercept and relaunch the request.Mainsheet
Thanks for the answer. I've updated the question to only ask about sending headers with a UIWebView and will accept your answer. I'll open up another question for sending headers with Mobile Safari.Sharpie
It turns out that I can reliably cast the request from UIWebViewDelegate to a NSMutableURLRequest. The request replacement solution suggested above was breaking iframes in the page by re-opening them in the full browser.Sharpie
@scompt.com your suggestion is not working for me. Can you provide lines of code?Immunogenetics
@scompt.com It seems not all requests are actually NSMutableURLRequests (I have not found a pattern yet), so the cast does not work reliablyPreterition
B
0

I haven't used this myself, but it looks like NSURLProtocol is the approved way to intercept and modify URL requests. Here's a tutorial: http://www.raywenderlich.com/59982/nsurlprotocol-tutorial

I'm using your solution of casting the request to NSMutableURLRequest, but since it's not documented that this is a mutable request, there's some risk that Apple might use an immutable object in the future.

Byington answered 6/11, 2014 at 16:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.