forked from mitmproxy/mitmproxy
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request mitmproxy#3188 from Kriechi/py36-check
fix syntax-error on older python interpreters
- Loading branch information
Showing
4 changed files
with
200 additions
and
173 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
""" | ||
This file contains python3.6+ syntax! | ||
Feel free to import and use whatever new package you deem necessary. | ||
""" | ||
|
||
import os | ||
import sys | ||
import asyncio | ||
import argparse # noqa | ||
import signal # noqa | ||
import typing # noqa | ||
|
||
from mitmproxy.tools import cmdline # noqa | ||
from mitmproxy import exceptions, master # noqa | ||
from mitmproxy import options # noqa | ||
from mitmproxy import optmanager # noqa | ||
from mitmproxy import proxy # noqa | ||
from mitmproxy import log # noqa | ||
from mitmproxy.utils import debug, arg_check # noqa | ||
|
||
OPTIONS_FILE_NAME = "config.yaml" | ||
|
||
|
||
def assert_utf8_env(): | ||
spec = "" | ||
for i in ["LANG", "LC_CTYPE", "LC_ALL"]: | ||
spec += os.environ.get(i, "").lower() | ||
if "utf" not in spec: | ||
print( | ||
"Error: mitmproxy requires a UTF console environment.", | ||
file=sys.stderr | ||
) | ||
print( | ||
"Set your LANG environment variable to something like en_US.UTF-8", | ||
file=sys.stderr | ||
) | ||
sys.exit(1) | ||
|
||
|
||
def process_options(parser, opts, args): | ||
if args.version: | ||
print(debug.dump_system_info()) | ||
sys.exit(0) | ||
if args.quiet or args.options or args.commands: | ||
# also reduce log verbosity if --options or --commands is passed, | ||
# we don't want log messages from regular startup then. | ||
args.termlog_verbosity = 'error' | ||
args.flow_detail = 0 | ||
if args.verbose: | ||
args.termlog_verbosity = 'debug' | ||
args.flow_detail = 2 | ||
|
||
adict = {} | ||
for n in dir(args): | ||
if n in opts: | ||
adict[n] = getattr(args, n) | ||
opts.merge(adict) | ||
|
||
return proxy.config.ProxyConfig(opts) | ||
|
||
|
||
def run( | ||
master_cls: typing.Type[master.Master], | ||
make_parser: typing.Callable[[options.Options], argparse.ArgumentParser], | ||
arguments: typing.Sequence[str], | ||
extra: typing.Callable[[typing.Any], dict] = None | ||
) -> master.Master: # pragma: no cover | ||
""" | ||
extra: Extra argument processing callable which returns a dict of | ||
options. | ||
""" | ||
debug.register_info_dumpers() | ||
|
||
opts = options.Options() | ||
master = master_cls(opts) | ||
|
||
parser = make_parser(opts) | ||
|
||
# To make migration from 2.x to 3.0 bearable. | ||
if "-R" in sys.argv and sys.argv[sys.argv.index("-R") + 1].startswith("http"): | ||
print("-R is used for specifying replacements.\n" | ||
"To use mitmproxy in reverse mode please use --mode reverse:SPEC instead") | ||
|
||
try: | ||
args = parser.parse_args(arguments) | ||
except SystemExit: | ||
arg_check.check() | ||
sys.exit(1) | ||
try: | ||
opts.confdir = args.confdir | ||
optmanager.load_paths( | ||
opts, | ||
os.path.join(opts.confdir, OPTIONS_FILE_NAME), | ||
) | ||
pconf = process_options(parser, opts, args) | ||
server: typing.Any = None | ||
if pconf.options.server: | ||
try: | ||
server = proxy.server.ProxyServer(pconf) | ||
except exceptions.ServerException as v: | ||
print(str(v), file=sys.stderr) | ||
sys.exit(1) | ||
else: | ||
server = proxy.server.DummyServer(pconf) | ||
|
||
master.server = server | ||
if args.options: | ||
print(optmanager.dump_defaults(opts)) | ||
sys.exit(0) | ||
if args.commands: | ||
master.commands.dump() | ||
sys.exit(0) | ||
opts.set(*args.setoptions, defer=True) | ||
if extra: | ||
opts.update(**extra(args)) | ||
|
||
loop = asyncio.get_event_loop() | ||
for signame in ('SIGINT', 'SIGTERM'): | ||
try: | ||
loop.add_signal_handler(getattr(signal, signame), master.shutdown) | ||
except NotImplementedError: | ||
# Not supported on Windows | ||
pass | ||
|
||
# Make sure that we catch KeyboardInterrupts on Windows. | ||
# https://stackoverflow.com/a/36925722/934719 | ||
if os.name == "nt": | ||
async def wakeup(): | ||
while True: | ||
await asyncio.sleep(0.2) | ||
asyncio.ensure_future(wakeup()) | ||
|
||
master.run() | ||
except exceptions.OptionsError as e: | ||
print("%s: %s" % (sys.argv[0], e), file=sys.stderr) | ||
sys.exit(1) | ||
except (KeyboardInterrupt, RuntimeError) as e: | ||
pass | ||
return master | ||
|
||
|
||
def mitmproxy(args=None) -> typing.Optional[int]: # pragma: no cover | ||
if os.name == "nt": | ||
print("Error: mitmproxy's console interface is not supported on Windows. " | ||
"You can run mitmdump or mitmweb instead.", file=sys.stderr) | ||
return 1 | ||
assert_utf8_env() | ||
from mitmproxy.tools import console | ||
run(console.master.ConsoleMaster, cmdline.mitmproxy, args) | ||
return None | ||
|
||
|
||
def mitmdump(args=None) -> typing.Optional[int]: # pragma: no cover | ||
from mitmproxy.tools import dump | ||
|
||
def extra(args): | ||
if args.filter_args: | ||
v = " ".join(args.filter_args) | ||
return dict( | ||
save_stream_filter=v, | ||
readfile_filter=v, | ||
dumper_filter=v, | ||
) | ||
return {} | ||
|
||
m = run(dump.DumpMaster, cmdline.mitmdump, args, extra) | ||
if m and m.errorcheck.has_errored: # type: ignore | ||
return 1 | ||
return None | ||
|
||
|
||
def mitmweb(args=None) -> typing.Optional[int]: # pragma: no cover | ||
from mitmproxy.tools import web | ||
run(web.master.WebMaster, cmdline.mitmweb, args) | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,180 +1,22 @@ | ||
""" | ||
This file must be kept in a python2.7 and python3.5 compatible syntax! | ||
DO NOT use type annotations or other python3.6-only features that makes this file unparsable by older interpreters! | ||
""" | ||
|
||
from __future__ import print_function # this is here for the version check to work on Python 2. | ||
|
||
import asyncio | ||
import sys | ||
|
||
if sys.version_info < (3, 6): | ||
# This must be before any mitmproxy imports, as they already break! | ||
# Keep all other imports below with the 'noqa' magic comment. | ||
print("#" * 49, file=sys.stderr) | ||
print("# mitmproxy requires Python 3.6 or higher! #", file=sys.stderr) | ||
print("#" * 49, file=sys.stderr) | ||
|
||
import argparse # noqa | ||
import os # noqa | ||
import signal # noqa | ||
import typing # noqa | ||
|
||
from mitmproxy.tools import cmdline # noqa | ||
from mitmproxy import exceptions, master # noqa | ||
from mitmproxy import options # noqa | ||
from mitmproxy import optmanager # noqa | ||
from mitmproxy import proxy # noqa | ||
from mitmproxy import log # noqa | ||
from mitmproxy.utils import debug, arg_check # noqa | ||
|
||
OPTIONS_FILE_NAME = "config.yaml" | ||
|
||
|
||
def assert_utf8_env(): | ||
spec = "" | ||
for i in ["LANG", "LC_CTYPE", "LC_ALL"]: | ||
spec += os.environ.get(i, "").lower() | ||
if "utf" not in spec: | ||
print( | ||
"Error: mitmproxy requires a UTF console environment.", | ||
file=sys.stderr | ||
) | ||
print( | ||
"Set your LANG environment variable to something like en_US.UTF-8", | ||
file=sys.stderr | ||
) | ||
sys.exit(1) | ||
|
||
|
||
def process_options(parser, opts, args): | ||
if args.version: | ||
print(debug.dump_system_info()) | ||
sys.exit(0) | ||
if args.quiet or args.options or args.commands: | ||
# also reduce log verbosity if --options or --commands is passed, | ||
# we don't want log messages from regular startup then. | ||
args.termlog_verbosity = 'error' | ||
args.flow_detail = 0 | ||
if args.verbose: | ||
args.termlog_verbosity = 'debug' | ||
args.flow_detail = 2 | ||
|
||
adict = {} | ||
for n in dir(args): | ||
if n in opts: | ||
adict[n] = getattr(args, n) | ||
opts.merge(adict) | ||
|
||
return proxy.config.ProxyConfig(opts) | ||
|
||
|
||
def run( | ||
master_cls: typing.Type[master.Master], | ||
make_parser: typing.Callable[[options.Options], argparse.ArgumentParser], | ||
arguments: typing.Sequence[str], | ||
extra: typing.Callable[[typing.Any], dict] = None | ||
) -> master.Master: # pragma: no cover | ||
""" | ||
extra: Extra argument processing callable which returns a dict of | ||
options. | ||
""" | ||
debug.register_info_dumpers() | ||
|
||
opts = options.Options() | ||
master = master_cls(opts) | ||
|
||
parser = make_parser(opts) | ||
|
||
# To make migration from 2.x to 3.0 bearable. | ||
if "-R" in sys.argv and sys.argv[sys.argv.index("-R") + 1].startswith("http"): | ||
print("-R is used for specifying replacements.\n" | ||
"To use mitmproxy in reverse mode please use --mode reverse:SPEC instead") | ||
|
||
try: | ||
args = parser.parse_args(arguments) | ||
except SystemExit: | ||
arg_check.check() | ||
sys.exit(1) | ||
try: | ||
opts.confdir = args.confdir | ||
optmanager.load_paths( | ||
opts, | ||
os.path.join(opts.confdir, OPTIONS_FILE_NAME), | ||
) | ||
pconf = process_options(parser, opts, args) | ||
server: typing.Any = None | ||
if pconf.options.server: | ||
try: | ||
server = proxy.server.ProxyServer(pconf) | ||
except exceptions.ServerException as v: | ||
print(str(v), file=sys.stderr) | ||
sys.exit(1) | ||
else: | ||
server = proxy.server.DummyServer(pconf) | ||
|
||
master.server = server | ||
if args.options: | ||
print(optmanager.dump_defaults(opts)) | ||
sys.exit(0) | ||
if args.commands: | ||
master.commands.dump() | ||
sys.exit(0) | ||
opts.set(*args.setoptions, defer=True) | ||
if extra: | ||
opts.update(**extra(args)) | ||
|
||
loop = asyncio.get_event_loop() | ||
for signame in ('SIGINT', 'SIGTERM'): | ||
try: | ||
loop.add_signal_handler(getattr(signal, signame), master.shutdown) | ||
except NotImplementedError: | ||
# Not supported on Windows | ||
pass | ||
|
||
# Make sure that we catch KeyboardInterrupts on Windows. | ||
# https://stackoverflow.com/a/36925722/934719 | ||
if os.name == "nt": | ||
async def wakeup(): | ||
while True: | ||
await asyncio.sleep(0.2) | ||
asyncio.ensure_future(wakeup()) | ||
|
||
master.run() | ||
except exceptions.OptionsError as e: | ||
print("%s: %s" % (sys.argv[0], e), file=sys.stderr) | ||
sys.exit(1) | ||
except (KeyboardInterrupt, RuntimeError) as e: | ||
pass | ||
return master | ||
|
||
|
||
def mitmproxy(args=None) -> typing.Optional[int]: # pragma: no cover | ||
if os.name == "nt": | ||
print("Error: mitmproxy's console interface is not supported on Windows. " | ||
"You can run mitmdump or mitmweb instead.", file=sys.stderr) | ||
return 1 | ||
assert_utf8_env() | ||
from mitmproxy.tools import console | ||
run(console.master.ConsoleMaster, cmdline.mitmproxy, args) | ||
return None | ||
|
||
|
||
def mitmdump(args=None) -> typing.Optional[int]: # pragma: no cover | ||
from mitmproxy.tools import dump | ||
|
||
def extra(args): | ||
if args.filter_args: | ||
v = " ".join(args.filter_args) | ||
return dict( | ||
save_stream_filter=v, | ||
readfile_filter=v, | ||
dumper_filter=v, | ||
) | ||
return {} | ||
|
||
m = run(dump.DumpMaster, cmdline.mitmdump, args, extra) | ||
if m and m.errorcheck.has_errored: # type: ignore | ||
return 1 | ||
return None | ||
|
||
|
||
def mitmweb(args=None) -> typing.Optional[int]: # pragma: no cover | ||
from mitmproxy.tools import web | ||
run(web.master.WebMaster, cmdline.mitmweb, args) | ||
return None | ||
print("#" * 76, file=sys.stderr) | ||
print("# mitmproxy requires Python 3.6 or higher! #", file=sys.stderr) | ||
print("#" + " " * 74 + "#", file=sys.stderr) | ||
print("# Please upgrade your Python intepreter or use our mitmproxy binaries from #", file=sys.stderr) | ||
print("# https://mitmproxy.org. If your operating system does not include the #", file=sys.stderr) | ||
print("# required Python version, you can try using pyenv or similar tools. #", file=sys.stderr) | ||
print("#" * 76, file=sys.stderr) | ||
sys.exit(1) | ||
else: | ||
from ._main import * # noqa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters