aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@corte.si>2016-05-31 16:34:28 +1200
committerAldo Cortesi <aldo@corte.si>2016-05-31 16:34:28 +1200
commit2f526393d29b6a03e43d1f6240175b4dfb13dc7d (patch)
tree5139eb975211295b65da9cc9736d92cd1ac0f756
parentd98582664d8f234fe6a2c805f02d47686243379f (diff)
parent4de4223b2ddb4417be0d6a2fa0556d531a494091 (diff)
downloadmitmproxy-2f526393d29b6a03e43d1f6240175b4dfb13dc7d.tar.gz
mitmproxy-2f526393d29b6a03e43d1f6240175b4dfb13dc7d.tar.bz2
mitmproxy-2f526393d29b6a03e43d1f6240175b4dfb13dc7d.zip
Merge pull request #1178 from cortesi/pseudohdrs
Improve handling of HTTP2 pseudo-headers
-rw-r--r--mitmproxy/protocol/http2.py18
-rw-r--r--netlib/http/http2/connections.py14
-rw-r--r--netlib/multidict.py8
-rw-r--r--test/netlib/http/http2/test_connections.py5
4 files changed, 35 insertions, 10 deletions
diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py
index 30763c66..b4101676 100644
--- a/mitmproxy/protocol/http2.py
+++ b/mitmproxy/protocol/http2.py
@@ -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,
@@ -379,12 +387,14 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread):
self.response_arrived.wait()
status_code = int(self.response_headers.get(':status', 502))
+ headers = self.response_headers.copy()
+ headers.clear(":status")
return HTTPResponse(
http_version=b"HTTP/2.0",
status_code=status_code,
reason='',
- headers=self.response_headers,
+ headers=headers,
content=None,
timestamp_start=self.timestamp_start,
timestamp_end=self.timestamp_end,
@@ -404,10 +414,12 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread):
raise Http2ProtocolException("Zombie Stream")
def send_response_headers(self, response):
+ headers = response.headers.copy()
+ headers.insert(0, ":status", str(response.status_code))
self.client_conn.h2.safe_send_headers(
self.is_zombie,
self.client_stream_id,
- response.headers
+ headers
)
if self.zombie: # pragma: no cover
raise Http2ProtocolException("Zombie Stream")
diff --git a/netlib/http/http2/connections.py b/netlib/http/http2/connections.py
index b988d6ef..6b91f2ff 100644
--- a/netlib/http/http2/connections.py
+++ b/netlib/http/http2/connections.py
@@ -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
diff --git a/netlib/multidict.py b/netlib/multidict.py
index 98fde7e3..f8876cbd 100644
--- a/netlib/multidict.py
+++ b/netlib/multidict.py
@@ -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.
diff --git a/test/netlib/http/http2/test_connections.py b/test/netlib/http/http2/test_connections.py
index ff462ba6..69667d1c 100644
--- a/test/netlib/http/http2/test_connections.py
+++ b/test/netlib/http/http2/test_connections.py
@@ -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'