aboutsummaryrefslogtreecommitdiffstats
path: root/netlib/http2/protocol.py
diff options
context:
space:
mode:
authorThomas Kriechbaumer <thomas@kriechbaumer.name>2015-06-12 14:41:54 +0200
committerThomas Kriechbaumer <thomas@kriechbaumer.name>2015-06-12 14:45:51 +0200
commita901bc3032747faf00adf82c3187d38213c070ca (patch)
treedaa1c4457c423c0d730517c591d261b3390c791d /netlib/http2/protocol.py
parent8ea157775debeccfa0f2fab3aa7e009d13ce4391 (diff)
downloadmitmproxy-a901bc3032747faf00adf82c3187d38213c070ca.tar.gz
mitmproxy-a901bc3032747faf00adf82c3187d38213c070ca.tar.bz2
mitmproxy-a901bc3032747faf00adf82c3187d38213c070ca.zip
http2: add response creation
Diffstat (limited to 'netlib/http2/protocol.py')
-rw-r--r--netlib/http2/protocol.py56
1 files changed, 41 insertions, 15 deletions
diff --git a/netlib/http2/protocol.py b/netlib/http2/protocol.py
index 4b69764f..56aee490 100644
--- a/netlib/http2/protocol.py
+++ b/netlib/http2/protocol.py
@@ -26,7 +26,8 @@ class HTTP2Protocol(object):
)
# "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
- CLIENT_CONNECTION_PREFACE = '505249202a20485454502f322e300d0a0d0a534d0d0a0d0a'.decode('hex')
+ CLIENT_CONNECTION_PREFACE =\
+ '505249202a20485454502f322e300d0a0d0a534d0d0a0d0a'.decode('hex')
ALPN_PROTO_H2 = 'h2'
@@ -38,6 +39,7 @@ class HTTP2Protocol(object):
self.current_stream_id = None
self.encoder = Encoder()
self.decoder = Decoder()
+ self.connection_preface_performed = False
def check_alpn(self):
alp = self.tcp_handler.get_alpn_proto_negotiated()
@@ -57,25 +59,36 @@ class HTTP2Protocol(object):
assert settings_ack_frame.flags & frame.Frame.FLAG_ACK
assert len(settings_ack_frame.settings) == 0
- def perform_server_connection_preface(self):
- magic_length = len(self.CLIENT_CONNECTION_PREFACE)
- magic = self.tcp_handler.rfile.safe_read(magic_length)
- assert magic == self.CLIENT_CONNECTION_PREFACE
+ def perform_server_connection_preface(self, force=False):
+ if force or not self.connection_preface_performed:
+ self.connection_preface_performed = True
- self.send_frame(frame.SettingsFrame(state=self))
- self._receive_settings()
- self._read_settings_ack()
+ magic_length = len(self.CLIENT_CONNECTION_PREFACE)
+ magic = self.tcp_handler.rfile.safe_read(magic_length)
+ assert magic == self.CLIENT_CONNECTION_PREFACE
- def perform_client_connection_preface(self):
- self.tcp_handler.wfile.write(self.CLIENT_CONNECTION_PREFACE)
+ self.send_frame(frame.SettingsFrame(state=self))
+ self._receive_settings()
+ self._read_settings_ack()
- self.send_frame(frame.SettingsFrame(state=self))
- self._receive_settings()
- self._read_settings_ack()
+ def perform_client_connection_preface(self, force=False):
+ if force or not self.connection_preface_performed:
+ self.connection_preface_performed = True
+
+ self.tcp_handler.wfile.write(self.CLIENT_CONNECTION_PREFACE)
+
+ self.send_frame(frame.SettingsFrame(state=self))
+ self._receive_settings()
+ self._read_settings_ack()
def next_stream_id(self):
if self.current_stream_id is None:
- self.current_stream_id = 1
+ if self.is_server:
+ # servers must use even stream ids
+ self.current_stream_id = 2
+ else:
+ # clients must use odd stream ids
+ self.current_stream_id = 1
else:
self.current_stream_id += 2
return self.current_stream_id
@@ -165,7 +178,8 @@ class HTTP2Protocol(object):
while True:
frm = self.read_frame()
- if isinstance(frm, frame.HeadersFrame) or isinstance(frm, frame.ContinuationFrame):
+ if isinstance(frm, frame.HeadersFrame)\
+ or isinstance(frm, frame.ContinuationFrame):
header_block_fragment += frm.header_block_fragment
if frm.flags & frame.Frame.FLAG_END_HEADERS:
if frm.flags & frame.Frame.FLAG_END_STREAM:
@@ -184,3 +198,15 @@ class HTTP2Protocol(object):
headers[header] = value
return headers, body
+
+ def create_response(self, code, headers=None, body=None):
+ if headers is None:
+ headers = []
+
+ headers = [(b':status', bytes(str(code)))] + headers
+
+ stream_id = self.next_stream_id()
+
+ return list(itertools.chain(
+ self._create_headers(headers, stream_id, end_stream=(body is None)),
+ self._create_body(body, stream_id)))