aboutsummaryrefslogtreecommitdiffstats
path: root/netlib/http/http2
diff options
context:
space:
mode:
Diffstat (limited to 'netlib/http/http2')
-rw-r--r--netlib/http/http2/__init__.py8
-rw-r--r--netlib/http/http2/connections.py (renamed from netlib/http/http2/protocol.py)30
-rw-r--r--netlib/http/http2/frame.py39
3 files changed, 55 insertions, 22 deletions
diff --git a/netlib/http/http2/__init__.py b/netlib/http/http2/__init__.py
index 5acf7696..7043d36f 100644
--- a/netlib/http/http2/__init__.py
+++ b/netlib/http/http2/__init__.py
@@ -1,2 +1,6 @@
-from frame import *
-from protocol import *
+from __future__ import absolute_import, print_function, division
+from .connections import HTTP2Protocol
+
+__all__ = [
+ "HTTP2Protocol"
+]
diff --git a/netlib/http/http2/protocol.py b/netlib/http/http2/connections.py
index b6d376d3..5220d5d2 100644
--- a/netlib/http/http2/protocol.py
+++ b/netlib/http/http2/connections.py
@@ -3,8 +3,8 @@ import itertools
import time
from hpack.hpack import Encoder, Decoder
-from netlib import http, utils
-from netlib.http import semantics
+from ... import utils
+from .. import Headers, Response, Request, ALPN_PROTO_H2
from . import frame
@@ -15,7 +15,7 @@ class TCPHandler(object):
self.wfile = wfile
-class HTTP2Protocol(semantics.ProtocolMixin):
+class HTTP2Protocol(object):
ERROR_CODES = utils.BiDi(
NO_ERROR=0x0,
@@ -36,8 +36,6 @@ class HTTP2Protocol(semantics.ProtocolMixin):
CLIENT_CONNECTION_PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
- ALPN_PROTO_H2 = 'h2'
-
def __init__(
self,
tcp_handler=None,
@@ -62,6 +60,7 @@ class HTTP2Protocol(semantics.ProtocolMixin):
def read_request(
self,
+ __rfile,
include_body=True,
body_size_limit=None,
allow_empty=False,
@@ -111,7 +110,7 @@ class HTTP2Protocol(semantics.ProtocolMixin):
port = 80 if scheme == 'http' else 443
port = int(port)
- request = http.Request(
+ request = Request(
form_in,
method,
scheme,
@@ -131,6 +130,7 @@ class HTTP2Protocol(semantics.ProtocolMixin):
def read_response(
self,
+ __rfile,
request_method='',
body_size_limit=None,
include_body=True,
@@ -159,7 +159,7 @@ class HTTP2Protocol(semantics.ProtocolMixin):
else:
timestamp_end = None
- response = http.Response(
+ response = Response(
(2, 0),
int(headers.get(':status', 502)),
"",
@@ -172,8 +172,16 @@ class HTTP2Protocol(semantics.ProtocolMixin):
return response
+ def assemble(self, message):
+ if isinstance(message, Request):
+ return self.assemble_request(message)
+ elif isinstance(message, Response):
+ return self.assemble_response(message)
+ else:
+ raise ValueError("HTTP message not supported.")
+
def assemble_request(self, request):
- assert isinstance(request, semantics.Request)
+ assert isinstance(request, Request)
authority = self.tcp_handler.sni if self.tcp_handler.sni else self.tcp_handler.address.host
if self.tcp_handler.address.port != 443:
@@ -200,7 +208,7 @@ class HTTP2Protocol(semantics.ProtocolMixin):
self._create_body(request.body, stream_id)))
def assemble_response(self, response):
- assert isinstance(response, semantics.Response)
+ assert isinstance(response, Response)
headers = response.headers.copy()
@@ -275,7 +283,7 @@ class HTTP2Protocol(semantics.ProtocolMixin):
def check_alpn(self):
alp = self.tcp_handler.get_alpn_proto_negotiated()
- if alp != self.ALPN_PROTO_H2:
+ if alp != ALPN_PROTO_H2:
raise NotImplementedError(
"HTTP2Protocol can not handle unknown ALP: %s" % alp)
return True
@@ -405,7 +413,7 @@ class HTTP2Protocol(semantics.ProtocolMixin):
else:
self._handle_unexpected_frame(frm)
- headers = http.Headers(
+ headers = Headers(
[[str(k), str(v)] for k, v in self.decoder.decode(header_block_fragment)]
)
diff --git a/netlib/http/http2/frame.py b/netlib/http/http2/frame.py
index b36b3adf..cb2cde99 100644
--- a/netlib/http/http2/frame.py
+++ b/netlib/http/http2/frame.py
@@ -1,12 +1,31 @@
-import sys
+from __future__ import absolute_import, print_function, division
import struct
from hpack.hpack import Encoder, Decoder
-from .. import utils
+from ...utils import BiDi
+from ...exceptions import HttpSyntaxException
-class FrameSizeError(Exception):
- pass
+ERROR_CODES = BiDi(
+ NO_ERROR=0x0,
+ PROTOCOL_ERROR=0x1,
+ INTERNAL_ERROR=0x2,
+ FLOW_CONTROL_ERROR=0x3,
+ SETTINGS_TIMEOUT=0x4,
+ STREAM_CLOSED=0x5,
+ FRAME_SIZE_ERROR=0x6,
+ REFUSED_STREAM=0x7,
+ CANCEL=0x8,
+ COMPRESSION_ERROR=0x9,
+ CONNECT_ERROR=0xa,
+ ENHANCE_YOUR_CALM=0xb,
+ INADEQUATE_SECURITY=0xc,
+ HTTP_1_1_REQUIRED=0xd
+)
+
+CLIENT_CONNECTION_PREFACE = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+
+ALPN_PROTO_H2 = b'h2'
class Frame(object):
@@ -30,7 +49,9 @@ class Frame(object):
length=0,
flags=FLAG_NO_FLAGS,
stream_id=0x0):
- valid_flags = reduce(lambda x, y: x | y, self.VALID_FLAGS, 0x0)
+ valid_flags = 0
+ for flag in self.VALID_FLAGS:
+ valid_flags |= flag
if flags | valid_flags != valid_flags:
raise ValueError('invalid flags detected.')
@@ -61,7 +82,7 @@ class Frame(object):
SettingsFrame.SETTINGS.SETTINGS_MAX_FRAME_SIZE]
if length > max_frame_size:
- raise FrameSizeError(
+ raise HttpSyntaxException(
"Frame size exceeded: %d, but only %d allowed." % (
length, max_frame_size))
@@ -80,7 +101,7 @@ class Frame(object):
stream_id = fields[4]
if raw_header[:4] == b'HTTP': # pragma no cover
- print >> sys.stderr, "WARNING: This looks like an HTTP/1 connection!"
+ raise HttpSyntaxException("Expected HTTP2 Frame, got HTTP/1 connection")
cls._check_frame_size(length, state)
@@ -339,7 +360,7 @@ class SettingsFrame(Frame):
TYPE = 0x4
VALID_FLAGS = [Frame.FLAG_ACK]
- SETTINGS = utils.BiDi(
+ SETTINGS = BiDi(
SETTINGS_HEADER_TABLE_SIZE=0x1,
SETTINGS_ENABLE_PUSH=0x2,
SETTINGS_MAX_CONCURRENT_STREAMS=0x3,
@@ -366,7 +387,7 @@ class SettingsFrame(Frame):
def from_bytes(cls, state, length, flags, stream_id, payload):
f = cls(state=state, length=length, flags=flags, stream_id=stream_id)
- for i in xrange(0, len(payload), 6):
+ for i in range(0, len(payload), 6):
identifier, value = struct.unpack("!HL", payload[i:i + 6])
f.settings[identifier] = value