Want to access the Flickr API with Javascript? So proxy it on Google AppEngine.

The Flickr API is one of my favorite APIs. It’s consistent, coherent, and well documented. It’s far from perfect, but it’s a shining example of many things that can go right in designing an API.

Okay, so you want to access Flickr’s API with javascript. But you can’t because browsers have this retarded cross domain policy that prevents fetching javascript from abritrary places on the internet. Boo.

The solution is to simply circumvent this ineffectual browser policy by proxying Flickr’s API (with Google AppEngine, no less).  The result we want is this: your javascript, which is served from AppEngine, just calls a method on its originating server which in turn calls Flickr’s API.

from google.appengine.ext import webapp
from google.appengine.api import urlfetch
 
class FlickrProxyHandler(webapp.RequestHandler):
  BASE_URL = 'http://api.flickr.com/services/rest/?'
 
  # flickr.txt has your api key and secret key
  KEY, SECRET = file('flickr.txt').read().split()
 
  def get(self, http_method = None):
    url = self.BASE_URL + self.request.query_string
    response = urlfetch.fetch(url, None, http_method or urlfetch.GET)
    # TODO set headers properly
    self.response.set_status(response.status_code)
    self.response.headers = response.headers # TODO: is this right?
    self.response.out.write(response.content)
 
  def put(self):
    # TODO not implemented.  just send back some headers.
    self.response.headers.add_header('Allow', urlfetch.GET)
    self.response.headers.add_header('Allow', urlfetch.POST)
    self.response.set_status(405)
 
  def post(self):
    self.get(urlfetch.POST) # well, that was easy
 
  def delete(self):
    # TODO not implemented.  just send back some headers.
    self.response.headers.add_header('Allow', urlfetch.GET)
    self.response.headers.add_header('Allow', urlfetch.POST)
    self.response.set_status(405)

Be sure to set up main.py to properly route requests:

def main():
  application = webapp.WSGIApplication([
    # http://whatever/flickr/rest/ is your new Flickr API endpoint!
    (r'^/flickr/rest/', FlickrProxyHandler),
  ], debug=False)
  wsgiref.handlers.CGIHandler().run(application)

So, that’s it. You’ve proxied the Flickr API on AppEngine. You are amazing. Now, when you serve javascript from your AppEngine app, it can call “/flickr/rest” under the same domain to make Flickr API calls. Go build stuff atop it. More on that part later.

I wrote this six or seven months ago, but am just now getting around to posting it. Oops. It’s also probably incomplete. Let me know if it’s lacking, yeah?


About this entry