experimental: don't interfere with headers, fix #93

This commit is contained in:
Maximilian Hils 2015-09-18 18:07:38 +02:00
parent 66d21fa4ba
commit 2d4a5fb116
7 changed files with 40 additions and 46 deletions

View File

@ -922,7 +922,7 @@ class FlowMaster(controller.Master):
if f.request: if f.request:
f.backup() f.backup()
f.request.is_replay = True f.request.is_replay = True
if f.request.content: if "Content-Length" in f.request.headers:
f.request.headers["Content-Length"] = str(len(f.request.content)) f.request.headers["Content-Length"] = str(len(f.request.content))
f.response = None f.response = None
f.error = None f.error = None

View File

@ -549,7 +549,6 @@ def make_connect_request(address):
def make_connect_response(http_version): def make_connect_response(http_version):
headers = Headers( headers = Headers(
Content_Length="0",
Proxy_Agent=version.NAMEVERSION Proxy_Agent=version.NAMEVERSION
) )
return HTTPResponse( return HTTPResponse(

View File

@ -27,13 +27,13 @@ as late as possible; this makes server replay without any outgoing connections p
from __future__ import (absolute_import, print_function, division) from __future__ import (absolute_import, print_function, division)
from .base import Layer, ServerConnectionMixin, Kill from .base import Layer, ServerConnectionMixin, Kill
from .http import Http1Layer, Http2Layer from .http import Http1Layer, UpstreamConnectLayer, Http2Layer
from .tls import TlsLayer, is_tls_record_magic from .tls import TlsLayer, is_tls_record_magic
from .rawtcp import RawTCPLayer from .rawtcp import RawTCPLayer
__all__ = [ __all__ = [
"Layer", "ServerConnectionMixin", "Kill", "Layer", "ServerConnectionMixin", "Kill",
"Http1Layer", "Http2Layer", "Http1Layer", "UpstreamConnectLayer", "Http2Layer",
"TlsLayer", "is_tls_record_magic", "TlsLayer", "is_tls_record_magic",
"RawTCPLayer" "RawTCPLayer"
] ]

View File

@ -1,5 +1,6 @@
from __future__ import (absolute_import, print_function, division) from __future__ import (absolute_import, print_function, division)
import threading import threading
import traceback
from libmproxy.exceptions import ReplayException from libmproxy.exceptions import ReplayException
from netlib.exceptions import HttpException, TcpException from netlib.exceptions import HttpException, TcpException
from netlib.http import http1 from netlib.http import http1
@ -97,5 +98,8 @@ class RequestReplayThread(threading.Thread):
# first place. # first place.
from ..proxy.root_context import Log from ..proxy.root_context import Log
self.channel.tell("log", Log("Connection killed", "info")) self.channel.tell("log", Log("Connection killed", "info"))
except Exception:
from ..proxy.root_context import Log
self.channel.tell("log", Log(traceback.format_exc(), "error"))
finally: finally:
r.form_out = form_out_backup r.form_out = form_out_backup

View File

@ -8,7 +8,8 @@ from libmproxy.exceptions import ProtocolException
from netlib.exceptions import TcpException from netlib.exceptions import TcpException
from netlib.http import ALPN_PROTO_H2, ALPN_PROTO_HTTP1 from netlib.http import ALPN_PROTO_H2, ALPN_PROTO_HTTP1
from ..protocol import ( from ..protocol import (
RawTCPLayer, TlsLayer, Http1Layer, Http2Layer, is_tls_record_magic, ServerConnectionMixin RawTCPLayer, TlsLayer, Http1Layer, Http2Layer, is_tls_record_magic, ServerConnectionMixin,
UpstreamConnectLayer
) )
from .modes import HttpProxy, HttpUpstreamProxy, ReverseProxy from .modes import HttpProxy, HttpUpstreamProxy, ReverseProxy
@ -63,7 +64,7 @@ class RootContext(object):
# in which case we need some form of TLS layer. # in which case we need some form of TLS layer.
if isinstance(top_layer, ReverseProxy): if isinstance(top_layer, ReverseProxy):
return TlsLayer(top_layer, client_tls, top_layer.server_tls) return TlsLayer(top_layer, client_tls, top_layer.server_tls)
if isinstance(top_layer, ServerConnectionMixin): if isinstance(top_layer, ServerConnectionMixin) or isinstance(top_layer, UpstreamConnectLayer):
return TlsLayer(top_layer, client_tls, client_tls) return TlsLayer(top_layer, client_tls, client_tls)
# 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed. # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed.

View File

@ -1,6 +1,7 @@
from setuptools import setup, find_packages from setuptools import setup, find_packages
from codecs import open from codecs import open
import os import os
import sys
from libmproxy import version from libmproxy import version
# Based on https://github.com/pypa/sampleproject/blob/master/setup.py # Based on https://github.com/pypa/sampleproject/blob/master/setup.py
@ -47,6 +48,11 @@ dev_deps = {
"sphinx-autobuild>=0.5.2", "sphinx-autobuild>=0.5.2",
"sphinxcontrib-documentedlist>=0.2", "sphinxcontrib-documentedlist>=0.2",
} }
example_deps = {
"pytz",
"harparser",
"beautifulsoup4",
}
# Add *all* script dependencies to developer dependencies. # Add *all* script dependencies to developer dependencies.
for script_deps in scripts.values(): for script_deps in scripts.values():
dev_deps.update(script_deps) dev_deps.update(script_deps)
@ -60,6 +66,9 @@ if os.name == "nt":
for script_deps in scripts.values(): for script_deps in scripts.values():
deps.update(script_deps) deps.update(script_deps)
if sys.version_info < (3, 4):
example_deps.add("enum34")
console_scripts = ["%s = libmproxy.main:%s" % (s, s) for s in scripts.keys()] console_scripts = ["%s = libmproxy.main:%s" % (s, s) for s in scripts.keys()]
setup( setup(
@ -101,11 +110,6 @@ setup(
"protobuf>=2.5.0", "protobuf>=2.5.0",
"cssutils>=1.0" "cssutils>=1.0"
], ],
'examples': [ 'examples': list(example_deps)
"pytz",
"harparser",
"beautifulsoup4",
"enum34"
]
} }
) )

View File

@ -118,17 +118,18 @@ class TcpMixin:
del self._ignore_backup del self._ignore_backup
def test_ignore(self): def test_ignore(self):
spec = '304:h"Alternate-Protocol"="mitmproxy-will-remove-this"' n = self.pathod("304")
n = self.pathod(spec)
self._ignore_on() self._ignore_on()
i = self.pathod(spec) i = self.pathod("305")
i2 = self.pathod(spec) i2 = self.pathod("306")
self._ignore_off() self._ignore_off()
assert i.status_code == i2.status_code == n.status_code == 304 assert n.status_code == 304
assert "Alternate-Protocol" in i.headers assert i.status_code == 305
assert "Alternate-Protocol" in i2.headers assert i2.status_code == 306
assert "Alternate-Protocol" not in n.headers assert any(f.response.status_code == 304 for f in self.master.state.flows)
assert not any(f.response.status_code == 305 for f in self.master.state.flows)
assert not any(f.response.status_code == 306 for f in self.master.state.flows)
# Test that we get the original SSL cert # Test that we get the original SSL cert
if self.ssl: if self.ssl:
@ -161,17 +162,18 @@ class TcpMixin:
del self._tcpproxy_backup del self._tcpproxy_backup
def test_tcp(self): def test_tcp(self):
spec = '304:h"Alternate-Protocol"="mitmproxy-will-remove-this"' n = self.pathod("304")
n = self.pathod(spec)
self._tcpproxy_on() self._tcpproxy_on()
i = self.pathod(spec) i = self.pathod("305")
i2 = self.pathod(spec) i2 = self.pathod("306")
self._tcpproxy_off() self._tcpproxy_off()
assert i.status_code == i2.status_code == n.status_code == 304 assert n.status_code == 304
assert "Alternate-Protocol" in i.headers assert i.status_code == 305
assert "Alternate-Protocol" in i2.headers assert i2.status_code == 306
assert "Alternate-Protocol" not in n.headers assert any(f.response.status_code == 304 for f in self.master.state.flows)
assert not any(f.response.status_code == 305 for f in self.master.state.flows)
assert not any(f.response.status_code == 306 for f in self.master.state.flows)
# Test that we get the original SSL cert # Test that we get the original SSL cert
if self.ssl: if self.ssl:
@ -182,7 +184,8 @@ class TcpMixin:
assert i_cert == i2_cert == n_cert assert i_cert == i2_cert == n_cert
# Make sure that TCP messages are in the event log. # Make sure that TCP messages are in the event log.
assert any("mitmproxy-will-remove-this" in m for m in self.master.log) assert any("305" in m for m in self.master.log)
assert any("306" in m for m in self.master.log)
class AppMixin: class AppMixin:
@ -886,23 +889,6 @@ class TestUpstreamProxySSL(
# request from chain[0] (regular proxy doesn't store CONNECTs) # request from chain[0] (regular proxy doesn't store CONNECTs)
assert self.chain[1].tmaster.state.flow_count() == 1 assert self.chain[1].tmaster.state.flow_count() == 1
def test_closing_connect_response(self):
"""
https://github.com/mitmproxy/mitmproxy/issues/313
"""
def handle_request(f):
f.request.http_version = b"HTTP/1.1"
del f.request.headers["Content-Length"]
f.reply()
_handle_request = self.chain[0].tmaster.handle_request
self.chain[0].tmaster.handle_request = handle_request
try:
assert self.pathoc().request("get:/p/418").status_code == 418
finally:
self.chain[0].tmaster.handle_request = _handle_request
class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxTest): class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxTest):
ssl = True ssl = True