iOS : How to do proper URL encoding?
Asked Answered
A

10

28

I'm unable to open a URL into UIWebView so I've seached & found that I need to encode URL, so I tried to encode it but, I've facing problem in URL encoding : My URL is http://somedomain.com/data/Témp%20Page%20-%20Open.html (It's not real URL).

I'm concerned with %20 that I tried to replace using stringByReplacingOccuranceOfString:@"" withString:@"" , it give me the URL I wanted like http://somedomain.com/data/Témp Page - Open.html However its not opening in UIWebView but amazingly it opens in Safari & FireFox perfect. Even I open unencoded URL its automatically converts and open the page I'm looking for.

I've google for URL encoding & it points me to different results I already checked but no results help me out!! I tried different functions answers in different URL encoding question but it just changed all special characters and make my URL like, http%3A%2F%2Fsomedomain.com%2Fdata%2FT... which can't open in UIWebView and even in any browser.

It gives the following Error Log in UIWebView delegate

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { }

Error Code : 101 & Description : Error Domain=WebKitErrorDomain Code=101 "The operation couldn’t be completed. (WebKitErrorDomain error 101.)" UserInfo=0x6e4cf60 {}

Arredondo answered 29/9, 2012 at 11:40 Comment(6)
The URL looks like it is in URL encoded format already except for the é-character which should probably be encoded as %c3%a9. Why it works in Safari etc could be because desktop browser is quite liberal with invalid URLs and will try to fix them for you i.e. assuming the é should be URL encoded.Jamieson
@MattiasWadman, If paste the same URL into browser, it'll convert %20 with space and not encode é, So it has no problem with it!Arredondo
What you see in the URL bar is not always that same that will actually be sent to the server, different browser present the URL in different ways. Try this httpdump.com/texis/browserinfo/Témp.html and note that "Request URI" is "/texis/browserinfo/T%C3%A9mp.html".Jamieson
Where does the URL come from? It seems to be only partially escaped, which is - frankly speaking - just garbage input, and very difficult to work with. If you don't specify a real URL for some tests, it's even more difficult to find an answer here.Armadillo
@Eiko, Well, the URL I posted here, I only changed its domain name (to somedomain.com) other than its exactly the same as real URL. However with strange behavior it can open with browsers in my MAC PC, also I just checked it on Android (In built browser) & iPhone phone (safari browser) and its working fine. It converts URL and open the page. URL looks like http://somedomain.com/data/mobile/index.html. Don't know what's the problem with UIWebView.Arredondo
@Arredondo The problem is that it's just not a valid URL. It's halfway encoded. The é needs to be escaped, but the spaces already are - and escaping again will just encode these % as well. Browsers probably did a lot of tweaking to get most of the URLs right that people throw at them. Of course you can now start guessing and tweaking that URL, but really, where do you get that input from?Armadillo
J
15

I did some tests and I think the problem is not really with the UIWebView but instead that NSURL won't accept the URL because of the é in "Témp" is not encoded properly. This will cause +[NSURLRequest requestWithURL:] and -[NSURL URLWithString:] to return nil as the string contains a malformed URL. I guess that you then end up using a nil request with -[UIViewWeb loadRequest:] which is no good.

Example:

NSLog(@"URL with é: %@", [NSURL URLWithString:@"http://host/Témp"]);
NSLog(@"URL with encoded é: %@", [NSURL URLWithString:@"http://host/T%C3%A9mp"]);

Output:

2012-10-02 12:02:56.366 test[73164:c07] URL with é: (null)
2012-10-02 12:02:56.368 test[73164:c07] URL with encoded é: http://host/T%C3%A9mp

If you really really want to borrow the graceful handling of malformed URLs that WebKit has and don't want to implement it yourself you can do something like this but it is very ugly:

UIWebView *webView = [[[UIWebView alloc]
                       initWithFrame:self.view.frame]
                      autorelease];

NSString *url = @"http://www.httpdump.com/texis/browserinfo/Témp.html";

[webView loadHTMLString:[NSString stringWithFormat:
                         @"<script>window.location=%@;</script>",
                         [[[NSString alloc]
                           initWithData:[NSJSONSerialization
                                         dataWithJSONObject:url
                                         options:NSJSONReadingAllowFragments
                                         error:NULL]
                           encoding:NSUTF8StringEncoding]
                          autorelease]]
                baseURL:nil];
Jamieson answered 2/10, 2012 at 10:3 Comment(6)
Hola! Well described answer! :)Arredondo
Thanks. Did it solve your problem? I updated my answer with a hack for using the graceful malformed URL handling that WebKit has.Jamieson
You've did a great research! It solved my problem. I learn something new! :)Arredondo
Hi if you have a nsstring and you want to convert it into a proper URL encoding then use the below method of NSString class. urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];Ru
@AbdulYasin but be careful as different parts of an URL should be encoded differently. from the documentation about that method "It may be difficult to use this function to "clean up" unescaped or partially escaped URL strings where sequences are unpredictable."Jamieson
What every web developer must know about URL encoding is a very good but a bit lengthy text how URL encoding work.Jamieson
M
16

The answer @Dhaval Vaishnani provided is only partially correct. This method treats the ?, = and & characters as not to be encoded, since they're valid in an URL. Thus, to encode an arbitrary string to be safely used as a part of an URL, you can't use this method. Instead you have to fall back to using CoreFoundation and CFURLRef:

NSString *unsafeString = @"this &string= confuses ? the InTeRwEbZ";
CFStringRef safeString = CFURLCreateStringByAddingPercentEscapes (
    NULL,
    (CFStringRef)unsafeString,
    NULL,
    CFSTR("/%&=?$#+-~@<>|\\*,.()[]{}^!"),
    kCFStringEncodingUTF8
);

Don't forget to dispose of the ownership of the resulting string using CFRelease(safeString);.

Also, it seems that despite the title, OP is looking for decoding and not encoding a string. CFURLRef has another, similar function call to be used for that:

NSString *escapedString = @"%32%65BCDEFGH";
CFStringRef unescapedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding (
    NULL,
    (CFStringRef)escapedString,
    CFSTR(""),
    kCFStringEncodingUTF8
);

Again, don't forget proper memory management.

Madame answered 2/10, 2012 at 6:32 Comment(1)
I always used this approach for encoding. But with this approach, i am facing the issue with this simple URL: URL: google.com/search?q=stackoverflow Encoded URL: google.com/search?q%3Dstackoverflow Its redirecting to google.com not to expected page. To find the difference please try it in iphone safari and web browser.Literalism
J
15

I did some tests and I think the problem is not really with the UIWebView but instead that NSURL won't accept the URL because of the é in "Témp" is not encoded properly. This will cause +[NSURLRequest requestWithURL:] and -[NSURL URLWithString:] to return nil as the string contains a malformed URL. I guess that you then end up using a nil request with -[UIViewWeb loadRequest:] which is no good.

Example:

NSLog(@"URL with é: %@", [NSURL URLWithString:@"http://host/Témp"]);
NSLog(@"URL with encoded é: %@", [NSURL URLWithString:@"http://host/T%C3%A9mp"]);

Output:

2012-10-02 12:02:56.366 test[73164:c07] URL with é: (null)
2012-10-02 12:02:56.368 test[73164:c07] URL with encoded é: http://host/T%C3%A9mp

If you really really want to borrow the graceful handling of malformed URLs that WebKit has and don't want to implement it yourself you can do something like this but it is very ugly:

UIWebView *webView = [[[UIWebView alloc]
                       initWithFrame:self.view.frame]
                      autorelease];

NSString *url = @"http://www.httpdump.com/texis/browserinfo/Témp.html";

[webView loadHTMLString:[NSString stringWithFormat:
                         @"<script>window.location=%@;</script>",
                         [[[NSString alloc]
                           initWithData:[NSJSONSerialization
                                         dataWithJSONObject:url
                                         options:NSJSONReadingAllowFragments
                                         error:NULL]
                           encoding:NSUTF8StringEncoding]
                          autorelease]]
                baseURL:nil];
Jamieson answered 2/10, 2012 at 10:3 Comment(6)
Hola! Well described answer! :)Arredondo
Thanks. Did it solve your problem? I updated my answer with a hack for using the graceful malformed URL handling that WebKit has.Jamieson
You've did a great research! It solved my problem. I learn something new! :)Arredondo
Hi if you have a nsstring and you want to convert it into a proper URL encoding then use the below method of NSString class. urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];Ru
@AbdulYasin but be careful as different parts of an URL should be encoded differently. from the documentation about that method "It may be difficult to use this function to "clean up" unescaped or partially escaped URL strings where sequences are unpredictable."Jamieson
What every web developer must know about URL encoding is a very good but a bit lengthy text how URL encoding work.Jamieson
U
13

The most straightforward way is to use:

NSString *encodedString = [rawString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

iDhaval was close, but he was doing it the other way around (decoding instead of encoding).

Anand's way would work, but you'll most likely have to replace more characters than spaces and new lines. See the reference here: http://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters

Hope that helps.

Unmanned answered 13/8, 2013 at 19:39 Comment(0)
C
6

It's very simple to encode the URL in iPhone. It is as following

NSString* strURL = @"http://somedomain.com/data/Témp Page - Open.html";

NSURL* url = [NSURL URLWithString:[strURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

It's a perfect way to encode the URL, I am using it and it's perfectly work with me.

Hope it will help you!!!

Chico answered 29/9, 2012 at 11:47 Comment(4)
Dhaval, Thanks for quick reply! I've tried the same before but there's no result, however I've also tried your code, it gives (null) when I NSLog url. And url is http://somedomain.com/data/Témp%20Page%20-%20Open.htmlArredondo
Note that +[NSString stringByReplacingPercentEscapesUsingEncoding:] behaves a bit strange, see this blog post madebymany.com/blog/url-encoding-an-nsstring-on-iosJamieson
@Dhaval Vaishnani Also, the message send you're using does not encode a non-escaped URL string, but rather decodes an already percent-escaped URL string.Madame
this replaces percent escaped sequences, rather than creating them. the process of percent encoding a URL is substituting reserved characters with percent-encodings of the form %3a e.g. This method replaces those with the corresponding reserved character. so as @Madame has this, this is a decode function.Romeliaromelle
A
4

This may useful to someone who's reach to this question for URL encoding, as my question likely different which has been solved and accepted, this is the way I used to do encoding,

-(NSString *)encodeURL:(NSString *)urlString
{
    CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)urlString, NULL, CFSTR("!*'();:@&=+@,/?#[]"), kCFStringEncodingUTF8);
    return (NSString *)CFBridgingRelease(newString);
}
Arredondo answered 6/5, 2013 at 9:8 Comment(0)
G
3

You can try this

NSString *url = @"http://www.abc.com/param=Hi how are you";

NSString* encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:
 NSASCIIStringEncoding];
Greengage answered 10/12, 2013 at 13:20 Comment(0)
C
3

I think this will work for you

[strUrl stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]

the Native method for URL Encoding.

Crawley answered 19/7, 2014 at 9:57 Comment(0)
A
2

Swift 4.x

let originalString = "https://www.somedomain.com/folder/some cool file.jpg"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedString!)
Arredondo answered 16/11, 2017 at 5:1 Comment(0)
E
0

You probably need to break the URL down into it's constituent parts and then URL encode the host and path but not the scheme. Then put it back together again.

Create an NSURL with the string and then use the methods on it such as host, scheme, path, query, etc to pull it apart. Then use CFURLCreateStringByAddingPercentEscapes to encode the parts and then you can put them back together again into a new NSURL.

Edgington answered 2/10, 2012 at 8:15 Comment(0)
I
-1

can you please Try this out.

    //yourURL contains your Encoded URL
    yourURL = [yourURL stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
    yourURL = [yourURL stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    NSLog(@"Keyword:%@ is this",yourURL);

I am not sure,but I have solved using this in my case. Hope this will solve yours.

Indelicate answered 2/10, 2012 at 6:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.