web: fix HTTP trailer update

This commit is contained in:
Maximilian Hils 2021-08-23 11:22:08 +02:00
parent 3589ec2f58
commit 7219284d44
2 changed files with 42 additions and 10 deletions

View File

@ -362,7 +362,10 @@ class FlowHandler(RequestHandler):
for header in v: for header in v:
request.headers.add(*header) request.headers.add(*header)
elif k == "trailers": elif k == "trailers":
request.trailers.clear() if request.trailers is not None:
request.trailers.clear()
else:
request.trailers = mitmproxy.http.Headers()
for trailer in v: for trailer in v:
request.trailers.add(*trailer) request.trailers.add(*trailer)
elif k == "content": elif k == "content":
@ -382,7 +385,10 @@ class FlowHandler(RequestHandler):
for header in v: for header in v:
response.headers.add(*header) response.headers.add(*header)
elif k == "trailers": elif k == "trailers":
response.trailers.clear() if response.trailers is not None:
response.trailers.clear()
else:
response.trailers = mitmproxy.http.Headers()
for trailer in v: for trailer in v:
response.trailers.add(*trailer) response.trailers.add(*trailer)
elif k == "content": elif k == "content":

View File

@ -10,15 +10,12 @@ from pathlib import Path
from unittest import mock from unittest import mock
import pytest import pytest
from mitmproxy.http import Headers
import tornado.testing import tornado.testing
from tornado import httpclient from tornado import httpclient
from tornado import websocket from tornado import websocket
from mitmproxy import certs, options, optmanager from mitmproxy import certs, options, optmanager
from mitmproxy.http import Headers
from mitmproxy.test import tflow from mitmproxy.test import tflow
from mitmproxy.tools.web import app from mitmproxy.tools.web import app
from mitmproxy.tools.web import master as webmaster from mitmproxy.tools.web import master as webmaster
@ -126,7 +123,11 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
f = tflow.tflow(resp=True) f = tflow.tflow(resp=True)
f.id = "42" f.id = "42"
f.request.content = b"foo\nbar" f.request.content = b"foo\nbar"
m.view.add([f]) f2 = tflow.tflow(ws=True, resp=True)
f2.request.content = None
f2.response.content = None
f2.id = "43"
m.view.add([f, f2])
m.view.add([tflow.tflow(err=True)]) m.view.add([tflow.tflow(err=True)])
m.log.info("test log") m.log.info("test log")
self.master = m self.master = m
@ -158,7 +159,7 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
resp = self.fetch("/flows") resp = self.fetch("/flows")
assert resp.code == 200 assert resp.code == 200
assert get_json(resp)[0]["request"]["contentHash"] assert get_json(resp)[0]["request"]["contentHash"]
assert get_json(resp)[1]["error"] assert get_json(resp)[2]["error"]
def test_flows_dump(self): def test_flows_dump(self):
resp = self.fetch("/flows/dump") resp = self.fetch("/flows/dump")
@ -184,7 +185,7 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
assert self.fetch( assert self.fetch(
"/flows/42/resume", method="POST").code == 200 "/flows/42/resume", method="POST").code == 200
assert sum(f.intercepted for f in self.view) == 1 assert sum(f.intercepted for f in self.view) >= 1
assert self.fetch("/flows/resume", method="POST").code == 200 assert self.fetch("/flows/resume", method="POST").code == 200
assert all(not f.intercepted for f in self.view) assert all(not f.intercepted for f in self.view)
@ -194,7 +195,7 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
f.intercept() f.intercept()
assert self.fetch("/flows/42/kill", method="POST").code == 200 assert self.fetch("/flows/42/kill", method="POST").code == 200
assert sum(f.killable for f in self.view) == 1 assert sum(f.killable for f in self.view) >= 1
assert self.fetch("/flows/kill", method="POST").code == 200 assert self.fetch("/flows/kill", method="POST").code == 200
assert all(not f.killable for f in self.view) assert all(not f.killable for f in self.view)
for f in self.view: for f in self.view:
@ -221,12 +222,14 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
"method": "PATCH", "method": "PATCH",
"port": 123, "port": 123,
"headers": [("foo", "bar")], "headers": [("foo", "bar")],
"trailers": [("foo", "bar")],
"content": "req", "content": "req",
}, },
"response": { "response": {
"msg": "Non-Authorisé", "msg": "Non-Authorisé",
"code": 404, "code": 404,
"headers": [("bar", "baz")], "headers": [("bar", "baz")],
"trailers": [("foo", "bar")],
"content": "resp", "content": "resp",
}, },
"marked": ":red_circle:", "marked": ":red_circle:",
@ -254,6 +257,13 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
body="!!" body="!!"
).code == 400 ).code == 400
upd = {
"request": {"trailers": [("foo", "baz")],},
"response": {"trailers": [("foo", "baz")],},
}
assert self.put_json("/flows/42", upd).code == 200
assert f.request.trailers["foo"] == "baz"
def test_flow_duplicate(self): def test_flow_duplicate(self):
resp = self.fetch("/flows/42/duplicate", method="POST") resp = self.fetch("/flows/42/duplicate", method="POST")
assert resp.code == 200 assert resp.code == 200
@ -342,6 +352,19 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
], ],
"description": "Raw" "description": "Raw"
} }
assert self.fetch("/flows/42/messages/content/raw").code == 400
def test_flow_contentview_websocket(self):
assert get_json(self.fetch("/flows/43/messages/content/raw?lines=2")) == [
{'description': 'Raw',
'from_client': True,
'lines': [[['text', 'hello binary']]],
'timestamp': 946681203},
{'description': 'Raw',
'from_client': True,
'lines': [[['text', 'hello text']]],
'timestamp': 946681204}
]
def test_commands(self): def test_commands(self):
resp = self.fetch("/commands") resp = self.fetch("/commands")
@ -374,6 +397,9 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
def test_option_save(self): def test_option_save(self):
assert self.fetch("/options/save", method="POST").code == 200 assert self.fetch("/options/save", method="POST").code == 200
def test_conf(self):
assert self.fetch("/conf.js").code == 200
def test_err(self): def test_err(self):
with mock.patch("mitmproxy.tools.web.app.IndexHandler.get") as f: with mock.patch("mitmproxy.tools.web.app.IndexHandler.get") as f:
f.side_effect = RuntimeError f.side_effect = RuntimeError