199 querystringlist=querystringlist, |
200 querystringlist=querystringlist, |
200 querystringdict=querystringdict, |
201 querystringdict=querystringdict, |
201 headers=headers, |
202 headers=headers, |
202 bodyfh=bodyfh) |
203 bodyfh=bodyfh) |
203 |
204 |
|
205 class wsgiresponse(object): |
|
206 """Represents a response to a WSGI request. |
|
207 |
|
208 A response consists of a status line, headers, and a body. |
|
209 |
|
210 Consumers must populate the ``status`` and ``headers`` fields and |
|
211 make a call to a ``setbody*()`` method before the response can be |
|
212 issued. |
|
213 |
|
214 When it is time to start sending the response over the wire, |
|
215 ``sendresponse()`` is called. It handles emitting the header portion |
|
216 of the response message. It then yields chunks of body data to be |
|
217 written to the peer. Typically, the WSGI application itself calls |
|
218 and returns the value from ``sendresponse()``. |
|
219 """ |
|
220 |
|
221 def __init__(self, req, startresponse): |
|
222 """Create an empty response tied to a specific request. |
|
223 |
|
224 ``req`` is a ``parsedrequest``. ``startresponse`` is the |
|
225 ``start_response`` function passed to the WSGI application. |
|
226 """ |
|
227 self._req = req |
|
228 self._startresponse = startresponse |
|
229 |
|
230 self.status = None |
|
231 self.headers = wsgiheaders.Headers([]) |
|
232 |
|
233 self._bodybytes = None |
|
234 self._bodygen = None |
|
235 self._started = False |
|
236 |
|
237 def setbodybytes(self, b): |
|
238 """Define the response body as static bytes.""" |
|
239 if self._bodybytes is not None or self._bodygen is not None: |
|
240 raise error.ProgrammingError('cannot define body multiple times') |
|
241 |
|
242 self._bodybytes = b |
|
243 self.headers['Content-Length'] = '%d' % len(b) |
|
244 |
|
245 def setbodygen(self, gen): |
|
246 """Define the response body as a generator of bytes.""" |
|
247 if self._bodybytes is not None or self._bodygen is not None: |
|
248 raise error.ProgrammingError('cannot define body multiple times') |
|
249 |
|
250 self._bodygen = gen |
|
251 |
|
252 def sendresponse(self): |
|
253 """Send the generated response to the client. |
|
254 |
|
255 Before this is called, ``status`` must be set and one of |
|
256 ``setbodybytes()`` or ``setbodygen()`` must be called. |
|
257 |
|
258 Calling this method multiple times is not allowed. |
|
259 """ |
|
260 if self._started: |
|
261 raise error.ProgrammingError('sendresponse() called multiple times') |
|
262 |
|
263 self._started = True |
|
264 |
|
265 if not self.status: |
|
266 raise error.ProgrammingError('status line not defined') |
|
267 |
|
268 if self._bodybytes is None and self._bodygen is None: |
|
269 raise error.ProgrammingError('response body not defined') |
|
270 |
|
271 # Various HTTP clients (notably httplib) won't read the HTTP response |
|
272 # until the HTTP request has been sent in full. If servers (us) send a |
|
273 # response before the HTTP request has been fully sent, the connection |
|
274 # may deadlock because neither end is reading. |
|
275 # |
|
276 # We work around this by "draining" the request data before |
|
277 # sending any response in some conditions. |
|
278 drain = False |
|
279 close = False |
|
280 |
|
281 # If the client sent Expect: 100-continue, we assume it is smart enough |
|
282 # to deal with the server sending a response before reading the request. |
|
283 # (httplib doesn't do this.) |
|
284 if self._req.headers.get('Expect', '').lower() == '100-continue': |
|
285 pass |
|
286 # Only tend to request methods that have bodies. Strictly speaking, |
|
287 # we should sniff for a body. But this is fine for our existing |
|
288 # WSGI applications. |
|
289 elif self._req.method not in ('POST', 'PUT'): |
|
290 pass |
|
291 else: |
|
292 # If we don't know how much data to read, there's no guarantee |
|
293 # that we can drain the request responsibly. The WSGI |
|
294 # specification only says that servers *should* ensure the |
|
295 # input stream doesn't overrun the actual request. So there's |
|
296 # no guarantee that reading until EOF won't corrupt the stream |
|
297 # state. |
|
298 if not isinstance(self._req.bodyfh, util.cappedreader): |
|
299 close = True |
|
300 else: |
|
301 # We /could/ only drain certain HTTP response codes. But 200 and |
|
302 # non-200 wire protocol responses both require draining. Since |
|
303 # we have a capped reader in place for all situations where we |
|
304 # drain, it is safe to read from that stream. We'll either do |
|
305 # a drain or no-op if we're already at EOF. |
|
306 drain = True |
|
307 |
|
308 if close: |
|
309 self.headers['Connection'] = 'Close' |
|
310 |
|
311 if drain: |
|
312 assert isinstance(self._req.bodyfh, util.cappedreader) |
|
313 while True: |
|
314 chunk = self._req.bodyfh.read(32768) |
|
315 if not chunk: |
|
316 break |
|
317 |
|
318 self._startresponse(pycompat.sysstr(self.status), self.headers.items()) |
|
319 if self._bodybytes: |
|
320 yield self._bodybytes |
|
321 elif self._bodygen: |
|
322 for chunk in self._bodygen: |
|
323 yield chunk |
|
324 else: |
|
325 error.ProgrammingError('do not know how to send body') |
|
326 |
204 class wsgirequest(object): |
327 class wsgirequest(object): |
205 """Higher-level API for a WSGI request. |
328 """Higher-level API for a WSGI request. |
206 |
329 |
207 WSGI applications are invoked with 2 arguments. They are used to |
330 WSGI applications are invoked with 2 arguments. They are used to |
208 instantiate instances of this class, which provides higher-level APIs |
331 instantiate instances of this class, which provides higher-level APIs |
226 self.multiprocess = wsgienv[r'wsgi.multiprocess'] |
349 self.multiprocess = wsgienv[r'wsgi.multiprocess'] |
227 self.run_once = wsgienv[r'wsgi.run_once'] |
350 self.run_once = wsgienv[r'wsgi.run_once'] |
228 self.env = wsgienv |
351 self.env = wsgienv |
229 self.req = parserequestfromenv(wsgienv, inp) |
352 self.req = parserequestfromenv(wsgienv, inp) |
230 self.form = self.req.querystringdict |
353 self.form = self.req.querystringdict |
|
354 self.res = wsgiresponse(self.req, start_response) |
231 self._start_response = start_response |
355 self._start_response = start_response |
232 self.server_write = None |
356 self.server_write = None |
233 self.headers = [] |
357 self.headers = [] |
234 |
358 |
235 def respond(self, status, type, filename=None, body=None): |
359 def respond(self, status, type, filename=None, body=None): |