359 if (self._bodybytes is not None or self._bodygen is not None |
358 if (self._bodybytes is not None or self._bodygen is not None |
360 or self._bodywillwrite): |
359 or self._bodywillwrite): |
361 raise error.ProgrammingError('cannot define body multiple times') |
360 raise error.ProgrammingError('cannot define body multiple times') |
362 |
361 |
363 def setbodybytes(self, b): |
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 self._verifybody() |
367 self._verifybody() |
366 self._bodybytes = b |
368 self._bodybytes = b |
367 self.headers['Content-Length'] = '%d' % len(b) |
369 self.headers['Content-Length'] = '%d' % len(b) |
368 |
370 |
369 def setbodygen(self, gen): |
371 def setbodygen(self, gen): |
405 raise error.ProgrammingError('status line not defined') |
407 raise error.ProgrammingError('status line not defined') |
406 |
408 |
407 if (self._bodybytes is None and self._bodygen is None |
409 if (self._bodybytes is None and self._bodygen is None |
408 and not self._bodywillwrite): |
410 and not self._bodywillwrite): |
409 raise error.ProgrammingError('response body not defined') |
411 raise error.ProgrammingError('response body not defined') |
|
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") |
410 |
441 |
411 # Various HTTP clients (notably httplib) won't read the HTTP response |
442 # Various HTTP clients (notably httplib) won't read the HTTP response |
412 # until the HTTP request has been sent in full. If servers (us) send a |
443 # until the HTTP request has been sent in full. If servers (us) send a |
413 # response before the HTTP request has been fully sent, the connection |
444 # response before the HTTP request has been fully sent, the connection |
414 # may deadlock because neither end is reading. |
445 # may deadlock because neither end is reading. |
537 if not isinstance(v, str): |
568 if not isinstance(v, str): |
538 raise TypeError('header value must be string: %r' % (v,)) |
569 raise TypeError('header value must be string: %r' % (v,)) |
539 |
570 |
540 if isinstance(status, ErrorResponse): |
571 if isinstance(status, ErrorResponse): |
541 self.headers.extend(status.headers) |
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 status = statusmessage(status.code, pycompat.bytestr(status)) |
573 status = statusmessage(status.code, pycompat.bytestr(status)) |
550 elif status == 200: |
574 elif status == 200: |
551 status = '200 Script output follows' |
575 status = '200 Script output follows' |
552 elif isinstance(status, int): |
576 elif isinstance(status, int): |
553 status = statusmessage(status) |
577 status = statusmessage(status) |