Merge pull request #952 from fimad/master

Add a content view for query parameters
This commit is contained in:
Aldo Cortesi 2016-02-18 08:57:42 +13:00
commit 10eed53d0a
3 changed files with 47 additions and 6 deletions

View File

@ -193,8 +193,11 @@ class FlowView(tabs.Tabs):
def _get_content_view(self, viewmode, message, max_lines, _): def _get_content_view(self, viewmode, message, max_lines, _):
try: try:
query = None
if isinstance(message, HTTPRequest):
query = message.query
description, lines = contentviews.get_content_view( description, lines = contentviews.get_content_view(
viewmode, message.content, headers=message.headers viewmode, message.content, headers=message.headers, query=query
) )
except ContentViewException: except ContentViewException:
s = "Content viewer failed: \n" + traceback.format_exc() s = "Content viewer failed: \n" + traceback.format_exc()

View File

@ -8,7 +8,8 @@ in the future, e.g. to decode protobuf messages sent as WebSocket frames.
Thus, the View API is very minimalistic. The only arguments are `data` and `**metadata`, Thus, the View API is very minimalistic. The only arguments are `data` and `**metadata`,
where `data` is the actual content (as bytes). The contents on metadata depend on the protocol in where `data` is the actual content (as bytes). The contents on metadata depend on the protocol in
use. For HTTP, the message headers are passed as the ``headers`` keyword argument. use. For HTTP, the message headers are passed as the ``headers`` keyword argument. For HTTP
requests, the query parameters are passed as the ``query`` keyword argument.
""" """
from __future__ import (absolute_import, print_function, division) from __future__ import (absolute_import, print_function, division)
@ -118,15 +119,19 @@ class ViewAuto(View):
def __call__(self, data, **metadata): def __call__(self, data, **metadata):
headers = metadata.get("headers", {}) headers = metadata.get("headers", {})
ctype = headers.get("content-type") ctype = headers.get("content-type")
if ctype: if data and ctype:
ct = parse_content_type(ctype) if ctype else None ct = parse_content_type(ctype) if ctype else None
ct = "%s/%s" % (ct[0], ct[1]) ct = "%s/%s" % (ct[0], ct[1])
if ct in content_types_map: if ct in content_types_map:
return content_types_map[ct][0](data, **metadata) return content_types_map[ct][0](data, **metadata)
elif utils.isXML(data): elif utils.isXML(data):
return get("XML")(data, **metadata) return get("XML")(data, **metadata)
if utils.isMostlyBin(data): if metadata.get("query"):
return get("Query")(data, **metadata)
if data and utils.isMostlyBin(data):
return get("Hex")(data) return get("Hex")(data)
if not data:
return "No content", []
return get("Raw")(data) return get("Raw")(data)
@ -460,6 +465,19 @@ class ViewProtobuf(View):
return "Protobuf", format_text(decoded) return "Protobuf", format_text(decoded)
class ViewQuery(View):
name = "Query"
prompt = ("query", "q")
content_types = []
def __call__(self, data, **metadata):
query = metadata.get("query")
if query:
return "Query", format_dict(query)
else:
return "Query", format_text("")
class ViewWBXML(View): class ViewWBXML(View):
name = "WBXML" name = "WBXML"
prompt = ("wbxml", "w") prompt = ("wbxml", "w")
@ -541,6 +559,7 @@ add(ViewCSS())
add(ViewURLEncoded()) add(ViewURLEncoded())
add(ViewMultipart()) add(ViewMultipart())
add(ViewImage()) add(ViewImage())
add(ViewQuery())
if pyamf: if pyamf:
add(ViewAMF()) add(ViewAMF())
@ -577,8 +596,6 @@ def get_content_view(viewmode, data, **metadata):
Raises: Raises:
ContentViewException, if the content view threw an error. ContentViewException, if the content view threw an error.
""" """
if not data:
return "No content", []
msg = [] msg = []
headers = metadata.get("headers", {}) headers = metadata.get("headers", {})

View File

@ -1,5 +1,6 @@
from mitmproxy.exceptions import ContentViewException from mitmproxy.exceptions import ContentViewException
from netlib.http import Headers from netlib.http import Headers
from netlib.odict import ODict
import netlib.utils import netlib.utils
from netlib import encoding from netlib import encoding
@ -45,6 +46,19 @@ class TestContentView:
) )
assert f[0].startswith("XML") assert f[0].startswith("XML")
f = v(
"",
headers=Headers()
)
assert f[0] == "No content"
f = v(
"",
headers=Headers(),
query=ODict([("foo", "bar")]),
)
assert f[0] == "Query"
def test_view_urlencoded(self): def test_view_urlencoded(self):
d = netlib.utils.urlencode([("one", "two"), ("three", "four")]) d = netlib.utils.urlencode([("one", "two"), ("three", "four")])
v = cv.ViewURLEncoded() v = cv.ViewURLEncoded()
@ -158,6 +172,13 @@ Larry
h = Headers(content_type="unparseable") h = Headers(content_type="unparseable")
assert not view(v, headers=h) assert not view(v, headers=h)
def test_view_query(self):
d = ""
v = cv.ViewQuery()
f = v(d, query=ODict([("foo", "bar")]))
assert f[0] == "Query"
assert [x for x in f[1]] == [[("header", "foo: "), ("text", "bar")]]
def test_get_content_view(self): def test_get_content_view(self):
r = cv.get_content_view( r = cv.get_content_view(
cv.get("Raw"), cv.get("Raw"),