mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 08:11:00 +00:00
Merge pull request #1073 from mitmproxy/first-line-format
form_(in|out) -> first_line_format
This commit is contained in:
commit
16fdbb4f2f
@ -80,18 +80,13 @@ class HTTPRequest(MessageMixin, Request):
|
|||||||
content: Content of the request, the value is None if there is content
|
content: Content of the request, the value is None if there is content
|
||||||
associated, but not present.
|
associated, but not present.
|
||||||
|
|
||||||
form_in: The request form which mitmproxy has received. The following
|
first_line_format: The request form. The following values are possible:
|
||||||
values are possible:
|
|
||||||
|
|
||||||
- relative (GET /index.html, OPTIONS *) (covers origin form and
|
- relative (GET /index.html, OPTIONS *) (origin form or asterisk form)
|
||||||
asterisk form)
|
|
||||||
- absolute (GET http://example.com:80/index.html)
|
- absolute (GET http://example.com:80/index.html)
|
||||||
- authority-form (CONNECT example.com:443)
|
- authority-form (CONNECT example.com:443)
|
||||||
Details: http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-25#section-5.3
|
Details: http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-25#section-5.3
|
||||||
|
|
||||||
form_out: The request form which mitmproxy will send out to the
|
|
||||||
destination
|
|
||||||
|
|
||||||
timestamp_start: Timestamp indicating when request transmission started
|
timestamp_start: Timestamp indicating when request transmission started
|
||||||
|
|
||||||
timestamp_end: Timestamp indicating when request transmission ended
|
timestamp_end: Timestamp indicating when request transmission ended
|
||||||
@ -110,7 +105,6 @@ class HTTPRequest(MessageMixin, Request):
|
|||||||
content,
|
content,
|
||||||
timestamp_start=None,
|
timestamp_start=None,
|
||||||
timestamp_end=None,
|
timestamp_end=None,
|
||||||
form_out=None,
|
|
||||||
is_replay=False,
|
is_replay=False,
|
||||||
stickycookie=False,
|
stickycookie=False,
|
||||||
stickyauth=False,
|
stickyauth=False,
|
||||||
@ -129,7 +123,6 @@ class HTTPRequest(MessageMixin, Request):
|
|||||||
timestamp_start,
|
timestamp_start,
|
||||||
timestamp_end,
|
timestamp_end,
|
||||||
)
|
)
|
||||||
self.form_out = form_out or first_line_format # FIXME remove
|
|
||||||
|
|
||||||
# Have this request's cookies been modified by sticky cookies or auth?
|
# Have this request's cookies been modified by sticky cookies or auth?
|
||||||
self.stickycookie = stickycookie
|
self.stickycookie = stickycookie
|
||||||
@ -167,20 +160,9 @@ class HTTPRequest(MessageMixin, Request):
|
|||||||
content=request.data.content,
|
content=request.data.content,
|
||||||
timestamp_start=request.data.timestamp_start,
|
timestamp_start=request.data.timestamp_start,
|
||||||
timestamp_end=request.data.timestamp_end,
|
timestamp_end=request.data.timestamp_end,
|
||||||
form_out=(request.form_out if hasattr(request, 'form_out') else None),
|
|
||||||
)
|
)
|
||||||
return req
|
return req
|
||||||
|
|
||||||
@property
|
|
||||||
def form_out(self):
|
|
||||||
warnings.warn(".form_out is deprecated, use .first_line_format instead.", DeprecationWarning)
|
|
||||||
return self.first_line_format
|
|
||||||
|
|
||||||
@form_out.setter
|
|
||||||
def form_out(self, value):
|
|
||||||
warnings.warn(".form_out is deprecated, use .first_line_format instead.", DeprecationWarning)
|
|
||||||
self.first_line_format = value
|
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return id(self)
|
return id(self)
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ class HttpLayer(Layer):
|
|||||||
self.validate_request(request)
|
self.validate_request(request)
|
||||||
|
|
||||||
# Regular Proxy Mode: Handle CONNECT
|
# Regular Proxy Mode: Handle CONNECT
|
||||||
if self.mode == "regular" and request.form_in == "authority":
|
if self.mode == "regular" and request.first_line_format == "authority":
|
||||||
self.handle_regular_mode_connect(request)
|
self.handle_regular_mode_connect(request)
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ class HttpLayer(Layer):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Upstream Proxy Mode: Handle CONNECT
|
# Upstream Proxy Mode: Handle CONNECT
|
||||||
if flow.request.form_in == "authority" and flow.response.status_code == 200:
|
if flow.request.first_line_format == "authority" and flow.response.status_code == 200:
|
||||||
self.handle_upstream_mode_connect(flow.request.copy())
|
self.handle_upstream_mode_connect(flow.request.copy())
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ class HttpLayer(Layer):
|
|||||||
if self.mode == "regular":
|
if self.mode == "regular":
|
||||||
pass # only absolute-form at this point, nothing to do here.
|
pass # only absolute-form at this point, nothing to do here.
|
||||||
elif self.mode == "upstream":
|
elif self.mode == "upstream":
|
||||||
if flow.request.form_in == "authority":
|
if flow.request.first_line_format == "authority":
|
||||||
flow.request.scheme = "http" # pseudo value
|
flow.request.scheme = "http" # pseudo value
|
||||||
else:
|
else:
|
||||||
# Setting request.host also updates the host header, which we want to preserve
|
# Setting request.host also updates the host header, which we want to preserve
|
||||||
@ -390,7 +390,7 @@ class HttpLayer(Layer):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def validate_request(self, request):
|
def validate_request(self, request):
|
||||||
if request.form_in == "absolute" and request.scheme != "http":
|
if request.first_line_format == "absolute" and request.scheme != "http":
|
||||||
raise HttpException("Invalid request scheme: %s" % request.scheme)
|
raise HttpException("Invalid request scheme: %s" % request.scheme)
|
||||||
|
|
||||||
expected_request_forms = {
|
expected_request_forms = {
|
||||||
@ -400,14 +400,14 @@ class HttpLayer(Layer):
|
|||||||
}
|
}
|
||||||
|
|
||||||
allowed_request_forms = expected_request_forms[self.mode]
|
allowed_request_forms = expected_request_forms[self.mode]
|
||||||
if request.form_in not in allowed_request_forms:
|
if request.first_line_format not in allowed_request_forms:
|
||||||
err_message = "Invalid HTTP request form (expected: %s, got: %s)" % (
|
err_message = "Invalid HTTP request form (expected: %s, got: %s)" % (
|
||||||
" or ".join(allowed_request_forms), request.form_in
|
" or ".join(allowed_request_forms), request.first_line_format
|
||||||
)
|
)
|
||||||
raise HttpException(err_message)
|
raise HttpException(err_message)
|
||||||
|
|
||||||
if self.mode == "regular" and request.form_in == "absolute":
|
if self.mode == "regular" and request.first_line_format == "absolute":
|
||||||
request.form_out = "relative"
|
request.first_line_format = "relative"
|
||||||
|
|
||||||
def authenticate(self, request):
|
def authenticate(self, request):
|
||||||
if self.config.authenticator:
|
if self.config.authenticator:
|
||||||
|
@ -54,7 +54,7 @@ class Http1Layer(_HttpTransmissionLayer):
|
|||||||
)
|
)
|
||||||
read_until_eof = http1.expected_http_body_size(flow.request, flow.response) == -1
|
read_until_eof = http1.expected_http_body_size(flow.request, flow.response) == -1
|
||||||
close_connection = request_close or response_close or read_until_eof
|
close_connection = request_close or response_close or read_until_eof
|
||||||
if flow.request.form_in == "authority" and flow.response.status_code == 200:
|
if flow.request.first_line_format == "authority" and flow.response.status_code == 200:
|
||||||
# Workaround for https://github.com/mitmproxy/mitmproxy/issues/313:
|
# Workaround for https://github.com/mitmproxy/mitmproxy/issues/313:
|
||||||
# Charles Proxy sends a CONNECT response with HTTP/1.0
|
# Charles Proxy sends a CONNECT response with HTTP/1.0
|
||||||
# and no Content-Length header
|
# and no Content-Length header
|
||||||
|
@ -303,11 +303,11 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread):
|
|||||||
port = None
|
port = None
|
||||||
|
|
||||||
if path == '*' or path.startswith("/"):
|
if path == '*' or path.startswith("/"):
|
||||||
form_in = "relative"
|
first_line_format = "relative"
|
||||||
elif method == 'CONNECT': # pragma: no cover
|
elif method == 'CONNECT': # pragma: no cover
|
||||||
raise NotImplementedError("CONNECT over HTTP/2 is not implemented.")
|
raise NotImplementedError("CONNECT over HTTP/2 is not implemented.")
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
form_in = "absolute"
|
first_line_format = "absolute"
|
||||||
# FIXME: verify if path or :host contains what we need
|
# FIXME: verify if path or :host contains what we need
|
||||||
scheme, host, port, _ = utils.parse_url(path)
|
scheme, host, port, _ = utils.parse_url(path)
|
||||||
|
|
||||||
@ -326,7 +326,7 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread):
|
|||||||
data = b"".join(data)
|
data = b"".join(data)
|
||||||
|
|
||||||
return HTTPRequest(
|
return HTTPRequest(
|
||||||
form_in,
|
first_line_format,
|
||||||
method,
|
method,
|
||||||
scheme,
|
scheme,
|
||||||
host,
|
host,
|
||||||
|
@ -30,7 +30,7 @@ class RequestReplayThread(threading.Thread):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
r = self.flow.request
|
r = self.flow.request
|
||||||
form_out_backup = r.form_out
|
first_line_format_backup = r.first_line_format
|
||||||
try:
|
try:
|
||||||
self.flow.response = None
|
self.flow.response = None
|
||||||
|
|
||||||
@ -63,9 +63,9 @@ class RequestReplayThread(threading.Thread):
|
|||||||
self.config.clientcerts,
|
self.config.clientcerts,
|
||||||
sni=self.flow.server_conn.sni
|
sni=self.flow.server_conn.sni
|
||||||
)
|
)
|
||||||
r.form_out = "relative"
|
r.first_line_format = "relative"
|
||||||
else:
|
else:
|
||||||
r.form_out = "absolute"
|
r.first_line_format= "absolute"
|
||||||
else:
|
else:
|
||||||
server_address = (r.host, r.port)
|
server_address = (r.host, r.port)
|
||||||
server = ServerConnection(server_address, (self.config.host, 0))
|
server = ServerConnection(server_address, (self.config.host, 0))
|
||||||
@ -75,7 +75,7 @@ class RequestReplayThread(threading.Thread):
|
|||||||
self.config.clientcerts,
|
self.config.clientcerts,
|
||||||
sni=self.flow.server_conn.sni
|
sni=self.flow.server_conn.sni
|
||||||
)
|
)
|
||||||
r.form_out = "relative"
|
r.first_line_format = "relative"
|
||||||
|
|
||||||
server.wfile.write(http1.assemble_request(r))
|
server.wfile.write(http1.assemble_request(r))
|
||||||
server.wfile.flush()
|
server.wfile.flush()
|
||||||
@ -102,4 +102,4 @@ class RequestReplayThread(threading.Thread):
|
|||||||
from ..proxy.root_context import Log
|
from ..proxy.root_context import Log
|
||||||
self.channel.tell("log", Log(traceback.format_exc(), "error"))
|
self.channel.tell("log", Log(traceback.format_exc(), "error"))
|
||||||
finally:
|
finally:
|
||||||
r.form_out = form_out_backup
|
r.first_line_format = first_line_format_backup
|
||||||
|
@ -102,15 +102,15 @@ class HTTP2Protocol(object):
|
|||||||
port = None
|
port = None
|
||||||
|
|
||||||
if path == '*' or path.startswith("/"):
|
if path == '*' or path.startswith("/"):
|
||||||
form_in = "relative"
|
first_line_format = "relative"
|
||||||
elif method == 'CONNECT':
|
elif method == 'CONNECT':
|
||||||
form_in = "authority"
|
first_line_format = "authority"
|
||||||
if ":" in authority:
|
if ":" in authority:
|
||||||
host, port = authority.split(":", 1)
|
host, port = authority.split(":", 1)
|
||||||
else:
|
else:
|
||||||
host = authority
|
host = authority
|
||||||
else:
|
else:
|
||||||
form_in = "absolute"
|
first_line_format = "absolute"
|
||||||
# FIXME: verify if path or :host contains what we need
|
# FIXME: verify if path or :host contains what we need
|
||||||
scheme, host, port, _ = utils.parse_url(path)
|
scheme, host, port, _ = utils.parse_url(path)
|
||||||
scheme = scheme.decode('ascii')
|
scheme = scheme.decode('ascii')
|
||||||
@ -123,7 +123,7 @@ class HTTP2Protocol(object):
|
|||||||
port = int(port)
|
port = int(port)
|
||||||
|
|
||||||
request = Request(
|
request = Request(
|
||||||
form_in,
|
first_line_format,
|
||||||
method.encode('ascii'),
|
method.encode('ascii'),
|
||||||
scheme.encode('ascii'),
|
scheme.encode('ascii'),
|
||||||
host.encode('ascii'),
|
host.encode('ascii'),
|
||||||
|
@ -358,24 +358,3 @@ class Request(Message):
|
|||||||
def get_form_multipart(self): # pragma: no cover
|
def get_form_multipart(self): # pragma: no cover
|
||||||
warnings.warn(".get_form_multipart is deprecated, use .multipart_form instead.", DeprecationWarning)
|
warnings.warn(".get_form_multipart is deprecated, use .multipart_form instead.", DeprecationWarning)
|
||||||
return self.multipart_form or ODict([])
|
return self.multipart_form or ODict([])
|
||||||
|
|
||||||
@property
|
|
||||||
def form_in(self): # pragma: no cover
|
|
||||||
warnings.warn(".form_in is deprecated, use .first_line_format instead.", DeprecationWarning)
|
|
||||||
return self.first_line_format
|
|
||||||
|
|
||||||
@form_in.setter
|
|
||||||
def form_in(self, form_in): # pragma: no cover
|
|
||||||
warnings.warn(".form_in is deprecated, use .first_line_format instead.", DeprecationWarning)
|
|
||||||
self.first_line_format = form_in
|
|
||||||
|
|
||||||
@property
|
|
||||||
def form_out(self): # pragma: no cover
|
|
||||||
warnings.warn(".form_out is deprecated, use .first_line_format instead.", DeprecationWarning)
|
|
||||||
return self.first_line_format
|
|
||||||
|
|
||||||
@form_out.setter
|
|
||||||
def form_out(self, form_out): # pragma: no cover
|
|
||||||
warnings.warn(".form_out is deprecated, use .first_line_format instead.", DeprecationWarning)
|
|
||||||
self.first_line_format = form_out
|
|
||||||
|
|
||||||
|
@ -973,22 +973,22 @@ class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxyTest):
|
|||||||
assert not self.chain[1].tmaster.state.flows[0].response # killed
|
assert not self.chain[1].tmaster.state.flows[0].response # killed
|
||||||
assert self.chain[1].tmaster.state.flows[1].response
|
assert self.chain[1].tmaster.state.flows[1].response
|
||||||
|
|
||||||
assert self.proxy.tmaster.state.flows[0].request.form_in == "authority"
|
assert self.proxy.tmaster.state.flows[0].request.first_line_format == "authority"
|
||||||
assert self.proxy.tmaster.state.flows[1].request.form_in == "relative"
|
assert self.proxy.tmaster.state.flows[1].request.first_line_format == "relative"
|
||||||
|
|
||||||
assert self.chain[0].tmaster.state.flows[
|
assert self.chain[0].tmaster.state.flows[
|
||||||
0].request.form_in == "authority"
|
0].request.first_line_format == "authority"
|
||||||
assert self.chain[0].tmaster.state.flows[
|
assert self.chain[0].tmaster.state.flows[
|
||||||
1].request.form_in == "relative"
|
1].request.first_line_format == "relative"
|
||||||
assert self.chain[0].tmaster.state.flows[
|
assert self.chain[0].tmaster.state.flows[
|
||||||
2].request.form_in == "authority"
|
2].request.first_line_format == "authority"
|
||||||
assert self.chain[0].tmaster.state.flows[
|
assert self.chain[0].tmaster.state.flows[
|
||||||
3].request.form_in == "relative"
|
3].request.first_line_format == "relative"
|
||||||
|
|
||||||
assert self.chain[1].tmaster.state.flows[
|
assert self.chain[1].tmaster.state.flows[
|
||||||
0].request.form_in == "relative"
|
0].request.first_line_format == "relative"
|
||||||
assert self.chain[1].tmaster.state.flows[
|
assert self.chain[1].tmaster.state.flows[
|
||||||
1].request.form_in == "relative"
|
1].request.first_line_format == "relative"
|
||||||
|
|
||||||
req = p.request("get:'/p/418:b\"content2\"'")
|
req = p.request("get:'/p/418:b\"content2\"'")
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ class TestReadRequestRelative(tservers.ServerTestBase):
|
|||||||
|
|
||||||
ssl = True
|
ssl = True
|
||||||
|
|
||||||
def test_asterisk_form_in(self):
|
def test_asterisk_form(self):
|
||||||
c = tcp.TCPClient(("127.0.0.1", self.port))
|
c = tcp.TCPClient(("127.0.0.1", self.port))
|
||||||
c.connect()
|
c.connect()
|
||||||
c.convert_to_ssl()
|
c.convert_to_ssl()
|
||||||
@ -334,7 +334,7 @@ class TestReadRequestRelative(tservers.ServerTestBase):
|
|||||||
|
|
||||||
req = protocol.read_request(NotImplemented)
|
req = protocol.read_request(NotImplemented)
|
||||||
|
|
||||||
assert req.form_in == "relative"
|
assert req.first_line_format == "relative"
|
||||||
assert req.method == "OPTIONS"
|
assert req.method == "OPTIONS"
|
||||||
assert req.path == "*"
|
assert req.path == "*"
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ class TestReadRequestAbsolute(tservers.ServerTestBase):
|
|||||||
|
|
||||||
ssl = True
|
ssl = True
|
||||||
|
|
||||||
def test_absolute_form_in(self):
|
def test_absolute_form(self):
|
||||||
c = tcp.TCPClient(("127.0.0.1", self.port))
|
c = tcp.TCPClient(("127.0.0.1", self.port))
|
||||||
c.connect()
|
c.connect()
|
||||||
c.convert_to_ssl()
|
c.convert_to_ssl()
|
||||||
@ -357,7 +357,7 @@ class TestReadRequestAbsolute(tservers.ServerTestBase):
|
|||||||
|
|
||||||
req = protocol.read_request(NotImplemented)
|
req = protocol.read_request(NotImplemented)
|
||||||
|
|
||||||
assert req.form_in == "absolute"
|
assert req.first_line_format == "absolute"
|
||||||
assert req.scheme == "http"
|
assert req.scheme == "http"
|
||||||
assert req.host == "address"
|
assert req.host == "address"
|
||||||
assert req.port == 22
|
assert req.port == 22
|
||||||
@ -382,13 +382,13 @@ class TestReadRequestConnect(tservers.ServerTestBase):
|
|||||||
protocol.connection_preface_performed = True
|
protocol.connection_preface_performed = True
|
||||||
|
|
||||||
req = protocol.read_request(NotImplemented)
|
req = protocol.read_request(NotImplemented)
|
||||||
assert req.form_in == "authority"
|
assert req.first_line_format == "authority"
|
||||||
assert req.method == "CONNECT"
|
assert req.method == "CONNECT"
|
||||||
assert req.host == "address"
|
assert req.host == "address"
|
||||||
assert req.port == 22
|
assert req.port == 22
|
||||||
|
|
||||||
req = protocol.read_request(NotImplemented)
|
req = protocol.read_request(NotImplemented)
|
||||||
assert req.form_in == "authority"
|
assert req.first_line_format == "authority"
|
||||||
assert req.method == "CONNECT"
|
assert req.method == "CONNECT"
|
||||||
assert req.host == "example.com"
|
assert req.host == "example.com"
|
||||||
assert req.port == 443
|
assert req.port == 443
|
||||||
|
Loading…
Reference in New Issue
Block a user