views:

269

answers:

3

When getting a URL for something in an Amazon S3 bucket it can append a signature to the end to confirm that the user has permission to view the object and the URL looks like so:

https://mybucket.amazonaws.com/mykey?AWSAccessKeyId=myaccesskey& Expires=1235241261&Signature=t5vFBWXaN0DvVaWfck9n2%2fmTzOU%3d

These URLs were coming back from my S3 library as string objects and I passed them around like that. Recently I ran my code through FxCop and it recommended that I use the Uri class to pass around URLs. I took FxCops advice and changed my URL string properties to Uri properties. Everything seemed to be working fine until much later I noticed that not all the objects were being fetched back successfully.

The reason for the problem was that the Uri class ToString() function would return a slightly different version of the URL:

https://mybucket.amazonaws.com/mykey?AWSAccessKeyId=myaccesskey& Expires=1235241261&Signature=t5vFBWXaN0DvVaWfck9n2/mTzOU=

My solution was to use the OriginalString property of the Uri class. But something feels wrong about this and I have two questions,

  • Should I have taken FxCops advice and used the Uri class?
  • Should Amazon realize that URLs may pass through many hands and not depend on them coming back exactly the same?

For using the .Net Uri class I can be sure that my URLs are always valid but it seems to make more subtle mistakes possible.

+4  A: 

It's not wrong of FxCop to suggest using the Uri class instead of a raw string. Using the Uri class provides type safety and several useful parsing methods.

System.Uri does do some encoding and decoding of the query string automatically. It sounds like you weren't expecting that behavior, and it caused some problems. I'd recommend checking out what characters should be escaped in URIs according to the HTTP standard.

Here's a wikipedia article that describes percent-encoding or URL-encoding in more detail.

Your specific issue is that %2f is an escape sequence in a URL for the forward slash / character. The System.Uri class decoded that sequence for you.

System.Uri isn't perfect, of course. Rick Strahl recently talked about different options for Uri string encoding on his blog.

dthrasher
In this case it was amazon that generated the URL should they been prepared for a slightly different encoding?
tpower
I think Amazon is doing the right thing by encoding a forward slash as "%2f" in their query string. It would be nice if they'd come up with a URI design that avoided the need for escape sequences at all, but sometimes it's not possible.
dthrasher
OK, do you mean that I should URL encode my uri before using it?
tpower
Yes. Before you use it in a browser address bar or in HTML, you should properly encode the string. I think you'll want to use the Uri.EscapeUriString() method to do it, but check the documentation first.
dthrasher
+1  A: 

What library are you using to build the S3 URLs? I am having to do that in my project and am looking for some sample code or libraries.

Using ThreeSharp but you should ask this as a Question not an Answer.
tpower
+4  A: 

I agree with dthrasher. FxCop wasn't wrong. But what FxCop doesn't tell you is the pain you may experience you use System.Uri, especially with ASP.NET. I just wrote up an article that will help you get better prepared to use this class, which can be somewhat confusing:

http://www.pluralsight.com/community/blogs/keith/archive/2009/10/10/did-fxcop-tell-you-to-use-system-uri.aspx

Keith Brown - Pluralsight