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 @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
32 """
33 WSGI Remoting Gateway.
34 """
35
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
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
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
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
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