Implements `.HTTPConnection.write_headers`.
(
self,
start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine],
headers: httputil.HTTPHeaders,
chunk: Optional[bytes] = None,
)
| 384 | self._max_body_size = max_body_size |
| 385 | |
| 386 | def write_headers( |
| 387 | self, |
| 388 | start_line: Union[httputil.RequestStartLine, httputil.ResponseStartLine], |
| 389 | headers: httputil.HTTPHeaders, |
| 390 | chunk: Optional[bytes] = None, |
| 391 | ) -> "Future[None]": |
| 392 | """Implements `.HTTPConnection.write_headers`.""" |
| 393 | lines = [] |
| 394 | if self.is_client: |
| 395 | assert isinstance(start_line, httputil.RequestStartLine) |
| 396 | self._request_start_line = start_line |
| 397 | lines.append(utf8(f"{start_line[0]} {start_line[1]} HTTP/1.1")) |
| 398 | # Client requests with a non-empty body must have either a |
| 399 | # Content-Length or a Transfer-Encoding. If Content-Length is not |
| 400 | # present we'll add our Transfer-Encoding below. |
| 401 | self._chunking_output = ( |
| 402 | start_line.method in ("POST", "PUT", "PATCH") |
| 403 | and "Content-Length" not in headers |
| 404 | ) |
| 405 | else: |
| 406 | assert isinstance(start_line, httputil.ResponseStartLine) |
| 407 | assert self._request_start_line is not None |
| 408 | assert self._request_headers is not None |
| 409 | self._response_start_line = start_line |
| 410 | lines.append(utf8("HTTP/1.1 %d %s" % (start_line[1], start_line[2]))) |
| 411 | self._chunking_output = ( |
| 412 | # TODO: should this use |
| 413 | # self._request_start_line.version or |
| 414 | # start_line.version? |
| 415 | self._request_start_line.version == "HTTP/1.1" |
| 416 | # Omit payload header field for HEAD request. |
| 417 | and self._request_start_line.method != "HEAD" |
| 418 | # 1xx, 204 and 304 responses have no body (not even a zero-length |
| 419 | # body), and so should not have either Content-Length or |
| 420 | # Transfer-Encoding headers. |
| 421 | and start_line.code not in (204, 304) |
| 422 | and (start_line.code < 100 or start_line.code >= 200) |
| 423 | # No need to chunk the output if a Content-Length is specified. |
| 424 | and "Content-Length" not in headers |
| 425 | ) |
| 426 | # If connection to a 1.1 client will be closed, inform client |
| 427 | if ( |
| 428 | self._request_start_line.version == "HTTP/1.1" |
| 429 | and self._disconnect_on_finish |
| 430 | ): |
| 431 | headers["Connection"] = "close" |
| 432 | # If a 1.0 client asked for keep-alive, add the header. |
| 433 | if ( |
| 434 | self._request_start_line.version == "HTTP/1.0" |
| 435 | and self._request_headers.get("Connection", "").lower() == "keep-alive" |
| 436 | ): |
| 437 | headers["Connection"] = "Keep-Alive" |
| 438 | if self._chunking_output: |
| 439 | headers["Transfer-Encoding"] = "chunked" |
| 440 | if not self.is_client and ( |
| 441 | self._request_start_line.method == "HEAD" |
| 442 | or cast(httputil.ResponseStartLine, start_line).code == 304 |
| 443 | ): |
nothing calls this directly
no test coverage detected