1
2
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 @author: U{Nick Joyce<mailto:nick@boxdesign.co.uk>}
23
24 @since: 0.1.0
25 """
26
27 import pyamf
28 from pyamf import remoting
29 from pyamf.remoting import gateway
30
31 __all__ = ['WSGIGateway']
32
34 """
35 WSGI Remoting Gateway.
36 """
37
39 """
40 Processes the AMF request, returning an AMF response.
41
42 @param request: The AMF Request.
43 @type request: L{Envelope<pyamf.remoting.Envelope>}
44 @rtype: L{Envelope<pyamf.remoting.Envelope>}
45 @return: The AMF Response.
46 """
47 response = remoting.Envelope(request.amfVersion, request.clientType)
48
49 for name, message in request:
50 processor = self.getProcessor(message)
51 response[name] = processor(message, http_request=environ)
52
53 return response
54
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 ])
66
67 return [response]
68
69 - def __call__(self, environ, start_response):
70 """
71 @rtype: C{StringIO}
72 @return: File-like object.
73 """
74 if environ['REQUEST_METHOD'] != 'POST':
75 return self.badRequestMethod(environ, start_response)
76
77 body = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))
78 stream = None
79
80 context = pyamf.get_context(pyamf.AMF0)
81
82
83 try:
84 request = remoting.decode(body, context)
85 except pyamf.DecodeError:
86 self.logger.debug(gateway.format_exception())
87
88 response = "400 Bad Request\n\nThe request body was unable to " \
89 "be successfully decoded."
90
91 if self.debug:
92 response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
93
94 start_response('400 Bad Request', [
95 ('Content-Type', 'text/plain'),
96 ('Content-Length', str(len(response))),
97 ])
98
99 return [response]
100
101
102 try:
103 response = self.getResponse(request, environ)
104 except (KeyboardInterrupt, SystemExit):
105 raise
106 except:
107 self.logger.debug(gateway.format_exception())
108
109 response = "500 Internal Server Error\n\nThe request was " \
110 "unable to be successfully processed."
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 ])
119
120 return [response]
121
122
123 try:
124 stream = remoting.encode(response, context)
125 except pyamf.EncodeError:
126 self.logger.debug(gateway.format_exception())
127
128 response = "500 Internal Server Error\n\nThe request was " \
129 "unable to be encoded."
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 ])
138
139 return [response]
140
141 response = stream.getvalue()
142
143 start_response('200 OK', [
144 ('Content-Type', remoting.CONTENT_TYPE),
145 ('Content-Length', str(len(response))),
146 ])
147
148 return [response]
149