aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2015-09-16 18:45:22 +0200
committerMaximilian Hils <git@maximilianhils.com>2015-09-16 18:45:22 +0200
commit0af060897854e0e0fc8207af02d22bec9eacab12 (patch)
tree8f5206386bb481a813f1b6891c30d5d2d33924ba /libmproxy
parent436a9ea8398e25709f139fde609aa74e8fb3f3f8 (diff)
downloadmitmproxy-0af060897854e0e0fc8207af02d22bec9eacab12.tar.gz
mitmproxy-0af060897854e0e0fc8207af02d22bec9eacab12.tar.bz2
mitmproxy-0af060897854e0e0fc8207af02d22bec9eacab12.zip
adjust to netlib changes
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/cmdline.py8
-rw-r--r--libmproxy/console/common.py2
-rw-r--r--libmproxy/console/flowview.py2
-rw-r--r--libmproxy/dump.py2
-rw-r--r--libmproxy/exceptions.py8
-rw-r--r--libmproxy/flow.py12
-rw-r--r--libmproxy/models/http.py25
-rw-r--r--libmproxy/protocol/http.py191
-rw-r--r--libmproxy/protocol/http_replay.py31
-rw-r--r--libmproxy/protocol/tls.py6
-rw-r--r--libmproxy/proxy/root_context.py7
-rw-r--r--libmproxy/proxy/server.py4
-rw-r--r--libmproxy/web/app.py6
13 files changed, 137 insertions, 167 deletions
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py
index 3779953f..16678486 100644
--- a/libmproxy/cmdline.py
+++ b/libmproxy/cmdline.py
@@ -103,11 +103,15 @@ def parse_setheader(s):
def parse_server_spec(url):
- p = netlib.utils.parse_url(url)
- if not p or not p[1] or p[0] not in ("http", "https"):
+ try:
+ p = netlib.utils.parse_url(url)
+ if p[0] not in ("http", "https"):
+ raise ValueError()
+ except ValueError:
raise configargparse.ArgumentTypeError(
"Invalid server specification: %s" % url
)
+
address = Address(p[1:3])
scheme = p[0].lower()
return config.ServerSpec(scheme, address)
diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py
index ae3dd61e..13374b25 100644
--- a/libmproxy/console/common.py
+++ b/libmproxy/console/common.py
@@ -4,7 +4,7 @@ import urwid
import urwid.util
import os
-from netlib.http.semantics import CONTENT_MISSING
+from netlib.http import CONTENT_MISSING
import netlib.utils
from .. import utils
diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py
index 3e13fab4..8220c1e7 100644
--- a/libmproxy/console/flowview.py
+++ b/libmproxy/console/flowview.py
@@ -6,7 +6,7 @@ import sys
import urwid
from netlib import odict
-from netlib.http.semantics import CONTENT_MISSING, Headers
+from netlib.http import CONTENT_MISSING, Headers
from . import common, grideditor, signals, searchable, tabs
from . import flowdetailview
from .. import utils, controller, contentviews
diff --git a/libmproxy/dump.py b/libmproxy/dump.py
index 9fc9e1b8..3915d4c8 100644
--- a/libmproxy/dump.py
+++ b/libmproxy/dump.py
@@ -6,7 +6,7 @@ import traceback
import click
import itertools
-from netlib.http.semantics import CONTENT_MISSING
+from netlib.http import CONTENT_MISSING
import netlib.utils
from . import flow, filt, contentviews
from .exceptions import ContentViewException
diff --git a/libmproxy/exceptions.py b/libmproxy/exceptions.py
index d916f457..b55201be 100644
--- a/libmproxy/exceptions.py
+++ b/libmproxy/exceptions.py
@@ -34,17 +34,17 @@ class Socks5Exception(ProtocolException):
pass
-class HttpException(ProtocolException):
+class HttpProtocolException(ProtocolException):
pass
-class InvalidCredentials(HttpException):
+class ServerException(ProxyException):
pass
-class ServerException(ProxyException):
+class ContentViewException(ProxyException):
pass
-class ContentViewException(ProxyException):
+class ReplayException(ProxyException):
pass
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index d037d36e..d735b9ec 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -12,7 +12,8 @@ import urlparse
from netlib import wsgi
-from netlib.http.semantics import CONTENT_MISSING, Headers
+from netlib.exceptions import HttpException
+from netlib.http import CONTENT_MISSING, Headers, http1
import netlib.http
from . import controller, tnetstring, filt, script, version
from .onboarding import app
@@ -161,9 +162,8 @@ class StreamLargeBodies(object):
def run(self, flow, is_request):
r = flow.request if is_request else flow.response
- code = flow.response.code if flow.response else None
- expected_size = netlib.http.http1.HTTP1Protocol.expected_http_body_size(
- r.headers, is_request, flow.request.method, code
+ expected_size = http1.expected_http_body_size(
+ flow.request, flow.response if not is_request else None
)
if not (0 <= expected_size <= self.max_size):
# r.stream may already be a callable, which we want to preserve.
@@ -842,7 +842,7 @@ class FlowMaster(controller.Master):
host,
port,
path,
- (1, 1),
+ b"HTTP/1.1",
headers,
None,
None,
@@ -1000,7 +1000,7 @@ class FlowMaster(controller.Master):
try:
if self.stream_large_bodies:
self.stream_large_bodies.run(f, False)
- except netlib.http.HttpError:
+ except HttpException:
f.reply(Kill)
return
diff --git a/libmproxy/models/http.py b/libmproxy/models/http.py
index 0d5e53b5..0769d2d0 100644
--- a/libmproxy/models/http.py
+++ b/libmproxy/models/http.py
@@ -6,18 +6,17 @@ import time
from libmproxy import utils
from netlib import encoding
-from netlib.http import status_codes, Headers
+from netlib.http import status_codes, Headers, Request, Response, CONTENT_MISSING
from netlib.tcp import Address
-from netlib.http.semantics import Request, Response, CONTENT_MISSING
from .. import version, stateobject
from .flow import Flow
class MessageMixin(stateobject.StateObject):
_stateobject_attributes = dict(
- httpversion=tuple,
+ httpversion=bytes,
headers=Headers,
- body=str,
+ body=bytes,
timestamp_start=float,
timestamp_end=float
)
@@ -120,7 +119,7 @@ class HTTPRequest(MessageMixin, Request):
path: Path portion of the URL (not present in authority-form)
- httpversion: HTTP version tuple, e.g. (1,1)
+ httpversion: HTTP version, e.g. "HTTP/1.1"
headers: Headers object
@@ -186,11 +185,11 @@ class HTTPRequest(MessageMixin, Request):
_stateobject_attributes = MessageMixin._stateobject_attributes.copy()
_stateobject_attributes.update(
form_in=str,
- method=str,
- scheme=str,
- host=str,
+ method=bytes,
+ scheme=bytes,
+ host=bytes,
port=int,
- path=str,
+ path=bytes,
form_out=str,
is_replay=bool
)
@@ -267,7 +266,7 @@ class HTTPResponse(MessageMixin, Response):
Exposes the following attributes:
- httpversion: HTTP version tuple, e.g. (1, 0), (1, 1), or (2, 0)
+ httpversion: HTTP version, e.g. "HTTP/1.1"
status_code: HTTP response status code
@@ -312,7 +311,7 @@ class HTTPResponse(MessageMixin, Response):
_stateobject_attributes = MessageMixin._stateobject_attributes.copy()
_stateobject_attributes.update(
status_code=int,
- msg=str
+ msg=bytes
)
@classmethod
@@ -532,7 +531,7 @@ def make_error_response(status_code, message, headers=None):
)
return HTTPResponse(
- (1, 1), # FIXME: Should be a string.
+ b"HTTP/1.1",
status_code,
response,
headers,
@@ -543,7 +542,7 @@ def make_error_response(status_code, message, headers=None):
def make_connect_request(address):
address = Address.wrap(address)
return HTTPRequest(
- "authority", "CONNECT", None, address.host, address.port, None, (1, 1),
+ "authority", "CONNECT", None, address.host, address.port, None, b"HTTP/1.1",
Headers(), ""
)
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py
index 230f2be9..a876df41 100644
--- a/libmproxy/protocol/http.py
+++ b/libmproxy/protocol/http.py
@@ -6,14 +6,14 @@ import traceback
import six
from netlib import tcp
-from netlib.http import http1, HttpErrorConnClosed, HttpError, Headers
-from netlib.http.semantics import CONTENT_MISSING
+from netlib.exceptions import HttpException, HttpReadDisconnect
+from netlib.http import http1, Headers
+from netlib.http import CONTENT_MISSING
from netlib.tcp import NetLibError, Address
-from netlib.http.http1 import HTTP1Protocol
-from netlib.http.http2 import HTTP2Protocol
+from netlib.http.http2.connections import HTTP2Protocol
from netlib.http.http2.frame import GoAwayFrame, PriorityFrame, WindowUpdateFrame
from .. import utils
-from ..exceptions import InvalidCredentials, HttpException, ProtocolException
+from ..exceptions import HttpProtocolException, ProtocolException
from ..models import (
HTTPFlow, HTTPRequest, HTTPResponse, make_error_response, make_connect_response, Error
)
@@ -45,14 +45,14 @@ class _StreamingHttpLayer(_HttpLayer):
def read_response_headers(self):
raise NotImplementedError
- def read_response_body(self, headers, request_method, response_code, max_chunk_size=None):
+ def read_response_body(self, request, response):
raise NotImplementedError()
yield "this is a generator" # pragma: no cover
- def read_response(self, request_method):
+ def read_response(self, request):
response = self.read_response_headers()
- response.body = "".join(
- self.read_response_body(response.headers, request_method, response.code)
+ response.body = b"".join(
+ self.read_response_body(request, response)
)
return response
@@ -64,7 +64,7 @@ class _StreamingHttpLayer(_HttpLayer):
def send_response(self, response):
if response.body == CONTENT_MISSING:
- raise HttpError(502, "Cannot assemble flow with CONTENT_MISSING")
+ raise HttpException("Cannot assemble flow with CONTENT_MISSING")
self.send_response_headers(response)
self.send_response_body(response, [response.body])
@@ -73,48 +73,31 @@ class Http1Layer(_StreamingHttpLayer):
def __init__(self, ctx, mode):
super(Http1Layer, self).__init__(ctx)
self.mode = mode
- self.client_protocol = HTTP1Protocol(self.client_conn)
- self.server_protocol = HTTP1Protocol(self.server_conn)
def read_request(self):
- return HTTPRequest.from_protocol(
- self.client_protocol,
- body_size_limit=self.config.body_size_limit
- )
+ req = http1.read_request(self.client_conn.rfile, body_size_limit=self.config.body_size_limit)
+ return HTTPRequest.wrap(req)
def send_request(self, request):
- self.server_conn.send(self.server_protocol.assemble(request))
+ self.server_conn.wfile.write(http1.assemble_request(request))
+ self.server_conn.wfile.flush()
def read_response_headers(self):
- return HTTPResponse.from_protocol(
- self.server_protocol,
- request_method=None, # does not matter if we don't read the body.
- body_size_limit=self.config.body_size_limit,
- include_body=False
- )
+ resp = http1.read_response_head(self.server_conn.rfile)
+ return HTTPResponse.wrap(resp)
- def read_response_body(self, headers, request_method, response_code, max_chunk_size=None):
- return self.server_protocol.read_http_body_chunked(
- headers,
- self.config.body_size_limit,
- request_method,
- response_code,
- False,
- max_chunk_size
- )
+ def read_response_body(self, request, response):
+ expected_size = http1.expected_http_body_size(request, response)
+ return http1.read_body(self.server_conn.rfile, expected_size, self.config.body_size_limit)
def send_response_headers(self, response):
- h = self.client_protocol._assemble_response_first_line(response)
- self.client_conn.wfile.write(h + "\r\n")
- h = self.client_protocol._assemble_response_headers(
- response,
- preserve_transfer_encoding=True
- )
- self.client_conn.wfile.write(h + "\r\n")
+ raw = http1.assemble_response_head(response, preserve_transfer_encoding=True)
+ self.client_conn.wfile.write(raw)
self.client_conn.wfile.flush()
def send_response_body(self, response, chunks):
- if self.client_protocol.has_chunked_encoding(response.headers):
+ if b"chunked" in response.headers.get(b"transfer-encoding", b"").lower():
+ # TODO: Move this into netlib.http.http1
chunks = itertools.chain(
(
"{:x}\r\n{}\r\n".format(len(chunk), chunk)
@@ -127,36 +110,24 @@ class Http1Layer(_StreamingHttpLayer):
self.client_conn.wfile.flush()
def check_close_connection(self, flow):
- close_connection = (
- http1.HTTP1Protocol.connection_close(
- flow.request.httpversion,
- flow.request.headers
- ) or http1.HTTP1Protocol.connection_close(
- flow.response.httpversion,
- flow.response.headers
- ) or http1.HTTP1Protocol.expected_http_body_size(
- flow.response.headers,
- False,
- flow.request.method,
- flow.response.code) == -1
+ request_close = http1.connection_close(
+ flow.request.httpversion,
+ flow.request.headers
)
+ response_close = http1.connection_close(
+ flow.response.httpversion,
+ flow.response.headers
+ )
+ read_until_eof = http1.expected_http_body_size(flow.request, flow.response) == -1
+ close_connection = request_close or response_close or read_until_eof
if flow.request.form_in == "authority" and flow.response.code == 200:
- # Workaround for
- # https://github.com/mitmproxy/mitmproxy/issues/313: Some
- # proxies (e.g. Charles) send a CONNECT response with HTTP/1.0
+ # Workaround for https://github.com/mitmproxy/mitmproxy/issues/313:
+ # Charles Proxy sends a CONNECT response with HTTP/1.0
# and no Content-Length header
return False
return close_connection
- def connect(self):
- self.ctx.connect()
- self.server_protocol = HTTP1Protocol(self.server_conn)
-
- def set_server(self, *args, **kwargs):
- self.ctx.set_server(*args, **kwargs)
- self.server_protocol = HTTP1Protocol(self.server_conn)
-
def __call__(self):
layer = HttpLayer(self, self.mode)
layer()
@@ -184,10 +155,10 @@ class Http2Layer(_HttpLayer):
# TODO: implement flow control and WINDOW_UPDATE frames
self.server_conn.send(self.server_protocol.assemble(message))
- def read_response(self, request_method):
+ def read_response(self, request):
return HTTPResponse.from_protocol(
self.server_protocol,
- request_method=request_method,
+ request_method=request.method,
body_size_limit=self.config.body_size_limit,
include_body=True,
stream_id=self._stream_id
@@ -295,7 +266,7 @@ class UpstreamConnectLayer(Layer):
def _send_connect_request(self):
self.send_request(self.connect_request)
- resp = self.read_response("CONNECT")
+ resp = self.read_response(self.connect_request)
if resp.code != 200:
raise ProtocolException("Reconnect: Upstream server refuses CONNECT request")
@@ -337,28 +308,31 @@ class HttpLayer(Layer):
self.__original_server_conn = self.server_conn
while True:
try:
- flow = HTTPFlow(self.client_conn, self.server_conn, live=self)
+ request = self.read_request()
+ self.log("request", "debug", [repr(request)])
- try:
- request = self.read_request()
- except tcp.NetLibError:
- # don't throw an error for disconnects that happen
- # before/between requests.
+ # Handle Proxy Authentication
+ if not self.authenticate(request):
return
- self.log("request", "debug", [repr(request)])
+ # Make sure that the incoming request matches our expectations
+ self.validate_request(request)
- # Handle Proxy Authentication
- self.authenticate(request)
+ except HttpReadDisconnect:
+ # don't throw an error for disconnects that happen before/between requests.
+ return
+ except (HttpException, NetLibError) as e:
+ self.send_error_response(400, repr(e))
+ six.reraise(ProtocolException, ProtocolException("Error in HTTP connection: %s" % repr(e)), sys.exc_info()[2])
+
+ try:
+ flow = HTTPFlow(self.client_conn, self.server_conn, live=self)
# Regular Proxy Mode: Handle CONNECT
if self.mode == "regular" and request.form_in == "authority":
self.handle_regular_mode_connect(request)
return
- # Make sure that the incoming request matches our expectations
- self.validate_request(request)
-
flow.request = request
self.process_request_hook(flow)
@@ -384,30 +358,26 @@ class HttpLayer(Layer):
self.handle_upstream_mode_connect(flow.request.copy())
return
- except (HttpErrorConnClosed, NetLibError, HttpError, ProtocolException) as e:
- error_propagated = False
- if flow.request and not flow.response:
+ except (HttpException, NetLibError) as e:
+ self.send_error_response(502, repr(e))
+
+ if not flow.response:
flow.error = Error(str(e))
self.channel.ask("error", flow)
self.log(traceback.format_exc(), "debug")
- error_propagated = True
-
- try:
- self.send_response(make_error_response(
- getattr(e, "code", 502),
- repr(e)
- ))
- except NetLibError:
- pass
-
- if not error_propagated:
- if isinstance(e, ProtocolException):
- six.reraise(ProtocolException, e, sys.exc_info()[2])
- else:
- six.reraise(ProtocolException, ProtocolException("Error in HTTP connection: %s" % repr(e)), sys.exc_info()[2])
+ return
+ else:
+ six.reraise(ProtocolException, ProtocolException("Error in HTTP connection: %s" % repr(e)), sys.exc_info()[2])
finally:
flow.live = False
+ def send_error_response(self, code, message):
+ try:
+ response = make_error_response(code, message)
+ self.send_response(response)
+ except NetLibError:
+ pass
+
def change_upstream_proxy_server(self, address):
# Make set_upstream_proxy_server always available,
# even if there's no UpstreamConnectLayer
@@ -435,10 +405,8 @@ class HttpLayer(Layer):
# First send the headers and then transfer the response incrementally
self.send_response_headers(flow.response)
chunks = self.read_response_body(
- flow.response.headers,
- flow.request.method,
- flow.response.code,
- max_chunk_size=4096
+ flow.request,
+ flow.response
)
if callable(flow.response.stream):
chunks = flow.response.stream(chunks)
@@ -451,11 +419,11 @@ class HttpLayer(Layer):
if self.supports_streaming:
flow.response = self.read_response_headers()
else:
- flow.response = self.read_response(flow.request.method)
+ flow.response = self.read_response(flow.request)
try:
get_response()
- except (tcp.NetLibError, HttpErrorConnClosed) as v:
+ except (tcp.NetLibError, HttpException) as v:
self.log(
"server communication error: %s" % repr(v),
level="debug"
@@ -485,10 +453,9 @@ class HttpLayer(Layer):
if flow.response.stream:
flow.response.content = CONTENT_MISSING
else:
- flow.response.content = "".join(self.read_response_body(
- flow.response.headers,
- flow.request.method,
- flow.response.code
+ flow.response.content = b"".join(self.read_response_body(
+ flow.request,
+ flow.response
))
flow.response.timestamp_end = utils.timestamp()
@@ -543,7 +510,7 @@ class HttpLayer(Layer):
if not self.server_conn:
self.connect()
if tls:
- raise HttpException("Cannot change scheme in upstream proxy mode.")
+ raise HttpProtocolException("Cannot change scheme in upstream proxy mode.")
"""
# This is a very ugly (untested) workaround to solve a very ugly problem.
if self.server_conn and self.server_conn.tls_established and not ssl:
@@ -561,12 +528,10 @@ class HttpLayer(Layer):
def validate_request(self, request):
if request.form_in == "absolute" and request.scheme != "http":
- self.send_response(
- make_error_response(400, "Invalid request scheme: %s" % request.scheme))
raise HttpException("Invalid request scheme: %s" % request.scheme)
expected_request_forms = {
- "regular": ("absolute",), # an authority request would already be handled.
+ "regular": ("authority", "absolute",),
"upstream": ("authority", "absolute"),
"transparent": ("relative",)
}
@@ -576,10 +541,9 @@ class HttpLayer(Layer):
err_message = "Invalid HTTP request form (expected: %s, got: %s)" % (
" or ".join(allowed_request_forms), request.form_in
)
- self.send_response(make_error_response(400, err_message))
raise HttpException(err_message)
- if self.mode == "regular":
+ if self.mode == "regular" and request.form_in == "absolute":
request.form_out = "relative"
def authenticate(self, request):
@@ -592,4 +556,5 @@ class HttpLayer(Layer):
"Proxy Authentication Required",
Headers(**self.config.authenticator.auth_challenge_headers())
))
- raise InvalidCredentials("Proxy Authentication Required")
+ return False
+ return True
diff --git a/libmproxy/protocol/http_replay.py b/libmproxy/protocol/http_replay.py
index a9ee5506..9d61d75c 100644
--- a/libmproxy/protocol/http_replay.py
+++ b/libmproxy/protocol/http_replay.py
@@ -1,8 +1,9 @@
from __future__ import (absolute_import, print_function, division)
import threading
+from libmproxy.exceptions import ReplayException
+from netlib.exceptions import HttpException
+from netlib.http import http1
-from netlib.http import HttpError
-from netlib.http.http1 import HTTP1Protocol
from netlib.tcp import NetLibError
from ..controller import Channel
from ..models import Error, HTTPResponse, ServerConnection, make_connect_request
@@ -47,13 +48,17 @@ class RequestReplayThread(threading.Thread):
server_address = self.config.upstream_server.address
server = ServerConnection(server_address)
server.connect()
- protocol = HTTP1Protocol(server)
if r.scheme == "https":
connect_request = make_connect_request((r.host, r.port))
- server.send(protocol.assemble(connect_request))
- resp = protocol.read_response("CONNECT")
+ server.wfile.write(http1.assemble_request(connect_request))
+ server.wfile.flush()
+ resp = http1.read_response(
+ server.rfile,
+ connect_request,
+ body_size_limit=self.config.body_size_limit
+ )
if resp.code != 200:
- raise HttpError(502, "Upstream server refuses CONNECT request")
+ raise ReplayException("Upstream server refuses CONNECT request")
server.establish_ssl(
self.config.clientcerts,
sni=self.flow.server_conn.sni
@@ -65,7 +70,6 @@ class RequestReplayThread(threading.Thread):
server_address = (r.host, r.port)
server = ServerConnection(server_address)
server.connect()
- protocol = HTTP1Protocol(server)
if r.scheme == "https":
server.establish_ssl(
self.config.clientcerts,
@@ -73,18 +77,19 @@ class RequestReplayThread(threading.Thread):
)
r.form_out = "relative"
- server.send(protocol.assemble(r))
+ server.wfile.write(http1.assemble_request(r))
+ server.wfile.flush()
self.flow.server_conn = server
- self.flow.response = HTTPResponse.from_protocol(
- protocol,
- r.method,
- body_size_limit=self.config.body_size_limit,
+ self.flow.response = http1.read_response(
+ server.rfile,
+ r,
+ body_size_limit=self.config.body_size_limit
)
if self.channel:
response_reply = self.channel.ask("response", self.flow)
if response_reply == Kill:
raise Kill()
- except (HttpError, NetLibError) as v:
+ except (ReplayException, HttpException, NetLibError) as v:
self.flow.error = Error(repr(v))
if self.channel:
self.channel.ask("error", self.flow)
diff --git a/libmproxy/protocol/tls.py b/libmproxy/protocol/tls.py
index 2935ca9f..cf303ca1 100644
--- a/libmproxy/protocol/tls.py
+++ b/libmproxy/protocol/tls.py
@@ -7,7 +7,7 @@ from construct import ConstructError
import six
from netlib.tcp import NetLibError, NetLibInvalidCertificateError
-from netlib.http.http1 import HTTP1Protocol
+from netlib.http import ALPN_PROTO_HTTP1
from ..contrib.tls._constructs import ClientHello
from ..exceptions import ProtocolException, TlsException, ClientHandshakeException
from .base import Layer
@@ -367,8 +367,8 @@ class TlsLayer(Layer):
"""
# This gets triggered if we haven't established an upstream connection yet.
- default_alpn = HTTP1Protocol.ALPN_PROTO_HTTP1
- # alpn_preference = netlib.http.http2.HTTP2Protocol.ALPN_PROTO_H2
+ default_alpn = ALPN_PROTO_HTTP1
+ # alpn_preference = ALPN_PROTO_H2
if self.alpn_for_client_connection in options:
choice = bytes(self.alpn_for_client_connection)
diff --git a/libmproxy/proxy/root_context.py b/libmproxy/proxy/root_context.py
index 54bea1db..72243c59 100644
--- a/libmproxy/proxy/root_context.py
+++ b/libmproxy/proxy/root_context.py
@@ -5,8 +5,7 @@ import sys
import six
from libmproxy.exceptions import ProtocolException
-from netlib.http.http1 import HTTP1Protocol
-from netlib.http.http2 import HTTP2Protocol
+from netlib.http import ALPN_PROTO_H2, ALPN_PROTO_HTTP1
from netlib.tcp import NetLibError
from ..protocol import (
RawTCPLayer, TlsLayer, Http1Layer, Http2Layer, is_tls_record_magic, ServerConnectionMixin
@@ -85,9 +84,9 @@ class RootContext(object):
# 5. Check for TLS ALPN (HTTP1/HTTP2)
if isinstance(top_layer, TlsLayer):
alpn = top_layer.client_conn.get_alpn_proto_negotiated()
- if alpn == HTTP2Protocol.ALPN_PROTO_H2:
+ if alpn == ALPN_PROTO_H2:
return Http2Layer(top_layer, 'transparent')
- if alpn == HTTP1Protocol.ALPN_PROTO_HTTP1:
+ if alpn == ALPN_PROTO_HTTP1:
return Http1Layer(top_layer, 'transparent')
# 6. Check for raw tcp mode
diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py
index 88448172..8b286458 100644
--- a/libmproxy/proxy/server.py
+++ b/libmproxy/proxy/server.py
@@ -6,7 +6,7 @@ import socket
import six
from netlib import tcp
-from netlib.http.http1 import HTTP1Protocol
+from netlib.http.http1 import assemble_response
from netlib.tcp import NetLibError
from ..exceptions import ProtocolException, ServerException, ClientHandshakeException
from ..protocol import Kill
@@ -138,7 +138,7 @@ class ConnectionHandler(object):
# understandable by HTTP clients and humans.
try:
error_response = make_error_response(502, repr(e))
- self.client_conn.send(HTTP1Protocol().assemble(error_response))
+ self.client_conn.send(assemble_response(error_response))
except NetLibError:
pass
except Exception:
diff --git a/libmproxy/web/app.py b/libmproxy/web/app.py
index 2517e7ad..8eee6dce 100644
--- a/libmproxy/web/app.py
+++ b/libmproxy/web/app.py
@@ -128,12 +128,10 @@ class FlowHandler(RequestHandler):
if a == "request":
request = flow.request
for k, v in b.iteritems():
- if k in ["method", "scheme", "host", "path"]:
+ if k in ["method", "scheme", "host", "path", "httpversion"]:
setattr(request, k, str(v))
elif k == "port":
request.port = int(v)
- elif k == "httpversion":
- request.httpversion = tuple(int(x) for x in v)
elif k == "headers":
request.headers.load_state(v)
else:
@@ -147,7 +145,7 @@ class FlowHandler(RequestHandler):
elif k == "code":
response.code = int(v)
elif k == "httpversion":
- response.httpversion = tuple(int(x) for x in v)
+ response.httpversion = str(v)
elif k == "headers":
response.headers.load_state(v)
else: