(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter)
| 453 | log.info("Served CA certificate to LAN device") |
| 454 | |
| 455 | async def _on_client(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter): |
| 456 | addr = writer.get_extra_info("peername") |
| 457 | task = self._track_current_task() |
| 458 | try: |
| 459 | first_line = await asyncio.wait_for(reader.readline(), timeout=30) |
| 460 | if not first_line: |
| 461 | return |
| 462 | |
| 463 | # Read remaining headers |
| 464 | header_block = first_line |
| 465 | while True: |
| 466 | line = await asyncio.wait_for(reader.readline(), timeout=10) |
| 467 | header_block += line |
| 468 | if len(header_block) > MAX_HEADER_BYTES: |
| 469 | log.warning("Request header block exceeds cap — closing") |
| 470 | return |
| 471 | if line in (b"\r\n", b"\n", b""): |
| 472 | break |
| 473 | |
| 474 | if has_unsupported_transfer_encoding(header_block): |
| 475 | log.warning("Unsupported Transfer-Encoding on client request") |
| 476 | writer.write( |
| 477 | b"HTTP/1.1 501 Not Implemented\r\n" |
| 478 | b"Connection: close\r\n" |
| 479 | b"Content-Length: 0\r\n\r\n" |
| 480 | ) |
| 481 | await writer.drain() |
| 482 | return |
| 483 | |
| 484 | request_line = first_line.decode(errors="replace").strip() |
| 485 | parts = request_line.split(" ", 2) |
| 486 | if len(parts) < 2: |
| 487 | return |
| 488 | |
| 489 | method = parts[0].upper() |
| 490 | path = parts[1] if len(parts) >= 2 else "/" |
| 491 | |
| 492 | if method == "GET" and path == "/ca.crt" and self._lan_sharing: |
| 493 | await self._serve_ca_cert(writer) |
| 494 | return |
| 495 | |
| 496 | if method == "CONNECT": |
| 497 | await self._do_connect(parts[1], reader, writer) |
| 498 | else: |
| 499 | await self._do_http(header_block, reader, writer) |
| 500 | |
| 501 | except asyncio.CancelledError: |
| 502 | pass |
| 503 | except asyncio.TimeoutError: |
| 504 | log.debug("Timeout: %s", addr) |
| 505 | except Exception as e: |
| 506 | log.error("Error (%s): %s", addr, e) |
| 507 | finally: |
| 508 | self._untrack_task(task) |
| 509 | try: |
| 510 | writer.close() |
| 511 | await writer.wait_closed() |
| 512 | except Exception: |
nothing calls this directly
no test coverage detected