Make an HTTP/2 request and return the response.
(sock, h2_conn, stream_id, method, path, authority)
| 69 | |
| 70 | |
| 71 | def h2_request(sock, h2_conn, stream_id, method, path, authority): |
| 72 | """Make an HTTP/2 request and return the response.""" |
| 73 | import h2.events |
| 74 | |
| 75 | # Send request |
| 76 | h2_conn.send_headers(stream_id, [ |
| 77 | (':method', method), |
| 78 | (':path', path), |
| 79 | (':authority', authority), |
| 80 | (':scheme', 'https'), |
| 81 | ], end_stream=True) |
| 82 | sock.sendall(h2_conn.data_to_send()) |
| 83 | |
| 84 | # Collect response |
| 85 | status = None |
| 86 | headers = {} |
| 87 | body = b'' |
| 88 | trailers = {} |
| 89 | |
| 90 | while True: |
| 91 | data = sock.recv(65536) |
| 92 | if not data: |
| 93 | break |
| 94 | |
| 95 | events = h2_conn.receive_data(data) |
| 96 | to_send = h2_conn.data_to_send() |
| 97 | if to_send: |
| 98 | sock.sendall(to_send) |
| 99 | |
| 100 | for event in events: |
| 101 | if isinstance(event, h2.events.ResponseReceived): |
| 102 | if event.stream_id == stream_id: |
| 103 | for name, value in event.headers: |
| 104 | if name == b':status': |
| 105 | status = int(value.decode()) |
| 106 | else: |
| 107 | headers[name.decode()] = value.decode() |
| 108 | |
| 109 | elif isinstance(event, h2.events.DataReceived): |
| 110 | if event.stream_id == stream_id: |
| 111 | body += event.data |
| 112 | |
| 113 | elif isinstance(event, h2.events.TrailersReceived): |
| 114 | if event.stream_id == stream_id: |
| 115 | for name, value in event.headers: |
| 116 | trailers[name.decode()] = value.decode() |
| 117 | |
| 118 | elif isinstance(event, h2.events.StreamEnded): |
| 119 | if event.stream_id == stream_id: |
| 120 | return { |
| 121 | 'status': status, |
| 122 | 'headers': headers, |
| 123 | 'body': body, |
| 124 | 'trailers': trailers, |
| 125 | } |
| 126 | |
| 127 | elif isinstance(event, h2.events.ConnectionTerminated): |
| 128 | raise RuntimeError(f"Connection terminated: {event.error_code}") |
no test coverage detected