Parse request line, return True if complete.
(self)
| 461 | return True |
| 462 | |
| 463 | def _parse_request_line(self): |
| 464 | """Parse request line, return True if complete.""" |
| 465 | idx = self._buffer.find(b'\r\n') |
| 466 | if idx == -1: |
| 467 | return False |
| 468 | |
| 469 | # Check request line length limit |
| 470 | if self._limit_request_line > 0 and idx > self._limit_request_line: |
| 471 | raise LimitRequestLine("Request line is too large") |
| 472 | |
| 473 | line = bytes(self._buffer[:idx]) |
| 474 | del self._buffer[:idx + 2] |
| 475 | |
| 476 | # Parse: METHOD PATH HTTP/x.y |
| 477 | parts = line.split(b' ', 2) |
| 478 | if len(parts) != 3: |
| 479 | raise InvalidRequestLine("Invalid request line") |
| 480 | |
| 481 | self.method = parts[0] |
| 482 | self.path = parts[1] |
| 483 | |
| 484 | # Validate method |
| 485 | if not self._permit_unconventional_http_method: |
| 486 | if not self._is_valid_method(self.method): |
| 487 | raise InvalidRequestMethod(self.method.decode('latin-1')) |
| 488 | |
| 489 | # RFC 9112 section 3.2.4: asterisk-form is only valid with OPTIONS. |
| 490 | if self.path == b'*' and self.method != b'OPTIONS': |
| 491 | raise InvalidRequestLine("Invalid request line") |
| 492 | |
| 493 | # RFC 9112 section 3.2.3: authority-form is only valid with CONNECT. |
| 494 | if (self.method != b'CONNECT' |
| 495 | and self.path != b'*' |
| 496 | and not self.path.startswith(b'/') |
| 497 | and b'://' not in self.path): |
| 498 | raise InvalidRequestLine("Invalid request line") |
| 499 | |
| 500 | # Parse version |
| 501 | version = parts[2] |
| 502 | if version == b'HTTP/1.1': |
| 503 | self.http_version = (1, 1) |
| 504 | elif version == b'HTTP/1.0': |
| 505 | self.http_version = (1, 0) |
| 506 | else: |
| 507 | if not self._permit_unconventional_http_version: |
| 508 | raise InvalidHTTPVersion(version.decode('latin-1')) |
| 509 | # Try to parse other HTTP/1.x versions if permitted |
| 510 | if version.startswith(b'HTTP/1.'): |
| 511 | try: |
| 512 | minor = int(version[7:]) |
| 513 | self.http_version = (1, minor) |
| 514 | except ValueError: |
| 515 | raise InvalidHTTPVersion(version.decode('latin-1')) |
| 516 | else: |
| 517 | raise InvalidHTTPVersion(version.decode('latin-1')) |
| 518 | |
| 519 | if self._on_message_begin: |
| 520 | self._on_message_begin() |
no test coverage detected