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