add Request.make

This commit is contained in:
Maximilian Hils 2017-03-15 14:04:58 +01:00
parent ec5d9cbd2b
commit 65c4a3cf1d
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.proxy.protocol import http_replay
from mitmproxy.types import basethread
import mitmproxy.net.http
from . import ctx as mitmproxy_ctx
@ -122,27 +121,18 @@ class Master:
self.should_exit.set()
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))
s = connections.ServerConnection.make_dummy((host, port))
s = connections.ServerConnection.make_dummy((req.host, req.port))
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
self.load_flow(f)
return f

View File

@ -1,6 +1,6 @@
import re
import urllib
from typing import Optional
from typing import Optional, AnyStr, Dict, Iterable, Tuple, Union
from mitmproxy.types import multidict
from mitmproxy.utils import strutils
@ -77,6 +77,53 @@ class Request(message.Message):
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):
"""
Replaces a regular expression pattern with repl in the headers, the

View File

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

View File

@ -1,7 +1,7 @@
from unittest import mock
import pytest
from mitmproxy.net.http import Headers
from mitmproxy.net.http import Headers, Request
from mitmproxy.test.tutils import treq
from .test_message import _test_decoded_attr, _test_passthrough_attr
@ -35,6 +35,32 @@ class TestRequestCore:
request.host = None
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):
r = treq()
r.path = b"foobarfoo"

View File

@ -140,7 +140,7 @@ class TestFlowMaster:
def test_create_flow(self):
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):
s = tservers.TestState()