1"""HTTP servlets""" 2 3from time import gmtime, strftime 4 5from Servlet import Servlet 6 7 8class HTTPServlet(Servlet): 9 """A HTTP servlet. 10 11 HTTPServlet implements the respond() method to invoke methods such as 12 respondToGet() and respondToPut() depending on the type of HTTP request. 13 Example HTTP request methods are GET, POST, HEAD, etc. 14 Subclasses implement HTTP method FOO in the Python method respondToFoo. 15 Unsupported methods return a "501 Not Implemented" status. 16 17 Note that HTTPServlet inherits awake() and respond() methods from 18 Servlet and that subclasses may make use of these. 19 20 See also: Servlet 21 22 FUTURE 23 * Document methods (take hints from Java HTTPServlet documentation) 24 """ 25 26 27 ## Init ## 28 29 def __init__(self): 30 Servlet.__init__(self) 31 self._methodForRequestType = {} # a cache; see respond() 32 33 34 ## Transactions ## 35 36 def respond(self, trans): 37 """Respond to a request. 38 39 Invokes the appropriate respondToSomething() method depending on the 40 type of request (e.g., GET, POST, PUT, ...). 41 """ 42 request = trans.request() 43 httpMethodName = request.method() 44 # For GET and HEAD, handle the HTTP If-Modified-Since header: 45 # if the object's last modified time is the same 46 # as the IMS header, we're done. 47 if httpMethodName in ('GET', 'HEAD'): 48 lm = self.lastModified(trans) 49 if lm: 50 lm = strftime('%a, %d %b %Y %H:%M:%S GMT', gmtime(lm)) 51 trans.response().setHeader('Last-Modified', lm) 52 ims = request.environ( 53 ).get('HTTP_IF_MODIFIED_SINCE') or request.environ( 54 ).get('IF_MODIFIED_SINCE') 55 if ims and ims.split(';', 1)[0] == lm: 56 trans.response().setStatus(304, 'Not Modified') 57 return 58 method = self._methodForRequestType.get(httpMethodName) 59 if not method: 60 methName = 'respondTo' + httpMethodName.capitalize() 61 method = getattr(self, methName, self.notImplemented) 62 self._methodForRequestType[httpMethodName] = method 63 method(trans) 64 65 @staticmethod 66 def notImplemented(trans): 67 trans.response().setStatus(501, 'Not Implemented') 68 69 @staticmethod 70 def lastModified(trans): 71 """Get time of last modification. 72 73 Return this object's Last-Modified time (as a float), 74 or None (meaning don't know or not applicable). 75 """ 76 return None 77 78 def respondToHead(self, trans): 79 """Respond to a HEAD request. 80 81 A correct but inefficient implementation. 82 """ 83 res = trans.response() 84 w = res.write 85 res.write = lambda *args: None 86 self.respondToGet(trans) 87 res.write = w 88