##// END OF EJS Templates
hgweb: refactor 304 handling code...
Gregory Szorc -
r36894:ccb70a77 default
parent child Browse files
Show More
@@ -15,7 +15,6 b' from .common import ('
15 15 ErrorResponse,
16 16 HTTP_BAD_REQUEST,
17 17 HTTP_NOT_FOUND,
18 HTTP_NOT_MODIFIED,
19 18 HTTP_OK,
20 19 HTTP_SERVER_ERROR,
21 20 cspvalues,
@@ -391,7 +390,10 b' class hgweb(object):'
391 390 if rctx.configbool('web', 'cache') and not rctx.nonce:
392 391 tag = 'W/"%d"' % self.mtime
393 392 if req.headers.get('If-None-Match') == tag:
394 raise ErrorResponse(HTTP_NOT_MODIFIED)
393 res.status = '304 Not Modified'
394 # Response body not allowed on 304.
395 res.setbodybytes('')
396 return res.sendresponse()
395 397
396 398 wsgireq.headers.append((r'ETag', pycompat.sysstr(tag)))
397 399 res.headers['ETag'] = tag
@@ -426,9 +428,6 b' class hgweb(object):'
426 428 return tmpl('error', error=pycompat.bytestr(inst))
427 429 except ErrorResponse as inst:
428 430 wsgireq.respond(inst, ctype)
429 if inst.code == HTTP_NOT_MODIFIED:
430 # Not allowed to return a body on a 304
431 return ['']
432 431 return tmpl('error', error=pycompat.bytestr(inst))
433 432
434 433 def check_perm(self, rctx, req, op):
@@ -15,7 +15,6 b' import wsgiref.headers as wsgiheaders'
15 15
16 16 from .common import (
17 17 ErrorResponse,
18 HTTP_NOT_MODIFIED,
19 18 statusmessage,
20 19 )
21 20
@@ -361,7 +360,10 b' class wsgiresponse(object):'
361 360 raise error.ProgrammingError('cannot define body multiple times')
362 361
363 362 def setbodybytes(self, b):
364 """Define the response body as static bytes."""
363 """Define the response body as static bytes.
364
365 The empty string signals that there is no response body.
366 """
365 367 self._verifybody()
366 368 self._bodybytes = b
367 369 self.headers['Content-Length'] = '%d' % len(b)
@@ -408,6 +410,35 b' class wsgiresponse(object):'
408 410 and not self._bodywillwrite):
409 411 raise error.ProgrammingError('response body not defined')
410 412
413 # RFC 7232 Section 4.1 states that a 304 MUST generate one of
414 # {Cache-Control, Content-Location, Date, ETag, Expires, Vary}
415 # and SHOULD NOT generate other headers unless they could be used
416 # to guide cache updates. Furthermore, RFC 7230 Section 3.3.2
417 # states that no response body can be issued. Content-Length can
418 # be sent. But if it is present, it should be the size of the response
419 # that wasn't transferred.
420 if self.status.startswith('304 '):
421 # setbodybytes('') will set C-L to 0. This doesn't conform with the
422 # spec. So remove it.
423 if self.headers.get('Content-Length') == '0':
424 del self.headers['Content-Length']
425
426 # Strictly speaking, this is too strict. But until it causes
427 # problems, let's be strict.
428 badheaders = {k for k in self.headers.keys()
429 if k.lower() not in ('date', 'etag', 'expires',
430 'cache-control',
431 'content-location',
432 'vary')}
433 if badheaders:
434 raise error.ProgrammingError(
435 'illegal header on 304 response: %s' %
436 ', '.join(sorted(badheaders)))
437
438 if self._bodygen is not None or self._bodywillwrite:
439 raise error.ProgrammingError("must use setbodybytes('') with "
440 "304 responses")
441
411 442 # Various HTTP clients (notably httplib) won't read the HTTP response
412 443 # until the HTTP request has been sent in full. If servers (us) send a
413 444 # response before the HTTP request has been fully sent, the connection
@@ -539,13 +570,6 b' class wsgirequest(object):'
539 570
540 571 if isinstance(status, ErrorResponse):
541 572 self.headers.extend(status.headers)
542 if status.code == HTTP_NOT_MODIFIED:
543 # RFC 2616 Section 10.3.5: 304 Not Modified has cases where
544 # it MUST NOT include any headers other than these and no
545 # body
546 self.headers = [(k, v) for (k, v) in self.headers if
547 k in ('Date', 'ETag', 'Expires',
548 'Cache-Control', 'Vary')]
549 573 status = statusmessage(status.code, pycompat.bytestr(status))
550 574 elif status == 200:
551 575 status = '200 Script output follows'
General Comments 0
You need to be logged in to leave comments. Login now