Archive for July, 2008

Fun with decorators on the Google AppEngine

Tuesday, July 22nd, 2008

Well I thought I’d give writing for the Google AppEngine a try and have found it a delightful platform to work with. Easy deployment, easy scalability (the DataStore non-RDBMS is a bit harder to get your mind around), and a squeaky clean WebOb-based WSGI minimalist framework called WebApp. Anyways, in developing a simple REST service, I ran across a great place to use Python Decorators. I needed to restrict access to a specific REST method based on IP Address so I wrote the following decorator:

1
2
3
4
5
6
7
8
9
def bind_ip(ips):
    def _dec(handler):
        def _check_ip(self, *args, **kwargs):            
            if self.request.remote_addr in ips:
                return handler(self, *args, **kwargs)
            else:
                  self.error(403)
        return _check_ip
    return _dec

The decorator returns a closure which only calls the method it encapsulates if the IP address of the client is specifically allowed. Notice the @bind_ip on line 11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import wsgiref.handlers
from google.appengine.ext import webapp
from util import bind_ip
 
allowed_ips = set([
    '127.0.0.1',
    'ip.of.rest.client'
    ])
 
class SecretHandler(webapp.RequestHandler):
  @bind_ip(allowed_ips)
  def get(self, secret):
     """ Do something Secret """
     self.response.out.write (secret)
 
def main():
  application = webapp.WSGIApplication([
          (r'/secret/(.*)', SecretHandler)
      ])
  wsgiref.handlers.CGIHandler().run(application)
 
if __name__ == '__main__':
  main()

Decorators are a simple way to easily annotate how functions should be called, and can be used for Authentication, Data Validation or however else you’d like to use them.