(data: bytes)
| 258 | chunk_response: bool = False |
| 259 | |
| 260 | def write(data: bytes) -> None: |
| 261 | nonlocal status_sent, headers_sent, chunk_response |
| 262 | assert status_set is not None, "write() before start_response" |
| 263 | assert headers_set is not None, "write() before start_response" |
| 264 | if status_sent is None: |
| 265 | status_sent = status_set |
| 266 | headers_sent = headers_set |
| 267 | try: |
| 268 | code_str, msg = status_sent.split(None, 1) |
| 269 | except ValueError: |
| 270 | code_str, msg = status_sent, "" |
| 271 | code = int(code_str) |
| 272 | self.send_response(code, msg) |
| 273 | header_keys = set() |
| 274 | for key, value in headers_sent: |
| 275 | self.send_header(key, value) |
| 276 | header_keys.add(key.lower()) |
| 277 | |
| 278 | # Use chunked transfer encoding if there is no content |
| 279 | # length. Do not use for 1xx and 204 responses. 304 |
| 280 | # responses and HEAD requests are also excluded, which |
| 281 | # is the more conservative behavior and matches other |
| 282 | # parts of the code. |
| 283 | # https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.1 |
| 284 | if ( |
| 285 | not ( |
| 286 | "content-length" in header_keys |
| 287 | or environ["REQUEST_METHOD"] == "HEAD" |
| 288 | or (100 <= code < 200) |
| 289 | or code in {204, 304} |
| 290 | ) |
| 291 | and self.protocol_version >= "HTTP/1.1" |
| 292 | ): |
| 293 | chunk_response = True |
| 294 | self.send_header("Transfer-Encoding", "chunked") |
| 295 | |
| 296 | # Always close the connection. This disables HTTP/1.1 |
| 297 | # keep-alive connections. They aren't handled well by |
| 298 | # Python's http.server because it doesn't know how to |
| 299 | # drain the stream before the next request line. |
| 300 | self.send_header("Connection", "close") |
| 301 | self.end_headers() |
| 302 | |
| 303 | assert isinstance(data, bytes), "applications must write bytes" |
| 304 | |
| 305 | if data: |
| 306 | if chunk_response: |
| 307 | self.wfile.write(hex(len(data))[2:].encode()) |
| 308 | self.wfile.write(b"\r\n") |
| 309 | |
| 310 | self.wfile.write(data) |
| 311 | |
| 312 | if chunk_response: |
| 313 | self.wfile.write(b"\r\n") |
| 314 | |
| 315 | self.wfile.flush() |
| 316 | |
| 317 | def start_response(status, headers, exc_info=None): # type: ignore |
no test coverage detected