Handle a single HTTP/2 request/stream.
(self, req, conn, h2_conn)
| 563 | return False |
| 564 | |
| 565 | def handle_http2_request(self, req, conn, h2_conn): |
| 566 | """Handle a single HTTP/2 request/stream.""" |
| 567 | environ = {} |
| 568 | resp = None |
| 569 | stream_id = req.stream.stream_id |
| 570 | |
| 571 | try: |
| 572 | self.cfg.pre_request(self, req) |
| 573 | request_start = datetime.now() |
| 574 | |
| 575 | # Create WSGI environ |
| 576 | resp, environ = wsgi.create(req, conn.sock, conn.client, |
| 577 | conn.server, self.cfg) |
| 578 | environ["wsgi.multithread"] = True |
| 579 | environ["HTTP_VERSION"] = "2" # Indicate HTTP/2 |
| 580 | |
| 581 | # Replace wsgi.early_hints with HTTP/2-specific version |
| 582 | def send_early_hints_h2(headers): |
| 583 | """Send 103 Early Hints over HTTP/2.""" |
| 584 | h2_conn.send_informational(stream_id, 103, headers) |
| 585 | |
| 586 | environ["wsgi.early_hints"] = send_early_hints_h2 |
| 587 | |
| 588 | # Add HTTP/2 trailer support |
| 589 | pending_trailers = [] |
| 590 | |
| 591 | def send_trailers_h2(trailers): |
| 592 | """Queue trailers to be sent after response body.""" |
| 593 | pending_trailers.extend(trailers) |
| 594 | |
| 595 | environ["gunicorn.http2.send_trailers"] = send_trailers_h2 |
| 596 | |
| 597 | self.nr += 1 |
| 598 | if self.nr >= self.max_requests: |
| 599 | if self.alive: |
| 600 | self.log.info("Autorestarting worker after current request.") |
| 601 | self.alive = False |
| 602 | |
| 603 | # Run WSGI app |
| 604 | respiter = self.wsgi(environ, resp.start_response) |
| 605 | |
| 606 | # Collect response body |
| 607 | response_body = b'' |
| 608 | try: |
| 609 | if hasattr(respiter, '__iter__'): |
| 610 | for item in respiter: |
| 611 | if item: |
| 612 | response_body += item |
| 613 | finally: |
| 614 | if hasattr(respiter, "close"): |
| 615 | respiter.close() |
| 616 | |
| 617 | # Send response via HTTP/2 |
| 618 | if pending_trailers: |
| 619 | # Send headers, body, then trailers separately |
| 620 | # Build response headers with :status pseudo-header |
| 621 | response_headers = [(':status', str(resp.status_code))] |
| 622 | for name, value in resp.headers: |
no test coverage detected