diff options
-rw-r--r-- | mitmproxy/master.py | 24 | ||||
-rw-r--r-- | mitmproxy/net/http/request.py | 49 | ||||
-rw-r--r-- | mitmproxy/tools/console/flowlist.py | 5 | ||||
-rw-r--r-- | release/README.md | 27 | ||||
-rw-r--r-- | setup.py | 4 | ||||
-rw-r--r-- | test/mitmproxy/net/http/test_request.py | 28 | ||||
-rw-r--r-- | test/mitmproxy/test_flow.py | 2 |
7 files changed, 105 insertions, 34 deletions
diff --git a/mitmproxy/master.py b/mitmproxy/master.py index 19d069bc..887a9240 100644 --- a/mitmproxy/master.py +++ b/mitmproxy/master.py @@ -12,7 +12,6 @@ from mitmproxy import http from mitmproxy import log from mitmproxy.proxy.protocol import http_replay from mitmproxy.types import basethread -import mitmproxy.net.http from . import ctx as mitmproxy_ctx @@ -117,27 +116,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 diff --git a/mitmproxy/net/http/request.py b/mitmproxy/net/http/request.py index b961e1e4..90a1f924 100644 --- a/mitmproxy/net/http/request.py +++ b/mitmproxy/net/http/request.py @@ -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 diff --git a/mitmproxy/tools/console/flowlist.py b/mitmproxy/tools/console/flowlist.py index d2e28d35..5fe86975 100644 --- a/mitmproxy/tools/console/flowlist.py +++ b/mitmproxy/tools/console/flowlist.py @@ -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): diff --git a/release/README.md b/release/README.md index 02fabfe9..a30221c8 100644 --- a/release/README.md +++ b/release/README.md @@ -1,14 +1,25 @@ # Release Checklist +Make sure run all these steps on the correct branch you want to create a new release for! +- Verify `mitmproxy/version.py` - Update CHANGELOG -- Verify that all CI tests pass for current master -- Tag the release, and push to Github +- Verify that all CI tests pass +- Tag the release and push to Github - Wait for tag CI to complete -- Download assets from snapshots.mitmproxy.org -- Create release notice on Github -- Upload wheel to pypi (`twine upload wheelname`) + +## GitHub Release +- Create release notice on Github [https://github.com/mitmproxy/mitmproxy/releases/new](here) +- Attach all files from the new release folder on https://snapshots.mitmproxy.org + +## PyPi +- Upload wheel to pypi: `twine upload <mitmproxy-...-.whl` + +## Docker - Update docker-releases repo - Create a new branch based of master for major versions. - - Add a commit that pins dependencies like so: https://github.com/mitmproxy/docker-releases/commit/3d6a9989fde068ad0aea257823ac3d7986ff1613. The requirements can be obtained by creating a fresh venv, pip-installing the new wheel in there, and then running `pip freeze`. -- Update `latest` tag on https://hub.docker.com/r/mitmproxy/mitmproxy/~/settings/automated-builds/ -- Bump the version in https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/version.py and update https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/io_compat.py in the next commit + - Update the dependencies in [alpine/requirements.txt](https://github.com/mitmproxy/docker-releases/commit/3d6a9989fde068ad0aea257823ac3d7986ff1613#diff-9b7e0eea8ae74688b1ac13ea080549ba) + * Creating a fresh venv, pip-installing the new wheel in there, and then export all packages: + * `virtualenv -ppython3.5 venv && source venv/bin/activate && pip install mitmproxy && pip freeze` +- Update `latest` tag [https://hub.docker.com/r/mitmproxy/mitmproxy/~/settings/automated-builds/](here) + +After everything is done, you might want to bump the version on master in [https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/version.py](mitmproxy/version.py) if you just created a major release. @@ -64,7 +64,7 @@ setup( "click>=6.2, <7", "certifi>=2015.11.20.1", # no semver here - this should always be on the last release! "construct>=2.8, <2.9", - "cryptography>=1.3, <1.8", + "cryptography>=1.3, <1.9", "cssutils>=1.0.1, <1.1", "h2>=2.5.1, <3", "html2text>=2016.1.8, <=2016.9.19", @@ -74,7 +74,7 @@ setup( "passlib>=1.6.5, <1.8", "pyasn1>=0.1.9, <0.3", "pyOpenSSL>=16.0, <17.0", - "pyparsing>=2.1.3, <2.2", + "pyparsing>=2.1.3, <2.3", "pyperclip>=1.5.22, <1.6", "requests>=2.9.1, <3", "ruamel.yaml>=0.13.2, <0.14", diff --git a/test/mitmproxy/net/http/test_request.py b/test/mitmproxy/net/http/test_request.py index 90ec31fe..ce49002c 100644 --- a/test/mitmproxy/net/http/test_request.py +++ b/test/mitmproxy/net/http/test_request.py @@ -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" diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 1fb33bb2..4f87a6ae 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -115,7 +115,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() |