From bd00132b65723c6aed14b2643cfebde4cffb36fc Mon Sep 17 00:00:00 2001 From: Roy Tu Date: Wed, 9 Jun 2021 03:26:19 -0700 Subject: [PATCH] Fix multipart forms losing `boundary` values on edit (#4625) * Fix for issue #4613 * Adding tests * Updated CHANGELOG.md * Restoring contentviews * Reverting contentview tests * Adding boundary generation and tests * Extra newline for flake8 * Janky byte fix * Revert "Extra newline for flake8" This reverts commit 683ba167de2264d29f318e2bab83e13cbfb8812d. * Reverting a commit that was supposed to go to dev branch * Update CHANGELOG.md * Update test_http.py Co-authored-by: Maximilian Hils --- CHANGELOG.md | 1 + mitmproxy/http.py | 13 ++++++++++++- test/mitmproxy/test_http.py | 6 +++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f73196422..55880cd7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ If you depend on these features, please raise your voice in * Customize markers with emoji, and filters: The `flow.mark` command may be used to mark a flow with either the default "red ball" marker, a single character, or an emoji like `:grapes:`. Use the `~marker` filter to filter on marker characters. (@rbdixon) * New `flow.comment` command to add a comment to the flow. Add `~comment ` filter syntax to search flow comments. (@rbdixon) +* Fix multipart forms losing `boundary` values on edit (@roytu) * --- TODO: add new PRs above this line --- * ... and various other fixes, documentation improvements, dependency version bumps, etc. diff --git a/mitmproxy/http.py b/mitmproxy/http.py index f5873b077..d901fec3f 100644 --- a/mitmproxy/http.py +++ b/mitmproxy/http.py @@ -1,3 +1,5 @@ +import binascii +import os import re import time import urllib.parse @@ -943,8 +945,17 @@ class Request(Message): return () def _set_multipart_form(self, value): + is_valid_content_type = self.headers.get("content-type", "").lower().startswith("multipart/form-data") + if not is_valid_content_type: + """ + Generate a random boundary here. + + See for specifications + on generating the boundary. + """ + boundary = "-" * 20 + binascii.hexlify(os.urandom(16)).decode() + self.headers["content-type"] = f"multipart/form-data; boundary={boundary}" self.content = multipart.encode(self.headers, value) - self.headers["content-type"] = "multipart/form-data" @property def multipart_form(self) -> multidict.MultiDictView[bytes, bytes]: diff --git a/test/mitmproxy/test_http.py b/test/mitmproxy/test_http.py index 2d1cbb0ba..2258df88e 100644 --- a/test/mitmproxy/test_http.py +++ b/test/mitmproxy/test_http.py @@ -429,9 +429,9 @@ class TestRequestUtils: def test_set_multipart_form(self): request = treq() - request.multipart_form = [("file", "shell.jpg"), ("file_size", "1000")] - assert request.headers["Content-Type"] == 'multipart/form-data' - assert request.content is None + request.multipart_form = [(b"file", b"shell.jpg"), (b"file_size", b"1000")] + assert request.headers["Content-Type"].startswith('multipart/form-data') + assert list(request.multipart_form.items()) == [(b"file", b"shell.jpg"), (b"file_size", b"1000")] class TestResponse: