Merge pull request #2161 from mhils/make-request

Add Request.make
This commit is contained in:
Thomas Kriechbaumer 2017-03-15 14:40:42 +01:00 committed by GitHub
commit cd93dabd75
5 changed files with 84 additions and 24 deletions

View File

@ -15,7 +15,6 @@ from mitmproxy import log
from mitmproxy import io from mitmproxy import io
from mitmproxy.proxy.protocol import http_replay from mitmproxy.proxy.protocol import http_replay
from mitmproxy.types import basethread from mitmproxy.types import basethread
import mitmproxy.net.http
from . import ctx as mitmproxy_ctx from . import ctx as mitmproxy_ctx
@ -122,27 +121,18 @@ class Master:
self.should_exit.set() self.should_exit.set()
self.addons.done() self.addons.done()
def create_request(self, method, scheme, host, port, path): def create_request(self, method, url):
""" """
this method creates a new artificial and minimalist request also adds it to flowlist Create a new artificial and minimalist request also adds it to flowlist.
Raises:
ValueError, if the url is malformed.
""" """
req = http.HTTPRequest.make(method, url)
c = connections.ClientConnection.make_dummy(("", 0)) c = connections.ClientConnection.make_dummy(("", 0))
s = connections.ServerConnection.make_dummy((host, port)) s = connections.ServerConnection.make_dummy((req.host, req.port))
f = http.HTTPFlow(c, s) f = http.HTTPFlow(c, s)
headers = mitmproxy.net.http.Headers()
req = http.HTTPRequest(
"absolute",
method,
scheme,
host,
port,
path,
b"HTTP/1.1",
headers,
b""
)
f.request = req f.request = req
self.load_flow(f) self.load_flow(f)
return f return f

View File

@ -1,6 +1,6 @@
import re import re
import urllib import urllib
from typing import Optional from typing import Optional, AnyStr, Dict, Iterable, Tuple, Union
from mitmproxy.types import multidict from mitmproxy.types import multidict
from mitmproxy.utils import strutils from mitmproxy.utils import strutils
@ -77,6 +77,53 @@ class Request(message.Message):
self.method, hostport, path self.method, hostport, path
) )
@classmethod
def make(
cls,
method: str,
url: str,
content: AnyStr = b"",
headers: Union[Dict[AnyStr, AnyStr], Iterable[Tuple[bytes, bytes]]] = ()
):
"""
Simplified API for creating request objects.
"""
req = cls(
"absolute",
method,
"",
"",
"",
"",
"HTTP/1.1",
(),
b""
)
req.url = url
# Headers can be list or dict, we differentiate here.
if isinstance(headers, dict):
req.headers = nheaders.Headers(**headers)
elif isinstance(headers, Iterable):
req.headers = nheaders.Headers(headers)
else:
raise TypeError("Expected headers to be an iterable or dict, but is {}.".format(
type(headers).__name__
))
# Assign this manually to update the content-length header.
if isinstance(content, bytes):
req.content = content
elif isinstance(content, str):
req.text = content
else:
raise TypeError("Expected content to be str or bytes, but is {}.".format(
type(content).__name__
))
return req
def replace(self, pattern, repl, flags=0, count=0): def replace(self, pattern, repl, flags=0, count=0):
""" """
Replaces a regular expression pattern with repl in the headers, the Replaces a regular expression pattern with repl in the headers, the

View File

@ -1,6 +1,5 @@
import urwid import urwid
import mitmproxy.net.http.url
from mitmproxy import exceptions from mitmproxy import exceptions
from mitmproxy.tools.console import common from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals from mitmproxy.tools.console import signals
@ -339,12 +338,10 @@ class FlowListBox(urwid.ListBox):
def new_request(self, url, method): def new_request(self, url, method):
try: try:
parts = mitmproxy.net.http.url.parse(str(url)) f = self.master.create_request(method, url)
except ValueError as e: except ValueError as e:
signals.status_message.send(message = "Invalid URL: " + str(e)) signals.status_message.send(message = "Invalid URL: " + str(e))
return return
scheme, host, port, path = parts
f = self.master.create_request(method, scheme, host, port, path)
self.master.view.focus.flow = f self.master.view.focus.flow = f
def keypress(self, size, key): def keypress(self, size, key):

View File

@ -1,7 +1,7 @@
from unittest import mock from unittest import mock
import pytest import pytest
from mitmproxy.net.http import Headers from mitmproxy.net.http import Headers, Request
from mitmproxy.test.tutils import treq from mitmproxy.test.tutils import treq
from .test_message import _test_decoded_attr, _test_passthrough_attr from .test_message import _test_decoded_attr, _test_passthrough_attr
@ -35,6 +35,32 @@ class TestRequestCore:
request.host = None request.host = None
assert repr(request) == "Request(GET /path)" assert repr(request) == "Request(GET /path)"
def test_make(self):
r = Request.make("GET", "https://example.com/")
assert r.method == "GET"
assert r.scheme == "https"
assert r.host == "example.com"
assert r.port == 443
assert r.path == "/"
r = Request.make("GET", "https://example.com/", "content", {"Foo": "bar"})
assert r.content == b"content"
assert r.headers["content-length"] == "7"
assert r.headers["Foo"] == "bar"
Request.make("GET", "https://example.com/", content=b"content")
with pytest.raises(TypeError):
Request.make("GET", "https://example.com/", content=42)
r = Request.make("GET", "https://example.com/", headers=[(b"foo", b"bar")])
assert r.headers["foo"] == "bar"
r = Request.make("GET", "https://example.com/", headers=({"foo": "baz"}))
assert r.headers["foo"] == "baz"
with pytest.raises(TypeError):
Request.make("GET", "https://example.com/", headers=42)
def test_replace(self): def test_replace(self):
r = treq() r = treq()
r.path = b"foobarfoo" r.path = b"foobarfoo"

View File

@ -140,7 +140,7 @@ class TestFlowMaster:
def test_create_flow(self): def test_create_flow(self):
fm = master.Master(None, DummyServer()) fm = master.Master(None, DummyServer())
assert fm.create_request("GET", "http", "example.com", 80, "/") assert fm.create_request("GET", "http://example.com/")
def test_all(self): def test_all(self):
s = tservers.TestState() s = tservers.TestState()