def request(self, flow: Flow) -> None: if flow.response or flow.error or (flow.reply and flow.reply.state == 'taken'): return if not (self.filter and self.filter(flow)): return headers = { 'server': version.MITMPROXY, } script = self._get_script() if not script: flow.response = Response.make(404, None, headers) return headers['content-type'] = 'application/javascript' flow.response = Response.make(200, script, headers)
async def wrapper(): try: await awaitable except: print_exc() flow.response = Response.make(500, None, {'server': version.MITMPROXY}) finally: flow.reply.commit()
async def _async_request(self, flow: Flow) -> None: referer = flow.request.headers['referer'] log.info(f'Webmanifest request from {referer}.') headers = { 'server': version.MITMPROXY, } try: character_info = await wait_for(self.data.get(referer), timeout=15) except (TimeoutError, CancelledError): log.error( f'Timeout while waiting for character data from {referer}.') flow.response = Response.make(404, b'', headers) return data = loads(character_info.decode('utf-8'))['data'] character_name = data['name'] avatar_url = data['decorations'].get('avatarUrl', None) manifest = { 'name': f'{character_name} - D&D Beyond', 'short_name': character_name, 'description': 'An official digital toolset for Fifth Edition (5e) Dungeons & Dragons (D&D).', 'icons': [], 'display': 'fullscreen', 'start_url': referer, } if avatar_url: manifest['icons'].append({ 'src': avatar_url, 'sizes': '192x192', 'type': 'image/webp', }) else: manifest['icons'].append({ 'src': 'https://www.dndbeyond.com/Content/Skins/Waterdeep/images/characters/default-avatar-builder.png', 'sizes': '192x192', 'type': 'image/png', }) headers['content-type'] = 'application/webmanifest+json' flow.response = Response.make(200, dumps(manifest).encode('utf-8'), headers)
def ws_testdata(tctx): tctx.server.address = ("example.com", 80) tctx.server.state = ConnectionState.OPEN flow = HTTPFlow( tctx.client, tctx.server ) flow.request = Request.make("GET", "http://example.com/", headers={ "Connection": "upgrade", "Upgrade": "websocket", "Sec-WebSocket-Version": "13", }) flow.response = Response.make(101, headers={ "Connection": "upgrade", "Upgrade": "websocket", }) return tctx, Playbook(websocket.WebsocketLayer(tctx, flow))
def test_make(self): r = Response.make() assert r.status_code == 200 assert r.content == b"" r = Response.make(418, "teatime") assert r.status_code == 418 assert r.content == b"teatime" assert r.headers["content-length"] == "7" Response.make(content=b"foo") Response.make(content="foo") with pytest.raises(TypeError): Response.make(content=42) r = Response.make(headers=[(b"foo", b"bar")]) assert r.headers["foo"] == "bar" r = Response.make(headers=({"foo": "baz"})) assert r.headers["foo"] == "baz" r = Response.make(headers=Headers(foo="qux")) assert r.headers["foo"] == "qux" with pytest.raises(TypeError): Response.make(headers=42)
def test_kill_flow(tctx, when): """Test that we properly kill flows if instructed to do so""" server = Placeholder(Server) connect_flow = Placeholder(HTTPFlow) flow = Placeholder(HTTPFlow) def kill(flow: HTTPFlow): # Can't use flow.kill() here because that currently still depends on a reply object. flow.error = Error(Error.KILLED_MESSAGE) def assert_kill(err_hook: bool = True): playbook >> reply(side_effect=kill) if err_hook: playbook << http.HttpErrorHook(flow) playbook >> reply() playbook << CloseConnection(tctx.client) assert playbook playbook = Playbook(http.HttpLayer(tctx, HTTPMode.regular)) assert (playbook >> DataReceived(tctx.client, b"CONNECT example.com:80 HTTP/1.1\r\n\r\n") << http.HttpConnectHook(connect_flow)) if when == "http_connect": return assert_kill(False) assert (playbook >> reply() << SendData(tctx.client, b'HTTP/1.1 200 Connection established\r\n\r\n') >> DataReceived(tctx.client, b"GET /foo?hello=1 HTTP/1.1\r\nHost: example.com\r\n\r\n") << layer.NextLayerHook(Placeholder()) >> reply_next_layer(lambda ctx: http.HttpLayer(ctx, HTTPMode.transparent)) << http.HttpRequestHeadersHook(flow)) if when == "requestheaders": return assert_kill() assert (playbook >> reply() << http.HttpRequestHook(flow)) if when == "request": return assert_kill() if when == "script-response-responseheaders": assert (playbook >> reply(side_effect=lambda f: setattr(f, "response", Response.make())) << http.HttpResponseHeadersHook(flow)) return assert_kill() assert (playbook >> reply() << OpenConnection(server) >> reply(None) << SendData(server, b"GET /foo?hello=1 HTTP/1.1\r\nHost: example.com\r\n\r\n") >> DataReceived(server, b"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World") << http.HttpResponseHeadersHook(flow)) if when == "responseheaders": return assert_kill() if when == "response": assert (playbook >> reply() >> DataReceived(server, b"!") << http.HttpResponseHook(flow)) return assert_kill(False) elif when == "error": assert (playbook >> reply() >> ConnectionClosed(server) << CloseConnection(server) << http.HttpErrorHook(flow)) return assert_kill(False) else: raise AssertionError
def reply_from_proxy(flow: HTTPFlow): flow.response = Response.make(418)
def request(flow): flow.response = HTTPResponse.make(200, cow, {'Content-Type': 'text/plain'})