mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 00:01:36 +00:00
inline/move http.make_* functions
This commit is contained in:
parent
9409bf0368
commit
d68c364b35
@ -7,7 +7,6 @@ from typing import Tuple
|
|||||||
import ldap3
|
import ldap3
|
||||||
import passlib.apache
|
import passlib.apache
|
||||||
|
|
||||||
import mitmproxy.net.http
|
|
||||||
from mitmproxy import ctx
|
from mitmproxy import ctx
|
||||||
from mitmproxy import exceptions
|
from mitmproxy import exceptions
|
||||||
from mitmproxy import http
|
from mitmproxy import http
|
||||||
@ -83,15 +82,23 @@ class ProxyAuth:
|
|||||||
|
|
||||||
def auth_required_response(self) -> http.Response:
|
def auth_required_response(self) -> http.Response:
|
||||||
if self.is_proxy_auth():
|
if self.is_proxy_auth():
|
||||||
return http.make_error_response(
|
status_code = status_codes.PROXY_AUTH_REQUIRED
|
||||||
status_codes.PROXY_AUTH_REQUIRED,
|
headers = {"Proxy-Authenticate": f'Basic realm="{REALM}"'}
|
||||||
headers=mitmproxy.http.Headers(Proxy_Authenticate=f'Basic realm="{REALM}"'),
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return http.make_error_response(
|
status_code = status_codes.UNAUTHORIZED
|
||||||
status_codes.UNAUTHORIZED,
|
headers = {"WWW-Authenticate": f'Basic realm="{REALM}"'}
|
||||||
headers=mitmproxy.http.Headers(WWW_Authenticate=f'Basic realm="{REALM}"'),
|
|
||||||
)
|
reason = http.status_codes.RESPONSES[status_code]
|
||||||
|
return http.Response.make(
|
||||||
|
status_code,
|
||||||
|
(
|
||||||
|
f"<html>"
|
||||||
|
f"<head><title>{status_code} {reason}</title></head>"
|
||||||
|
f"<body><h1>{status_code} {reason}</h1></body>"
|
||||||
|
f"</html>"
|
||||||
|
),
|
||||||
|
headers
|
||||||
|
)
|
||||||
|
|
||||||
def check(self, f: http.HTTPFlow) -> Optional[Tuple[str, str]]:
|
def check(self, f: http.HTTPFlow) -> Optional[Tuple[str, str]]:
|
||||||
"""
|
"""
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import html
|
import re
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
@ -13,14 +13,13 @@ from typing import Optional
|
|||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from mitmproxy.net.http import url
|
|
||||||
from mitmproxy import flow
|
from mitmproxy import flow
|
||||||
from mitmproxy import version
|
|
||||||
from mitmproxy.coretypes import multidict
|
from mitmproxy.coretypes import multidict
|
||||||
from mitmproxy.coretypes import serializable
|
from mitmproxy.coretypes import serializable
|
||||||
from mitmproxy.net import http, encoding
|
from mitmproxy.net import encoding
|
||||||
from mitmproxy.net.http import cookies, multipart
|
from mitmproxy.net.http import cookies, multipart
|
||||||
from mitmproxy.net.http import status_codes
|
from mitmproxy.net.http import status_codes
|
||||||
|
from mitmproxy.net.http import url
|
||||||
from mitmproxy.net.http.headers import assemble_content_type, parse_content_type
|
from mitmproxy.net.http.headers import assemble_content_type, parse_content_type
|
||||||
from mitmproxy.proxy import context
|
from mitmproxy.proxy import context
|
||||||
from mitmproxy.utils import human
|
from mitmproxy.utils import human
|
||||||
@ -1158,69 +1157,10 @@ class HTTPFlow(flow.Flow):
|
|||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
def make_error_response(
|
__all__ = [
|
||||||
status_code: int,
|
"HTTPFlow",
|
||||||
message: str = "",
|
"Message",
|
||||||
headers: Optional[Headers] = None,
|
"Request",
|
||||||
) -> Response:
|
"Response",
|
||||||
body: bytes = """
|
"Headers",
|
||||||
<html>
|
]
|
||||||
<head>
|
|
||||||
<title>{status_code} {reason}</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>{status_code} {reason}</h1>
|
|
||||||
<p>{message}</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
""".strip().format(
|
|
||||||
status_code=status_code,
|
|
||||||
reason=http.status_codes.RESPONSES.get(status_code, "Unknown"),
|
|
||||||
message=html.escape(message),
|
|
||||||
).encode("utf8", "replace")
|
|
||||||
|
|
||||||
if not headers:
|
|
||||||
headers = Headers(
|
|
||||||
Server=version.MITMPROXY,
|
|
||||||
Connection="close",
|
|
||||||
Content_Length=str(len(body)),
|
|
||||||
Content_Type="text/html"
|
|
||||||
)
|
|
||||||
|
|
||||||
return Response.make(status_code, body, headers)
|
|
||||||
|
|
||||||
|
|
||||||
def make_connect_request(address: Tuple[str, int]) -> Request:
|
|
||||||
return Request(
|
|
||||||
host=address[0],
|
|
||||||
port=address[1],
|
|
||||||
method=b"CONNECT",
|
|
||||||
scheme=b"",
|
|
||||||
authority=f"{address[0]}:{address[1]}".encode(),
|
|
||||||
path=b"",
|
|
||||||
http_version=b"HTTP/1.1",
|
|
||||||
headers=Headers(),
|
|
||||||
content=b"",
|
|
||||||
trailers=None,
|
|
||||||
timestamp_start=time.time(),
|
|
||||||
timestamp_end=time.time(),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def make_connect_response(http_version):
|
|
||||||
# Do not send any response headers as it breaks proxying non-80 ports on
|
|
||||||
# Android emulators using the -http-proxy option.
|
|
||||||
return Response(
|
|
||||||
http_version,
|
|
||||||
200,
|
|
||||||
b"Connection established",
|
|
||||||
Headers(),
|
|
||||||
b"",
|
|
||||||
None,
|
|
||||||
time.time(),
|
|
||||||
time.time(),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def make_expect_continue_response():
|
|
||||||
return Response.make(100)
|
|
||||||
|
@ -449,7 +449,18 @@ class HttpStream(layer.Layer):
|
|||||||
|
|
||||||
def handle_connect_finish(self):
|
def handle_connect_finish(self):
|
||||||
if not self.flow.response:
|
if not self.flow.response:
|
||||||
self.flow.response = http.make_connect_response(self.flow.request.data.http_version)
|
# Do not send any response headers as it breaks proxying non-80 ports on
|
||||||
|
# Android emulators using the -http-proxy option.
|
||||||
|
self.flow.response = http.Response(
|
||||||
|
self.flow.request.data.http_version,
|
||||||
|
200,
|
||||||
|
b"Connection established",
|
||||||
|
http.Headers(),
|
||||||
|
b"",
|
||||||
|
None,
|
||||||
|
time.time(),
|
||||||
|
time.time(),
|
||||||
|
)
|
||||||
|
|
||||||
if 200 <= self.flow.response.status_code < 300:
|
if 200 <= self.flow.response.status_code < 300:
|
||||||
yield SendHttp(ResponseHeaders(self.stream_id, self.flow.response), self.context.client)
|
yield SendHttp(ResponseHeaders(self.stream_id, self.flow.response), self.context.client)
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import html
|
||||||
from typing import Union, Optional, Callable, Type
|
from typing import Union, Optional, Callable, Type
|
||||||
|
|
||||||
import h11
|
import h11
|
||||||
from h11._readers import ChunkedReader, ContentLengthReader, Http10Reader
|
from h11._readers import ChunkedReader, ContentLengthReader, Http10Reader
|
||||||
from h11._receivebuffer import ReceiveBuffer
|
from h11._receivebuffer import ReceiveBuffer
|
||||||
|
|
||||||
from mitmproxy import http
|
from mitmproxy import http, version
|
||||||
from mitmproxy.net.http import http1, status_codes
|
from mitmproxy.net.http import http1, status_codes
|
||||||
from mitmproxy.proxy import commands, events, layer
|
from mitmproxy.proxy import commands, events, layer
|
||||||
from mitmproxy.proxy.context import Connection, ConnectionState, Context
|
from mitmproxy.proxy.context import Connection, ConnectionState, Context
|
||||||
@ -145,13 +146,13 @@ class Http1Connection(HttpConnection, metaclass=abc.ABCMeta):
|
|||||||
yield from self.make_pipe()
|
yield from self.make_pipe()
|
||||||
return
|
return
|
||||||
connection_done = (
|
connection_done = (
|
||||||
http1.expected_http_body_size(self.request, self.response) == -1
|
http1.expected_http_body_size(self.request, self.response) == -1
|
||||||
or http1.connection_close(self.request.http_version, self.request.headers)
|
or http1.connection_close(self.request.http_version, self.request.headers)
|
||||||
or http1.connection_close(self.response.http_version, self.response.headers)
|
or http1.connection_close(self.response.http_version, self.response.headers)
|
||||||
# If we proxy HTTP/2 to HTTP/1, we only use upstream connections for one request.
|
# If we proxy HTTP/2 to HTTP/1, we only use upstream connections for one request.
|
||||||
# This simplifies our connection management quite a bit as we can rely on
|
# This simplifies our connection management quite a bit as we can rely on
|
||||||
# the proxyserver's max-connection-per-server throttling.
|
# the proxyserver's max-connection-per-server throttling.
|
||||||
or (self.request.is_http2 and isinstance(self, Http1Client))
|
or (self.request.is_http2 and isinstance(self, Http1Client))
|
||||||
)
|
)
|
||||||
if connection_done:
|
if connection_done:
|
||||||
yield commands.CloseConnection(self.conn)
|
yield commands.CloseConnection(self.conn)
|
||||||
@ -211,7 +212,7 @@ class Http1Server(Http1Connection):
|
|||||||
yield from self.mark_done(response=True)
|
yield from self.mark_done(response=True)
|
||||||
elif isinstance(event, ResponseProtocolError):
|
elif isinstance(event, ResponseProtocolError):
|
||||||
if not self.response:
|
if not self.response:
|
||||||
resp = http.make_error_response(event.code, event.message)
|
resp = make_error_response(event.code, event.message)
|
||||||
raw = http1.assemble_response(resp)
|
raw = http1.assemble_response(resp)
|
||||||
yield commands.SendData(self.conn, raw)
|
yield commands.SendData(self.conn, raw)
|
||||||
yield commands.CloseConnection(self.conn)
|
yield commands.CloseConnection(self.conn)
|
||||||
@ -362,6 +363,37 @@ def make_body_reader(expected_size: Optional[int]) -> TBodyReader:
|
|||||||
return ContentLengthReader(expected_size)
|
return ContentLengthReader(expected_size)
|
||||||
|
|
||||||
|
|
||||||
|
def make_error_response(
|
||||||
|
status_code: int,
|
||||||
|
message: str = "",
|
||||||
|
) -> http.Response:
|
||||||
|
body: bytes = """
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{status_code} {reason}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{status_code} {reason}</h1>
|
||||||
|
<p>{message}</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
""".strip().format(
|
||||||
|
status_code=status_code,
|
||||||
|
reason=http.status_codes.RESPONSES.get(status_code, "Unknown"),
|
||||||
|
message=html.escape(message),
|
||||||
|
).encode("utf8", "replace")
|
||||||
|
|
||||||
|
return http.Response.make(
|
||||||
|
status_code,
|
||||||
|
body,
|
||||||
|
http.Headers(
|
||||||
|
Server=version.MITMPROXY,
|
||||||
|
Connection="close",
|
||||||
|
Content_Type="text/html",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Http1Client",
|
"Http1Client",
|
||||||
"Http1Server",
|
"Http1Server",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import time
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
from h11._receivebuffer import ReceiveBuffer
|
from h11._receivebuffer import ReceiveBuffer
|
||||||
@ -44,7 +45,20 @@ class HttpUpstreamProxy(tunnel.TunnelLayer):
|
|||||||
if not self.send_connect:
|
if not self.send_connect:
|
||||||
return (yield from super().start_handshake())
|
return (yield from super().start_handshake())
|
||||||
assert self.conn.address
|
assert self.conn.address
|
||||||
req = http.make_connect_request(self.conn.address)
|
req = http.Request(
|
||||||
|
host=self.conn.address[0],
|
||||||
|
port=self.conn.address[1],
|
||||||
|
method=b"CONNECT",
|
||||||
|
scheme=b"",
|
||||||
|
authority=f"{self.conn.address[0]}:{self.conn.address[1]}".encode(),
|
||||||
|
path=b"",
|
||||||
|
http_version=b"HTTP/1.1",
|
||||||
|
headers=http.Headers(),
|
||||||
|
content=b"",
|
||||||
|
trailers=None,
|
||||||
|
timestamp_start=time.time(),
|
||||||
|
timestamp_end=time.time(),
|
||||||
|
)
|
||||||
raw = http1.assemble_request(req)
|
raw = http1.assemble_request(req)
|
||||||
yield commands.SendData(self.tunnel_connection, raw)
|
yield commands.SendData(self.tunnel_connection, raw)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ from mitmproxy.proxy.commands import SendData
|
|||||||
from mitmproxy.proxy.events import DataReceived
|
from mitmproxy.proxy.events import DataReceived
|
||||||
from mitmproxy.proxy.layers.http import Http1Server, ReceiveHttp, RequestHeaders, RequestEndOfMessage, \
|
from mitmproxy.proxy.layers.http import Http1Server, ReceiveHttp, RequestHeaders, RequestEndOfMessage, \
|
||||||
ResponseHeaders, ResponseEndOfMessage, RequestData, Http1Client, ResponseData
|
ResponseHeaders, ResponseEndOfMessage, RequestData, Http1Client, ResponseData
|
||||||
|
from mitmproxy.proxy.layers.http._http1 import make_error_response
|
||||||
from test.mitmproxy.proxy.tutils import Placeholder, Playbook
|
from test.mitmproxy.proxy.tutils import Placeholder, Playbook
|
||||||
|
|
||||||
|
|
||||||
@ -199,3 +200,7 @@ class TestClient:
|
|||||||
>> RequestHeaders(3, req, True)
|
>> RequestHeaders(3, req, True)
|
||||||
<< SendData(tctx.server, Placeholder(bytes))
|
<< SendData(tctx.server, Placeholder(bytes))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_error_response():
|
||||||
|
assert make_error_response(543, 'foobar')
|
||||||
|
@ -197,27 +197,3 @@ class TestHTTPFlow:
|
|||||||
def test_timestamp_start(self):
|
def test_timestamp_start(self):
|
||||||
f = tflow.tflow()
|
f = tflow.tflow()
|
||||||
assert f.timestamp_start == f.request.timestamp_start
|
assert f.timestamp_start == f.request.timestamp_start
|
||||||
|
|
||||||
|
|
||||||
def test_make_error_response():
|
|
||||||
resp = http.make_error_response(543, 'foobar', Headers())
|
|
||||||
assert resp
|
|
||||||
|
|
||||||
|
|
||||||
def test_make_connect_request():
|
|
||||||
req = http.make_connect_request(('invalidhost', 1234))
|
|
||||||
assert req.first_line_format == 'authority'
|
|
||||||
assert req.method == 'CONNECT'
|
|
||||||
assert req.http_version == 'HTTP/1.1'
|
|
||||||
|
|
||||||
|
|
||||||
def test_make_connect_response():
|
|
||||||
resp = http.make_connect_response('foobar')
|
|
||||||
assert resp.http_version == 'foobar'
|
|
||||||
assert resp.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
def test_expect_continue_response():
|
|
||||||
resp = http.make_expect_continue_response()
|
|
||||||
assert resp.http_version == 'HTTP/1.1'
|
|
||||||
assert resp.status_code == 100
|
|
||||||
|
Loading…
Reference in New Issue
Block a user