mirror of
https://github.com/zhigang1992/mitmproxy.git
synced 2026-04-28 20:24:59 +08:00
Improve handling of pseudo-headers
- The canonical source for :method, :scheme and :path are the .method, .scheme and .path attributes on the request object. - These pseudo-headers are stripped after reading the request, and re-inserted just before sending. - The :authority header remains, and should be handled analagously to the Host header in HTTP1 with respect to display and user interaction.
This commit is contained in:
@@ -306,6 +306,9 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread):
|
||||
method = self.request_headers.get(':method', 'GET')
|
||||
scheme = self.request_headers.get(':scheme', 'https')
|
||||
path = self.request_headers.get(':path', '/')
|
||||
self.request_headers.clear(":method")
|
||||
self.request_headers.clear(":scheme")
|
||||
self.request_headers.clear(":path")
|
||||
host = None
|
||||
port = None
|
||||
|
||||
@@ -362,10 +365,15 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread):
|
||||
self.server_stream_id = self.server_conn.h2.get_next_available_stream_id()
|
||||
self.server_to_client_stream_ids[self.server_stream_id] = self.client_stream_id
|
||||
|
||||
headers = message.headers.copy()
|
||||
headers.insert(0, ":path", message.path)
|
||||
headers.insert(0, ":method", message.method)
|
||||
headers.insert(0, ":scheme", message.scheme)
|
||||
|
||||
self.server_conn.h2.safe_send_headers(
|
||||
self.is_zombie,
|
||||
self.server_stream_id,
|
||||
message.headers
|
||||
headers
|
||||
)
|
||||
self.server_conn.h2.safe_send_body(
|
||||
self.is_zombie,
|
||||
|
||||
@@ -98,6 +98,11 @@ class HTTP2Protocol(object):
|
||||
method = headers.get(':method', 'GET')
|
||||
scheme = headers.get(':scheme', 'https')
|
||||
path = headers.get(':path', '/')
|
||||
|
||||
headers.clear(":method")
|
||||
headers.clear(":scheme")
|
||||
headers.clear(":path")
|
||||
|
||||
host = None
|
||||
port = None
|
||||
|
||||
@@ -202,12 +207,9 @@ class HTTP2Protocol(object):
|
||||
|
||||
if ':authority' not in headers:
|
||||
headers.insert(0, b':authority', authority.encode('ascii'))
|
||||
if ':scheme' not in headers:
|
||||
headers.insert(0, b':scheme', request.scheme.encode('ascii'))
|
||||
if ':path' not in headers:
|
||||
headers.insert(0, b':path', request.path.encode('ascii'))
|
||||
if ':method' not in headers:
|
||||
headers.insert(0, b':method', request.method.encode('ascii'))
|
||||
headers.insert(0, b':scheme', request.scheme.encode('ascii'))
|
||||
headers.insert(0, b':path', request.path.encode('ascii'))
|
||||
headers.insert(0, b':method', request.method.encode('ascii'))
|
||||
|
||||
if hasattr(request, 'stream_id'):
|
||||
stream_id = request.stream_id
|
||||
|
||||
@@ -171,6 +171,14 @@ class _MultiDict(MutableMapping, Serializable):
|
||||
else:
|
||||
return super(_MultiDict, self).items()
|
||||
|
||||
def clear(self, key):
|
||||
"""
|
||||
Removes all items with the specified key, and does not raise an
|
||||
exception if the key does not exist.
|
||||
"""
|
||||
if key in self:
|
||||
del self[key]
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Get the MultiDict as a plain Python dict.
|
||||
|
||||
@@ -312,7 +312,10 @@ class TestReadRequest(tservers.ServerTestBase):
|
||||
req = protocol.read_request(NotImplemented)
|
||||
|
||||
assert req.stream_id
|
||||
assert req.headers.fields == ((b':method', b'GET'), (b':path', b'/'), (b':scheme', b'https'))
|
||||
assert req.headers.fields == ()
|
||||
assert req.method == "GET"
|
||||
assert req.path == "/"
|
||||
assert req.scheme == "https"
|
||||
assert req.content == b'foobar'
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user