Package pyamf :: Package remoting :: Package gateway :: Module wsgi
[hide private]
[frames] | no frames]

Source Code for Module pyamf.remoting.gateway.wsgi

  1  # Copyright (c) 2007-2009 The PyAMF Project. 
  2  # See LICENSE.txt for details. 
  3   
  4  """ 
  5  WSGI server implementation. 
  6   
  7  The Python Web Server Gateway Interface (WSGI) is a simple and universal 
  8  interface between web servers and web applications or frameworks. 
  9   
 10  The WSGI interface has two sides: the "server" or "gateway" side, and the 
 11  "application" or "framework" side. The server side invokes a callable 
 12  object (usually a function or a method) that is provided by the application 
 13  side. Additionally WSGI provides middlewares; a WSGI middleware implements 
 14  both sides of the API, so that it can be inserted "between" a WSGI server 
 15  and a WSGI application -- the middleware will act as an application from 
 16  the server's point of view, and as a server from the application's point 
 17  of view. 
 18   
 19  @see: U{WSGI homepage (external)<http://wsgi.org>} 
 20  @see: U{PEP-333 (external)<http://www.python.org/peps/pep-0333.html>} 
 21   
 22  @since: 0.1.0 
 23  """ 
 24   
 25  import pyamf 
 26  from pyamf import remoting 
 27  from pyamf.remoting import gateway 
 28   
 29  __all__ = ['WSGIGateway'] 
 30   
 31   
32 -class WSGIGateway(gateway.BaseGateway):
33 """ 34 WSGI Remoting Gateway. 35 """ 36
37 - def getResponse(self, request, environ):
38 """ 39 Processes the AMF request, returning an AMF response. 40 41 @param request: The AMF Request. 42 @type request: L{Envelope<pyamf.remoting.Envelope>} 43 @rtype: L{Envelope<pyamf.remoting.Envelope>} 44 @return: The AMF Response. 45 """ 46 response = remoting.Envelope(request.amfVersion, request.clientType) 47 48 for name, message in request: 49 processor = self.getProcessor(message) 50 environ['pyamf.request'] = message 51 response[name] = processor(message, http_request=environ) 52 53 return response
54
55 - def badRequestMethod(self, environ, start_response):
56 """ 57 Return HTTP 400 Bad Request. 58 """ 59 response = "400 Bad Request\n\nTo access this PyAMF gateway you " \ 60 "must use POST requests (%s received)" % environ['REQUEST_METHOD'] 61 62 start_response('400 Bad Request', [ 63 ('Content-Type', 'text/plain'), 64 ('Content-Length', str(len(response))), 65 ('Server', gateway.SERVER_NAME), 66 ]) 67 68 return [response]
69
70 - def __call__(self, environ, start_response):
71 """ 72 @rtype: C{StringIO} 73 @return: File-like object. 74 """ 75 if environ['REQUEST_METHOD'] != 'POST': 76 return self.badRequestMethod(environ, start_response) 77 78 body = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) 79 stream = None 80 timezone_offset = self._get_timezone_offset() 81 82 # Decode the request 83 try: 84 request = remoting.decode(body, strict=self.strict, 85 logger=self.logger, timezone_offset=timezone_offset) 86 except (pyamf.DecodeError, IOError): 87 if self.logger: 88 self.logger.exception(gateway.format_exception()) 89 90 response = "400 Bad Request\n\nThe request body was unable to " \ 91 "be successfully decoded." 92 93 if self.debug: 94 response += "\n\nTraceback:\n\n%s" % gateway.format_exception() 95 96 start_response('400 Bad Request', [ 97 ('Content-Type', 'text/plain'), 98 ('Content-Length', str(len(response))), 99 ('Server', gateway.SERVER_NAME), 100 ]) 101 102 return [response] 103 except (KeyboardInterrupt, SystemExit): 104 raise 105 except: 106 if self.logger: 107 self.logger.exception(gateway.format_exception()) 108 109 response = "500 Internal Server Error\n\nAn unexpected error " \ 110 "occurred whilst decoding." 111 112 if self.debug: 113 response += "\n\nTraceback:\n\n%s" % gateway.format_exception() 114 115 start_response('500 Internal Server Error', [ 116 ('Content-Type', 'text/plain'), 117 ('Content-Length', str(len(response))), 118 ('Server', gateway.SERVER_NAME), 119 ]) 120 121 return [response] 122 123 if self.logger: 124 self.logger.info("AMF Request: %r" % request) 125 126 # Process the request 127 try: 128 response = self.getResponse(request, environ) 129 except (KeyboardInterrupt, SystemExit): 130 raise 131 except: 132 if self.logger: 133 self.logger.exception(gateway.format_exception()) 134 135 response = "500 Internal Server Error\n\nThe request was " \ 136 "unable to be successfully processed." 137 138 if self.debug: 139 response += "\n\nTraceback:\n\n%s" % gateway.format_exception() 140 141 start_response('500 Internal Server Error', [ 142 ('Content-Type', 'text/plain'), 143 ('Content-Length', str(len(response))), 144 ('Server', gateway.SERVER_NAME), 145 ]) 146 147 return [response] 148 149 if self.logger: 150 self.logger.info("AMF Response: %r" % response) 151 152 # Encode the response 153 try: 154 stream = remoting.encode(response, strict=self.strict, 155 timezone_offset=timezone_offset) 156 except: 157 if self.logger: 158 self.logger.exception(gateway.format_exception()) 159 160 response = "500 Internal Server Error\n\nThe request was " \ 161 "unable to be encoded." 162 163 if self.debug: 164 response += "\n\nTraceback:\n\n%s" % gateway.format_exception() 165 166 start_response('500 Internal Server Error', [ 167 ('Content-Type', 'text/plain'), 168 ('Content-Length', str(len(response))), 169 ('Server', gateway.SERVER_NAME), 170 ]) 171 172 return [response] 173 174 response = stream.getvalue() 175 176 start_response('200 OK', [ 177 ('Content-Type', remoting.CONTENT_TYPE), 178 ('Content-Length', str(len(response))), 179 ('Server', gateway.SERVER_NAME), 180 ]) 181 182 return [response]
183