Back in February I started work on integrating Yahoo's FireEagle location service into Geomium and I ran into a problems with Python 2.5. Using Steve Marshall's Python library the included test.py script was working perfectly with Python2.6, but when running with Python2.5 I'd get back an "Invalid OAuth signature error".
I posted the problem to the OAuth user group but didn't get any response. I got in touch with Yahoo. After quite a bit of back and forth we finally figured out the problem, which I'm posting here to try and save others from months of frustration!
The Yahoo guys noticed that with Python2.5 the HTTP host header was being sent through as as "fireeagle.yahooapis.com:443", whereas 2.6 sends "fireeagle.yahooapis.com". The inclusion of the port results in an invalid OAuth signature, because the signature is generated assuming the port isn't included. I dug into the Python2.5 httplib code and came across this:
813 if self.port == HTTP_PORT:
814 self.putheader('Host', host_enc)
815 else:
816 self.putheader('Host', "%s:%s" % (host_enc, self.port))
In Python 2.6 the comparison on line 813 is done with self.default_port instead of HTTP_PORT, which prevents the port from being added with HTTPS requests. I noticed that later on in the code that if you pass in your own host header it prevents one being created for you:
875 def _send_request(self, method, url, body, headers):
876 # honour explicitly requested Host: and Accept-Encoding headers
877 header_names = dict.fromkeys([k.lower() for k in headers])
878 skips = {}
879 if 'host' in header_names:
880 skips['skip_host'] = 1
So the fix turns out to be really simple - explicitly set the http header. That's exactly what I've done in my fork of the fireeagle library (see the fix). I've also sent a push request, so hopefully this fix will make it back into the original library. Thanks to Arnab Nandi and Anand S from Yahoo for helping to debug things their end.