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 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 -class WSGIGateway(gateway.BaseGateway):
     32      """
     33      WSGI Remoting Gateway.
     34      """
     35
     36 -    def getResponse(self, request, environ):
     37          """
     38          Processes the AMF request, returning an AMF response.
     39
     40          @param request: The AMF Request.
     41          @type request: L{Envelope<pyamf.remoting.Envelope>}
     42          @rtype: L{Envelope<pyamf.remoting.Envelope>}
     43          @return: The AMF Response.
     44          """
     45          response = remoting.Envelope(request.amfVersion, request.clientType)
     46
     47          for name, message in request:
     48              processor = self.getProcessor(message)
     49              response[name] = processor(message, http_request=environ)
     50
     51          return response
     52
     53 -    def badRequestMethod(self, environ, start_response):
     54          """
     55          Return HTTP 400 Bad Request.
     56          """
     57          response = "400 Bad Request\n\nTo access this PyAMF gateway you " \
     58              "must use POST requests (%s received)" % environ['REQUEST_METHOD']
     59
     60          start_response('400 Bad Request', [
     61              ('Content-Type', 'text/plain'),
     62              ('Content-Length', str(len(response))),
     63              ('Server', gateway.SERVER_NAME),
     64          ])
     65
     66          return [response]
     67
     68 -    def __call__(self, environ, start_response):
     69          """
     70          @rtype: C{StringIO}
     71          @return: File-like object.
     72          """
     73          if environ['REQUEST_METHOD'] != 'POST':
     74              return self.badRequestMethod(environ, start_response)
     75
     76          body = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))
     77          stream = None
     78
     79          context = pyamf.get_context(pyamf.AMF0)
     80
     81          # Decode the request
     82          try:
     83              request = remoting.decode(body, context, strict=self.strict)
     84          except (pyamf.DecodeError, EOFError):
     85              self.logger.exception(gateway.format_exception())
     86
     87              response = "400 Bad Request\n\nThe request body was unable to " \
     88                  "be successfully decoded."
     89
     90              if self.debug:
     91                  response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
     92
     93              start_response('400 Bad Request', [
     94                  ('Content-Type', 'text/plain'),
     95                  ('Content-Length', str(len(response))),
     96                  ('Server', gateway.SERVER_NAME),
     97              ])
     98
     99              return [response]
    100          except (KeyboardInterrupt, SystemExit):
    101              raise
    102          except:
    103              self.logger.exception(gateway.format_exception())
    104
    105              response = "500 Internal Server Error\n\nAn unexpected error occurred whilst decoding."
    106
    107              if self.debug:
    108                  response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
    109
    110              start_response('500 Internal Server Error', [
    111                  ('Content-Type', 'text/plain'),
    112                  ('Content-Length', str(len(response))),
    113                  ('Server', gateway.SERVER_NAME),
    114              ])
    115
    116              return [response]
    117
    118          self.logger.debug("AMF Request: %r" % request)
    119
    120          # Process the request
    121          try:
    122              response = self.getResponse(request, environ)
    123          except (KeyboardInterrupt, SystemExit):
    124              raise
    125          except:
    126              self.logger.exception(gateway.format_exception())
    127
    128              response = "500 Internal Server Error\n\nThe request was " \
    129                  "unable to be successfully processed."
    130
    131              if self.debug:
    132                  response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
    133
    134              start_response('500 Internal Server Error', [
    135                  ('Content-Type', 'text/plain'),
    136                  ('Content-Length', str(len(response))),
    137                  ('Server', gateway.SERVER_NAME),
    138              ])
    139
    140              return [response]
    141
    142          self.logger.debug("AMF Response: %r" % response)
    143
    144          # Encode the response
    145          try:
    146              stream = remoting.encode(response, context, strict=self.strict)
    147          except:
    148              self.logger.exception(gateway.format_exception())
    149
    150              response = "500 Internal Server Error\n\nThe request was " \
    151                  "unable to be encoded."
    152
    153              if self.debug:
    154                  response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
    155
    156              start_response('500 Internal Server Error', [
    157                  ('Content-Type', 'text/plain'),
    158                  ('Content-Length', str(len(response))),
    159                  ('Server', gateway.SERVER_NAME),
    160              ])
    161
    162              return [response]
    163
    164          response = stream.getvalue()
    165
    166          start_response('200 OK', [
    167              ('Content-Type', remoting.CONTENT_TYPE),
    168              ('Content-Length', str(len(response))),
    169              ('Server', gateway.SERVER_NAME),
    170          ])
    171
    172          return [response]
    173