MCPcopy
hub / github.com/mitmproxy/mitmproxy / Http1Server

Class Http1Server

mitmproxy/proxy/layers/http/_http1.py:223–336  ·  view source on GitHub ↗

A simple HTTP/1 server with no pipelining support.

Source from the content-addressed store, hash-verified

221
222
223class Http1Server(Http1Connection):
224 """A simple HTTP/1 server with no pipelining support."""
225
226 ReceiveProtocolError = RequestProtocolError
227 ReceiveData = RequestData
228 ReceiveEndOfMessage = RequestEndOfMessage
229 stream_id: int
230
231 def __init__(self, context: Context):
232 super().__init__(context, context.client)
233 self.stream_id = 1
234
235 def send(self, event: HttpEvent) -> layer.CommandGenerator[None]:
236 assert event.stream_id == self.stream_id
237 if isinstance(event, ResponseHeaders):
238 self.response = response = event.response
239
240 if response.is_http2 or response.is_http3:
241 response = response.copy()
242 # Convert to an HTTP/1 response.
243 response.http_version = "HTTP/1.1"
244 # not everyone supports empty reason phrases, so we better make up one.
245 response.reason = status_codes.RESPONSES.get(response.status_code, "")
246 # Shall we set a Content-Length header here if there is none?
247 # For now, let's try to modify as little as possible.
248
249 raw = http1.assemble_response_head(response)
250 yield commands.SendData(self.conn, raw)
251 elif isinstance(event, ResponseData):
252 assert self.response
253 if "chunked" in self.response.headers.get("transfer-encoding", "").lower():
254 raw = b"%x\r\n%s\r\n" % (len(event.data), event.data)
255 else:
256 raw = event.data
257 if raw:
258 yield commands.SendData(self.conn, raw)
259 elif isinstance(event, ResponseEndOfMessage):
260 assert self.request
261 assert self.response
262 if (
263 self.request.method.upper() != "HEAD"
264 and "chunked"
265 in self.response.headers.get("transfer-encoding", "").lower()
266 ):
267 yield commands.SendData(self.conn, b"0\r\n\r\n")
268 yield from self.mark_done(response=True)
269 elif isinstance(event, ResponseProtocolError):
270 if not (self.conn.state & ConnectionState.CAN_WRITE):
271 return
272 status = event.code.http_status_code()
273 if not self.response and status is not None:
274 yield commands.SendData(
275 self.conn, make_error_response(status, event.message)
276 )
277 yield commands.CloseConnection(self.conn)
278 else:
279 raise AssertionError(f"Unexpected event: {event}")
280

Callers 5

test_simpleMethod · 0.90
test_connectMethod · 0.90
test_upgradeMethod · 0.90
test_upgrade_deniedMethod · 0.90
_handle_eventMethod · 0.85

Calls

no outgoing calls

Tested by 4

test_simpleMethod · 0.72
test_connectMethod · 0.72
test_upgradeMethod · 0.72
test_upgrade_deniedMethod · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…