views:

8006

answers:

11

I have a business need to be able to customize the UserAgent for an embedded UIWebView. (For instnace, I'd like the server to respond differently if, say, a user is using one version of the app versus another.)

Is it possible to customize the UserAgent in the existing iPhone SDK's UIWebView control the way it is, say, for an embedded IE browser in a Windows app?

A: 

I tried it uisng NSMutableURLRequest, but didn't work. Have you found a working solution?

+3  A: 

It should work with an NSMutableURLRequest as Kuso has written.

NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL: [NSURL urlWithString: @"http://www.google.com/"];
[urlRequest setValue: @"iPhone" forHTTPHeaderField: @"User-Agent"]; // Or any other User-Agent value.

You'll have to use NSURLConnection to get the responseData. Set the responseData to your UIWebView and the webView should render:

[webView loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL];
Dshutsi
A: 

It worked if I used "User_Agent"....underscore instead of a dash. However, could not make it work on link in webview.

A: 

Does anyone know where I can find the source of UIWebView?

UIWebView is an Apple proprietary class and is NOT open source. You have the API. That is all.
August
+3  A: 

Works for me:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)req navigationType:(UIWebViewNavigationType)navigationType {
    NSMutableURLRequest *request = (NSMutableURLRequest *)req;

    if ([request respondsToSelector:@selector(setValue:forHTTPHeaderField:)]) {
        [request setValue:[NSString stringWithFormat:@"%@ Safari/528.16", [request valueForHTTPHeaderField:@"User-Agent"]] forHTTPHeaderField:@"User_Agent"];
    }
    return YES; 
}

Note that you need to use @"User-Agent" to read the property, but @"User_Agent" to set it.

Also, for those wondering what string they should use to make the iPhone detect like Safari, the above doesn't always work, so I'd try using the default built-in to Safari 4 on the Mac: @"Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16"

My inspiration was the otherwise-useless rant found here: http://chaosinmotion.com/blog/?p=224 (and kuso's discovery of @"User_Agent" working. Yay.)

Louis St-Amour
One downside to this approach: If your webView contains custom urls (someapplication://) they will fail since you're always returning YES.
jpoz
+1  A: 

Hmm, various other posts on other blogs, e.g. http://www.iphonedevsdk.com/forum/iphone-sdk-development/8524-uiwebview-forcing-non-mobile-web-pages-possible.html [1] there may be some problems with trying to override the standard header values -- which is why attempts to set "User-Agent" fails, but using "User_Agent" works (i.e. since that isn't the standard header-name, with an underscore). Here's the quote from the above:

It does not seem to be possible to overwrite the User-Agent from the NSURLRequest, as it seems that this header gets written over when the request goes out. However, you are able to add custom defined header key/value pairs. These key/values would not show up in the normal server request logs, but they can be tapped, for instance, [by parsing them in your app-server/web-app stack].

Comments from the peanut gallery on this? Hmm, why shouldn't a mutable NSURLRequest allow us to in fact modify any header value we wanted? Thoughts? Thx...

-dk

sfjava
A: 

Taking everything this is how it was solved for me:

- (void)viewDidLoad {

NSString *urlAddress = @"http://www.amazon.com";

//Create a URL object.
NSURL *url = [NSURL URLWithString:urlAddress];

//URL Requst Object
NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:url];
[requestObj setValue:@"Foobar/1.0" forHTTPHeaderField:@"User_Agent"];


//Load the request in the UIWebView.
[webView loadRequest:requestObj];
}

Thanks Everyone.

Michael Robinson
Start a new question.
John Rudy
+1  A: 

Using @"User_Agent" simply causes a custom header to appear in the GET request.

User_agent: Foobar/1.0\r\n
User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7D11\r\n

The above is what appears in the dissected HTTP packet, essentially confirming what Sfjava was quoting from that forum. It's interesting to note that "User_Agent" gets turned into "User_agent."

dodeskjeggen
A: 

using @"User_Agent" in shouldStartLoadWithRequest doesn't really solve the problem. i tried loading http://www.cnn.com and i am taken to mobile version of cnn ie m.cnn.com

Using NSUrlConnection has a problem that "back/forward" history is not maintained by uiwebview.

Has anybody cracked this problem ???

Naveen
+1  A: 

This solution seems to have been seen as a pretty clever way to do it

http://www.icab.de/blog/2010/04/07/changing-the-headers-for-uiwebkit-http-requests/

It uses Method Swizzling and you can learn more about it on the CocoaDev page

Give it a look !

Open SEO
+1  A: 

Actually adding any header field to the NSURLRequest argument in shouldStartLoadWithRequest seems to work, because the request responds to setValue:ForHTTPHeaderField - but it doesn't actually work - the request is sent out without the header.

So I used this workaround in shouldStartLoadWithRequest which just copies the given request to a new mutable request, and re-loads it. This does in fact modify the header which is sent out.

if ( [request valueForHTTPHeaderField:@"MyUserAgent"] == nil )
{
    NSMutableURLRequest *modRequest = [request mutableCopyWithZone:NULL];
    [modRequest setValue:@"myagent" forHTTPHeaderField:@"MyUserAgent"];
    [webViewArgument loadRequest:modRequest];
    return NO;
}

Unfortunately, this still doesn't allow overriding the user-agent http header, which is apparently overwritten by Apple. I guess for overriding it you would have to manage a NSURLConnection by yourself.

Danra