mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 18:18:25 +00:00
Merge pull request #1974 from cortesi/setheaders
Regularise setheaders options
This commit is contained in:
commit
cf991ba4e2
@ -2,6 +2,43 @@ from mitmproxy import exceptions
|
|||||||
from mitmproxy import flowfilter
|
from mitmproxy import flowfilter
|
||||||
|
|
||||||
|
|
||||||
|
def parse_setheader(s):
|
||||||
|
"""
|
||||||
|
Returns a (pattern, regex, replacement) tuple.
|
||||||
|
|
||||||
|
The general form for a replacement hook is as follows:
|
||||||
|
|
||||||
|
/patt/regex/replacement
|
||||||
|
|
||||||
|
The first character specifies the separator. Example:
|
||||||
|
|
||||||
|
:~q:foo:bar
|
||||||
|
|
||||||
|
If only two clauses are specified, the pattern is set to match
|
||||||
|
universally (i.e. ".*"). Example:
|
||||||
|
|
||||||
|
/foo/bar/
|
||||||
|
|
||||||
|
Clauses are parsed from left to right. Extra separators are taken to be
|
||||||
|
part of the final clause. For instance, the replacement clause below is
|
||||||
|
"foo/bar/":
|
||||||
|
|
||||||
|
/one/two/foo/bar/
|
||||||
|
"""
|
||||||
|
sep, rem = s[0], s[1:]
|
||||||
|
parts = rem.split(sep, 2)
|
||||||
|
if len(parts) == 2:
|
||||||
|
patt = ".*"
|
||||||
|
a, b = parts
|
||||||
|
elif len(parts) == 3:
|
||||||
|
patt, a, b = parts
|
||||||
|
else:
|
||||||
|
raise exceptions.OptionsError(
|
||||||
|
"Invalid replacement specifier: %s" % s
|
||||||
|
)
|
||||||
|
return patt, a, b
|
||||||
|
|
||||||
|
|
||||||
class SetHeaders:
|
class SetHeaders:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.lst = []
|
self.lst = []
|
||||||
@ -16,7 +53,12 @@ class SetHeaders:
|
|||||||
"""
|
"""
|
||||||
if "setheaders" in updated:
|
if "setheaders" in updated:
|
||||||
self.lst = []
|
self.lst = []
|
||||||
for fpatt, header, value in options.setheaders:
|
for shead in options.setheaders:
|
||||||
|
if isinstance(shead, str):
|
||||||
|
fpatt, header, value = parse_setheader(shead)
|
||||||
|
else:
|
||||||
|
fpatt, header, value = shead
|
||||||
|
|
||||||
flt = flowfilter.parse(fpatt)
|
flt = flowfilter.parse(fpatt)
|
||||||
if not flt:
|
if not flt:
|
||||||
raise exceptions.OptionsError(
|
raise exceptions.OptionsError(
|
||||||
|
@ -41,7 +41,7 @@ class Options(optmanager.OptManager):
|
|||||||
replacements: Sequence[Union[Tuple[str, str, str], str]] = [],
|
replacements: Sequence[Union[Tuple[str, str, str], str]] = [],
|
||||||
replacement_files: Sequence[Union[Tuple[str, str, str], str]] = [],
|
replacement_files: Sequence[Union[Tuple[str, str, str], str]] = [],
|
||||||
server_replay_use_headers: Sequence[str] = [],
|
server_replay_use_headers: Sequence[str] = [],
|
||||||
setheaders: Sequence[Tuple[str, str, str]] = [],
|
setheaders: Sequence[Union[Tuple[str, str, str], str]] = [],
|
||||||
server_replay: Sequence[str] = [],
|
server_replay: Sequence[str] = [],
|
||||||
stickycookie: Optional[str] = None,
|
stickycookie: Optional[str] = None,
|
||||||
stickyauth: Optional[str] = None,
|
stickyauth: Optional[str] = None,
|
||||||
|
@ -2,7 +2,6 @@ import argparse
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from mitmproxy import exceptions
|
from mitmproxy import exceptions
|
||||||
from mitmproxy import flowfilter
|
|
||||||
from mitmproxy import options
|
from mitmproxy import options
|
||||||
from mitmproxy import platform
|
from mitmproxy import platform
|
||||||
from mitmproxy.utils import human
|
from mitmproxy.utils import human
|
||||||
@ -18,57 +17,6 @@ class ParseException(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _parse_hook(s):
|
|
||||||
sep, rem = s[0], s[1:]
|
|
||||||
parts = rem.split(sep, 2)
|
|
||||||
if len(parts) == 2:
|
|
||||||
patt = ".*"
|
|
||||||
a, b = parts
|
|
||||||
elif len(parts) == 3:
|
|
||||||
patt, a, b = parts
|
|
||||||
else:
|
|
||||||
raise ParseException(
|
|
||||||
"Malformed hook specifier - too few clauses: %s" % s
|
|
||||||
)
|
|
||||||
|
|
||||||
if not a:
|
|
||||||
raise ParseException("Empty clause: %s" % str(patt))
|
|
||||||
|
|
||||||
if not flowfilter.parse(patt):
|
|
||||||
raise ParseException("Malformed filter pattern: %s" % patt)
|
|
||||||
|
|
||||||
return patt, a, b
|
|
||||||
|
|
||||||
|
|
||||||
def parse_setheader(s):
|
|
||||||
"""
|
|
||||||
Returns a (pattern, header, value) tuple.
|
|
||||||
|
|
||||||
The general form for a replacement hook is as follows:
|
|
||||||
|
|
||||||
/patt/header/value
|
|
||||||
|
|
||||||
The first character specifies the separator. Example:
|
|
||||||
|
|
||||||
:~q:foo:bar
|
|
||||||
|
|
||||||
If only two clauses are specified, the pattern is set to match
|
|
||||||
universally (i.e. ".*"). Example:
|
|
||||||
|
|
||||||
/foo/bar/
|
|
||||||
|
|
||||||
Clauses are parsed from left to right. Extra separators are taken to be
|
|
||||||
part of the final clause. For instance, the value clause below is
|
|
||||||
"foo/bar/":
|
|
||||||
|
|
||||||
/one/two/foo/bar/
|
|
||||||
|
|
||||||
Checks that pattern and regex are both well-formed. Raises
|
|
||||||
ParseException on error.
|
|
||||||
"""
|
|
||||||
return _parse_hook(s)
|
|
||||||
|
|
||||||
|
|
||||||
def get_common_options(args):
|
def get_common_options(args):
|
||||||
stickycookie, stickyauth = None, None
|
stickycookie, stickyauth = None, None
|
||||||
if args.stickycookie_filt:
|
if args.stickycookie_filt:
|
||||||
@ -81,14 +29,6 @@ def get_common_options(args):
|
|||||||
if stream_large_bodies:
|
if stream_large_bodies:
|
||||||
stream_large_bodies = human.parse_size(stream_large_bodies)
|
stream_large_bodies = human.parse_size(stream_large_bodies)
|
||||||
|
|
||||||
setheaders = []
|
|
||||||
for i in args.setheader or []:
|
|
||||||
try:
|
|
||||||
p = parse_setheader(i)
|
|
||||||
except ParseException as e:
|
|
||||||
raise exceptions.OptionsError(e)
|
|
||||||
setheaders.append(p)
|
|
||||||
|
|
||||||
if args.streamfile and args.streamfile[0] == args.rfile:
|
if args.streamfile and args.streamfile[0] == args.rfile:
|
||||||
if args.streamfile[1] == "wb":
|
if args.streamfile[1] == "wb":
|
||||||
raise exceptions.OptionsError(
|
raise exceptions.OptionsError(
|
||||||
@ -171,7 +111,7 @@ def get_common_options(args):
|
|||||||
rfile=args.rfile,
|
rfile=args.rfile,
|
||||||
replacements=args.replacements,
|
replacements=args.replacements,
|
||||||
replacement_files=args.replacement_files,
|
replacement_files=args.replacement_files,
|
||||||
setheaders=setheaders,
|
setheaders=args.setheaders,
|
||||||
server_replay=args.server_replay,
|
server_replay=args.server_replay,
|
||||||
scripts=args.scripts,
|
scripts=args.scripts,
|
||||||
stickycookie=stickycookie,
|
stickycookie=stickycookie,
|
||||||
@ -648,7 +588,7 @@ def set_headers(parser):
|
|||||||
)
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"--setheader",
|
"--setheader",
|
||||||
action="append", type=str, dest="setheader",
|
action="append", type=str, dest="setheaders",
|
||||||
metavar="PATTERN",
|
metavar="PATTERN",
|
||||||
help="Header set pattern."
|
help="Header set pattern."
|
||||||
)
|
)
|
||||||
@ -708,8 +648,8 @@ def common_options(parser):
|
|||||||
|
|
||||||
|
|
||||||
def mitmproxy():
|
def mitmproxy():
|
||||||
# Don't import mitmproxy.tools.console for mitmdump, urwid is not available on all
|
# Don't import mitmproxy.tools.console for mitmdump, urwid is not available
|
||||||
# platforms.
|
# on all platforms.
|
||||||
from .console import palettes
|
from .console import palettes
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(usage="%(prog)s [options]")
|
parser = argparse.ArgumentParser(usage="%(prog)s [options]")
|
||||||
|
@ -7,6 +7,7 @@ from mitmproxy.tools.console import select
|
|||||||
from mitmproxy.tools.console import signals
|
from mitmproxy.tools.console import signals
|
||||||
|
|
||||||
from mitmproxy.addons import replace
|
from mitmproxy.addons import replace
|
||||||
|
from mitmproxy.addons import setheaders
|
||||||
|
|
||||||
footer = [
|
footer = [
|
||||||
('heading_key', "enter/space"), ":toggle ",
|
('heading_key', "enter/space"), ":toggle ",
|
||||||
@ -190,10 +191,16 @@ class Options(urwid.WidgetWrap):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def setheaders(self):
|
def setheaders(self):
|
||||||
|
data = []
|
||||||
|
for d in self.master.options.setheaders:
|
||||||
|
if isinstance(d, str):
|
||||||
|
data.append(setheaders.parse_setheader(d))
|
||||||
|
else:
|
||||||
|
data.append(d)
|
||||||
self.master.view_grideditor(
|
self.master.view_grideditor(
|
||||||
grideditor.SetHeadersEditor(
|
grideditor.SetHeadersEditor(
|
||||||
self.master,
|
self.master,
|
||||||
self.master.options.setheaders,
|
data,
|
||||||
self.master.options.setter("setheaders")
|
self.master.options.setter("setheaders")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -3,19 +3,28 @@ from mitmproxy.test import tutils
|
|||||||
from mitmproxy.test import taddons
|
from mitmproxy.test import taddons
|
||||||
|
|
||||||
from mitmproxy.addons import setheaders
|
from mitmproxy.addons import setheaders
|
||||||
from mitmproxy import options
|
|
||||||
|
|
||||||
|
|
||||||
class TestSetHeaders:
|
class TestSetHeaders:
|
||||||
|
def test_parse_setheaders(self):
|
||||||
|
x = setheaders.parse_setheader("/foo/bar/voing")
|
||||||
|
assert x == ("foo", "bar", "voing")
|
||||||
|
x = setheaders.parse_setheader("/foo/bar/vo/ing/")
|
||||||
|
assert x == ("foo", "bar", "vo/ing/")
|
||||||
|
x = setheaders.parse_setheader("/bar/voing")
|
||||||
|
assert x == (".*", "bar", "voing")
|
||||||
|
tutils.raises("invalid replacement", setheaders.parse_setheader, "/")
|
||||||
|
|
||||||
def test_configure(self):
|
def test_configure(self):
|
||||||
sh = setheaders.SetHeaders()
|
sh = setheaders.SetHeaders()
|
||||||
o = options.Options(
|
with taddons.context() as tctx:
|
||||||
setheaders = [("~b", "one", "two")]
|
tutils.raises(
|
||||||
)
|
"invalid setheader filter pattern",
|
||||||
tutils.raises(
|
tctx.configure,
|
||||||
"invalid setheader filter pattern",
|
sh,
|
||||||
sh.configure, o, o.keys()
|
setheaders = [("~b", "one", "two")]
|
||||||
)
|
)
|
||||||
|
tctx.configure(sh, setheaders = ["/foo/bar/voing"])
|
||||||
|
|
||||||
def test_setheaders(self):
|
def test_setheaders(self):
|
||||||
sh = setheaders.SetHeaders()
|
sh = setheaders.SetHeaders()
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
import argparse
|
import argparse
|
||||||
from mitmproxy.tools import cmdline
|
from mitmproxy.tools import cmdline
|
||||||
from mitmproxy.test import tutils
|
|
||||||
|
|
||||||
|
|
||||||
def test_parse_setheaders():
|
|
||||||
x = cmdline.parse_setheader("/foo/bar/voing")
|
|
||||||
assert x == ("foo", "bar", "voing")
|
|
||||||
|
|
||||||
|
|
||||||
def test_common():
|
def test_common():
|
||||||
@ -21,18 +15,6 @@ def test_common():
|
|||||||
assert v["stickycookie"] == "foo"
|
assert v["stickycookie"] == "foo"
|
||||||
assert v["stickyauth"] == "foo"
|
assert v["stickyauth"] == "foo"
|
||||||
|
|
||||||
opts.setheader = ["/foo/bar/voing"]
|
|
||||||
v = cmdline.get_common_options(opts)
|
|
||||||
assert v["setheaders"] == [("foo", "bar", "voing")]
|
|
||||||
|
|
||||||
opts.setheader = ["//"]
|
|
||||||
tutils.raises(
|
|
||||||
"empty clause",
|
|
||||||
cmdline.get_common_options,
|
|
||||||
opts
|
|
||||||
)
|
|
||||||
opts.setheader = []
|
|
||||||
|
|
||||||
|
|
||||||
def test_mitmproxy():
|
def test_mitmproxy():
|
||||||
ap = cmdline.mitmproxy()
|
ap = cmdline.mitmproxy()
|
||||||
|
Loading…
Reference in New Issue
Block a user