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