mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-22 15:37:45 +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 passlib.apache
|
||||
|
||||
import mitmproxy.net.http
|
||||
from mitmproxy import ctx
|
||||
from mitmproxy import exceptions
|
||||
from mitmproxy import http
|
||||
@ -83,15 +82,23 @@ class ProxyAuth:
|
||||
|
||||
def auth_required_response(self) -> http.Response:
|
||||
if self.is_proxy_auth():
|
||||
return http.make_error_response(
|
||||
status_codes.PROXY_AUTH_REQUIRED,
|
||||
headers=mitmproxy.http.Headers(Proxy_Authenticate=f'Basic realm="{REALM}"'),
|
||||
)
|
||||
status_code = status_codes.PROXY_AUTH_REQUIRED
|
||||
headers = {"Proxy-Authenticate": f'Basic realm="{REALM}"'}
|
||||
else:
|
||||
return http.make_error_response(
|
||||
status_codes.UNAUTHORIZED,
|
||||
headers=mitmproxy.http.Headers(WWW_Authenticate=f'Basic realm="{REALM}"'),
|
||||
)
|
||||
status_code = status_codes.UNAUTHORIZED
|
||||
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]]:
|
||||
"""
|
||||
|
@ -1,4 +1,4 @@
|
||||
import html
|
||||
import re
|
||||
import re
|
||||
import time
|
||||
import urllib.parse
|
||||
@ -13,14 +13,13 @@ from typing import Optional
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
|
||||
from mitmproxy.net.http import url
|
||||
from mitmproxy import flow
|
||||
from mitmproxy import version
|
||||
from mitmproxy.coretypes import multidict
|
||||
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 status_codes
|
||||
from mitmproxy.net.http import url
|
||||
from mitmproxy.net.http.headers import assemble_content_type, parse_content_type
|
||||
from mitmproxy.proxy import context
|
||||
from mitmproxy.utils import human
|
||||
@ -1158,69 +1157,10 @@ class HTTPFlow(flow.Flow):
|
||||
return f
|
||||
|
||||
|
||||
def make_error_response(
|
||||
status_code: int,
|
||||
message: str = "",
|
||||
headers: Optional[Headers] = None,
|
||||
) -> 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")
|
||||
|
||||
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)
|
||||
__all__ = [
|
||||
"HTTPFlow",
|
||||
"Message",
|
||||
"Request",
|
||||
"Response",
|
||||
"Headers",
|
||||
]
|
||||
|
@ -449,7 +449,18 @@ class HttpStream(layer.Layer):
|
||||
|
||||
def handle_connect_finish(self):
|
||||
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:
|
||||
yield SendHttp(ResponseHeaders(self.stream_id, self.flow.response), self.context.client)
|
||||
|
@ -1,11 +1,12 @@
|
||||
import abc
|
||||
import html
|
||||
from typing import Union, Optional, Callable, Type
|
||||
|
||||
import h11
|
||||
from h11._readers import ChunkedReader, ContentLengthReader, Http10Reader
|
||||
from h11._receivebuffer import ReceiveBuffer
|
||||
|
||||
from mitmproxy import http
|
||||
from mitmproxy import http, version
|
||||
from mitmproxy.net.http import http1, status_codes
|
||||
from mitmproxy.proxy import commands, events, layer
|
||||
from mitmproxy.proxy.context import Connection, ConnectionState, Context
|
||||
@ -145,13 +146,13 @@ class Http1Connection(HttpConnection, metaclass=abc.ABCMeta):
|
||||
yield from self.make_pipe()
|
||||
return
|
||||
connection_done = (
|
||||
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.response.http_version, self.response.headers)
|
||||
# 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
|
||||
# the proxyserver's max-connection-per-server throttling.
|
||||
or (self.request.is_http2 and isinstance(self, Http1Client))
|
||||
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.response.http_version, self.response.headers)
|
||||
# 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
|
||||
# the proxyserver's max-connection-per-server throttling.
|
||||
or (self.request.is_http2 and isinstance(self, Http1Client))
|
||||
)
|
||||
if connection_done:
|
||||
yield commands.CloseConnection(self.conn)
|
||||
@ -211,7 +212,7 @@ class Http1Server(Http1Connection):
|
||||
yield from self.mark_done(response=True)
|
||||
elif isinstance(event, ResponseProtocolError):
|
||||
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)
|
||||
yield commands.SendData(self.conn, raw)
|
||||
yield commands.CloseConnection(self.conn)
|
||||
@ -362,6 +363,37 @@ def make_body_reader(expected_size: Optional[int]) -> TBodyReader:
|
||||
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__ = [
|
||||
"Http1Client",
|
||||
"Http1Server",
|
||||
|
@ -1,3 +1,4 @@
|
||||
import time
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from h11._receivebuffer import ReceiveBuffer
|
||||
@ -44,7 +45,20 @@ class HttpUpstreamProxy(tunnel.TunnelLayer):
|
||||
if not self.send_connect:
|
||||
return (yield from super().start_handshake())
|
||||
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)
|
||||
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.layers.http import Http1Server, ReceiveHttp, RequestHeaders, RequestEndOfMessage, \
|
||||
ResponseHeaders, ResponseEndOfMessage, RequestData, Http1Client, ResponseData
|
||||
from mitmproxy.proxy.layers.http._http1 import make_error_response
|
||||
from test.mitmproxy.proxy.tutils import Placeholder, Playbook
|
||||
|
||||
|
||||
@ -199,3 +200,7 @@ class TestClient:
|
||||
>> RequestHeaders(3, req, True)
|
||||
<< 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):
|
||||
f = tflow.tflow()
|
||||
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