Create callback parser based on http_parser setting. Parser selection: - auto: Use H1CProtocol if available (>= 0.4.1) and no incompatible flags, else PythonProtocol - fast: Require H1CProtocol >= 0.4.1 (error if unavailable or incompatible flags) - python: Use Pytho
(self)
| 450 | ) |
| 451 | |
| 452 | def _setup_callback_parser(self): |
| 453 | """Create callback parser based on http_parser setting. |
| 454 | |
| 455 | Parser selection: |
| 456 | - auto: Use H1CProtocol if available (>= 0.4.1) and no incompatible flags, else PythonProtocol |
| 457 | - fast: Require H1CProtocol >= 0.4.1 (error if unavailable or incompatible flags) |
| 458 | - python: Use PythonProtocol only |
| 459 | """ |
| 460 | parser_setting = getattr(self.cfg, 'http_parser', 'auto') |
| 461 | |
| 462 | # Check for incompatible compatibility flags |
| 463 | incompatible = [] |
| 464 | for flag in self._FAST_PARSER_INCOMPATIBLE_FLAGS: |
| 465 | if getattr(self.cfg, flag, False): |
| 466 | incompatible.append(flag) |
| 467 | # PROXY protocol framing is implemented only in PythonProtocol; the C parser |
| 468 | # has no proxy_protocol kwarg and would silently drop the framing. |
| 469 | if getattr(self.cfg, 'proxy_protocol', 'off') != 'off': |
| 470 | incompatible.append('proxy_protocol') |
| 471 | |
| 472 | if parser_setting == 'python': |
| 473 | parser_class = PythonProtocol |
| 474 | elif parser_setting == 'fast': |
| 475 | if not self._check_h1c_protocol_available(): |
| 476 | raise RuntimeError("gunicorn_h1c required for http_parser='fast'") |
| 477 | if not ASGIProtocol._h1c_has_limits: |
| 478 | raise RuntimeError( |
| 479 | "gunicorn_h1c >= 0.4.1 required for http_parser='fast'. " |
| 480 | "Please upgrade: pip install --upgrade gunicorn_h1c" |
| 481 | ) |
| 482 | if incompatible: |
| 483 | raise RuntimeError( |
| 484 | "http_parser='fast' is incompatible with compatibility flags: %s. " |
| 485 | "Use http_parser='python' or disable these flags." |
| 486 | % ', '.join(incompatible) |
| 487 | ) |
| 488 | parser_class = ASGIProtocol._h1c_protocol_class |
| 489 | else: # auto |
| 490 | if (self._check_h1c_protocol_available() and |
| 491 | ASGIProtocol._h1c_has_limits and not incompatible): |
| 492 | parser_class = ASGIProtocol._h1c_protocol_class |
| 493 | else: |
| 494 | parser_class = PythonProtocol |
| 495 | |
| 496 | # Handle limit_request_line=0 (unlimited per documentation) |
| 497 | # PythonProtocol handles 0 correctly, but C parser needs a large value |
| 498 | limit_request_line = self.cfg.limit_request_line |
| 499 | if limit_request_line == 0 and parser_class != PythonProtocol: |
| 500 | limit_request_line = 1024 * 1024 # 1MB for C parser |
| 501 | |
| 502 | # Create parser with callbacks and limit parameters (both parsers support them). |
| 503 | # Only the Python parser implements PROXY protocol framing; pass the option there. |
| 504 | parser_kwargs = { |
| 505 | 'on_headers_complete': self._on_headers_complete, |
| 506 | 'on_body': self._on_body, |
| 507 | 'on_message_complete': self._on_message_complete, |
| 508 | 'limit_request_line': limit_request_line, |
| 509 | 'limit_request_fields': self.cfg.limit_request_fields, |
no test coverage detected