Friday, September 18, 2009

Amazon Product Advertising API signature urlencoding in python

As of August 15, 2009, Amazon product advertising API users are required to sign their REST requests. That article points out that you must URL encode the parameters using RFC 3986, and then helpfully points out that existing URL encoders do it wrong! They then give fixed-up examples for Java and Perl. This post gives the Python version. Here is the magic so you can leave if you have to:
  encoded_char = urllib.quote(char, safe='~')


Now let's check it.

First, let's use their Perl to generate "golden" text to check against. It's important to name the script foo.pl to respect our ancestors.
$ cat foo.pl
#!/usr/bin/perl

use URI;

for $idx ( 0 .. 255 ) {
print "$idx ", URI::Escape::uri_escape(chr($idx), "^A-Za-z0-9\-_.~" ), "\n";
}
Make the file 'golden.txt':
$ ./foo.pl > golden.txt
Now here's the Python:
$ cat foo.py
#!/usr/bin/python

import urllib

for idx in range(256):
print "%d %s" % (idx, urllib.quote(chr(idx), safe='~'))
Make the test file:
$ ./foo.py > python-test.txt
Test:
$ diff golden.txt python-test.txt
$
Good to go! If you try without the safe parameter, you'll see it doesn't encode '/' and does encode '~', which is what gave me the idea to try safe='~'.

Now go forth and prosper. If I work up the energy, I'll post a larger Amazon example in context.