NSURL, Trailing Slashes, and OAuth

Here’s a surprisingly important note from the documentation for the NSURL class’ path method:

Return Value

The path of the URL, unescaped with the stringByReplacingPercentEscapesUsingEncoding: method. If the receiver does not conform to RFC 1808, returns nil. If this URL is a file URL (as determined with isFileURL), the return value is suitable for input into methods of NSFileManager or NSPathUtilities. If the path has a trailing slash it is stripped.

Trailing Slashes

Trailing slashes in URLs are sort of funny things; whether URLs should include them or not is a matter of some debate, determined in practice by the conventions of the framework used to implement the server at the endpoint of the URL. For instance, Django strongly suggests (although it doesn’t really require, due to all those regexes) that all your URLs end with trailing slashes.

Example

Let’s say you’re dealing with URLs that include trailing slashes. And let’s say you use NSURLs to reach them, with something like this:

// Set up request ...
NSURL* url = [NSURL URLWithString:@"http://www.example.com/foo/bar/baz/"]
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url
						       cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
						   timeoutInterval:30];
request.HTTPMethod = @"POST";
	
// Set up delegate
MyNSURLConnectionDelegate* delegate = … set up an appropriate object …
	
// Create and start request
NSURLConnection* conn = [[[NSURLConnection alloc] initWithRequest:request
							 delegate:delegate] autorelease];
[conn start];

This will produce an HTTP request on the wire that looks something like this:

POST /foo/bar/baz/ HTTP/1.1
Host: www.example.com

On the other hand, url.path will return /foo/bar/baz. The path returned by url.path is not the same as the path sent over the wire.

Signing

“So what?”, you might ask. Well, the less-important point here is that /foo/bar/baz and /foo/bar/baz/ are not the same thing, and don’t (in principle) refer to the same object. (In practice, they’re often hacked to be synonyms on the server-side, but that’s not an assumption that a client should really be making.) The more important point is that if you’re signing your request (with, e.g., OAuth), then you need to know the exact path sent over the wire.

The slash-stripping behavior of path hides the precise path sent over the wire. If you’re handed an NSMutableURLRequest and asked to sign it (by, e.g., appending an OAuth authorization header) you can’t use the path method to construct the signature without some other information that specifies whether or not the path on the wire ends with a slash.

FWIW, absoluteString does not strip trailing slashes. This is helpful, but complicated by the fact that other parts of the URL (e.g., the query string) follow the path; a trailing slash won’t necessarily be the last character in a URL’s absoluteString.

This is all a little inconvenient.

Share and Enjoy:
  • Twitter
  • Facebook
  • Digg
  • Reddit
  • HackerNews
  • del.icio.us
  • Google Bookmarks
  • Slashdot
This entry was posted in iPhone, Python, Web stuff. Bookmark the permalink.

Comments are closed.