Show More
@@ -254,12 +254,6 class wsgirequest(object): | |||
|
254 | 254 | self.server_write = None |
|
255 | 255 | self.headers = [] |
|
256 | 256 | |
|
257 | def drain(self): | |
|
258 | '''need to read all data from request, httplib is half-duplex''' | |
|
259 | length = int(self.env.get('CONTENT_LENGTH') or 0) | |
|
260 | for s in util.filechunkiter(self.inp, limit=length): | |
|
261 | pass | |
|
262 | ||
|
263 | 257 | def respond(self, status, type, filename=None, body=None): |
|
264 | 258 | if not isinstance(type, str): |
|
265 | 259 | type = pycompat.sysstr(type) |
@@ -292,6 +286,53 class wsgirequest(object): | |||
|
292 | 286 | elif isinstance(status, int): |
|
293 | 287 | status = statusmessage(status) |
|
294 | 288 | |
|
289 | # Various HTTP clients (notably httplib) won't read the HTTP | |
|
290 | # response until the HTTP request has been sent in full. If servers | |
|
291 | # (us) send a response before the HTTP request has been fully sent, | |
|
292 | # the connection may deadlock because neither end is reading. | |
|
293 | # | |
|
294 | # We work around this by "draining" the request data before | |
|
295 | # sending any response in some conditions. | |
|
296 | drain = False | |
|
297 | close = False | |
|
298 | ||
|
299 | # If the client sent Expect: 100-continue, we assume it is smart | |
|
300 | # enough to deal with the server sending a response before reading | |
|
301 | # the request. (httplib doesn't do this.) | |
|
302 | if self.env.get(r'HTTP_EXPECT', r'').lower() == r'100-continue': | |
|
303 | pass | |
|
304 | # Only tend to request methods that have bodies. Strictly speaking, | |
|
305 | # we should sniff for a body. But this is fine for our existing | |
|
306 | # WSGI applications. | |
|
307 | elif self.env[r'REQUEST_METHOD'] not in (r'POST', r'PUT'): | |
|
308 | pass | |
|
309 | else: | |
|
310 | # If we don't know how much data to read, there's no guarantee | |
|
311 | # that we can drain the request responsibly. The WSGI | |
|
312 | # specification only says that servers *should* ensure the | |
|
313 | # input stream doesn't overrun the actual request. So there's | |
|
314 | # no guarantee that reading until EOF won't corrupt the stream | |
|
315 | # state. | |
|
316 | if not isinstance(self.inp, util.cappedreader): | |
|
317 | close = True | |
|
318 | else: | |
|
319 | # We /could/ only drain certain HTTP response codes. But 200 | |
|
320 | # and non-200 wire protocol responses both require draining. | |
|
321 | # Since we have a capped reader in place for all situations | |
|
322 | # where we drain, it is safe to read from that stream. We'll | |
|
323 | # either do a drain or no-op if we're already at EOF. | |
|
324 | drain = True | |
|
325 | ||
|
326 | if close: | |
|
327 | self.headers.append((r'Connection', r'Close')) | |
|
328 | ||
|
329 | if drain: | |
|
330 | assert isinstance(self.inp, util.cappedreader) | |
|
331 | while True: | |
|
332 | chunk = self.inp.read(32768) | |
|
333 | if not chunk: | |
|
334 | break | |
|
335 | ||
|
295 | 336 | self.server_write = self._start_response( |
|
296 | 337 | pycompat.sysstr(status), self.headers) |
|
297 | 338 | self._start_response = None |
@@ -301,9 +301,6 def _callhttp(repo, wsgireq, req, proto, | |||
|
301 | 301 | wsgireq.respond(HTTP_OK, HGTYPE, body=rsp) |
|
302 | 302 | return [] |
|
303 | 303 | elif isinstance(rsp, wireprototypes.pusherr): |
|
304 | # This is the httplib workaround documented in _handlehttperror(). | |
|
305 | wsgireq.drain() | |
|
306 | ||
|
307 | 304 | rsp = '0\n%s\n' % rsp.res |
|
308 | 305 | wsgireq.respond(HTTP_OK, HGTYPE, body=rsp) |
|
309 | 306 | return [] |
@@ -316,21 +313,6 def _callhttp(repo, wsgireq, req, proto, | |||
|
316 | 313 | def _handlehttperror(e, wsgireq, req): |
|
317 | 314 | """Called when an ErrorResponse is raised during HTTP request processing.""" |
|
318 | 315 | |
|
319 | # Clients using Python's httplib are stateful: the HTTP client | |
|
320 | # won't process an HTTP response until all request data is | |
|
321 | # sent to the server. The intent of this code is to ensure | |
|
322 | # we always read HTTP request data from the client, thus | |
|
323 | # ensuring httplib transitions to a state that allows it to read | |
|
324 | # the HTTP response. In other words, it helps prevent deadlocks | |
|
325 | # on clients using httplib. | |
|
326 | ||
|
327 | if (req.method == 'POST' and | |
|
328 | # But not if Expect: 100-continue is being used. | |
|
329 | (req.headers.get('Expect', '').lower() != '100-continue')): | |
|
330 | wsgireq.drain() | |
|
331 | else: | |
|
332 | wsgireq.headers.append((r'Connection', r'Close')) | |
|
333 | ||
|
334 | 316 | # TODO This response body assumes the failed command was |
|
335 | 317 | # "unbundle." That assumption is not always valid. |
|
336 | 318 | wsgireq.respond(e, HGTYPE, body='0\n%s\n' % pycompat.bytestr(e)) |
General Comments 0
You need to be logged in to leave comments.
Login now