diff options
Diffstat (limited to 'examples/simple')
-rw-r--r-- | examples/simple/README.md | 18 | ||||
-rw-r--r-- | examples/simple/add_header.py | 2 | ||||
-rw-r--r-- | examples/simple/add_header_class.py | 7 | ||||
-rw-r--r-- | examples/simple/custom_contentview.py | 28 | ||||
-rw-r--r-- | examples/simple/filter_flows.py | 23 | ||||
-rw-r--r-- | examples/simple/io_read_dumpfile.py | 21 | ||||
-rw-r--r-- | examples/simple/io_write_dumpfile.py | 29 | ||||
-rw-r--r-- | examples/simple/logging.py | 12 | ||||
-rw-r--r-- | examples/simple/modify_body_inject_iframe.py | 29 | ||||
-rw-r--r-- | examples/simple/modify_form.py | 10 | ||||
-rw-r--r-- | examples/simple/modify_querystring.py | 2 | ||||
-rw-r--r-- | examples/simple/redirect_requests.py | 11 | ||||
-rw-r--r-- | examples/simple/script_arguments.py | 17 | ||||
-rw-r--r-- | examples/simple/send_reply_from_proxy.py | 17 | ||||
-rw-r--r-- | examples/simple/upsidedownternet.py | 16 | ||||
-rw-r--r-- | examples/simple/wsgi_flask_app.py | 25 |
16 files changed, 267 insertions, 0 deletions
diff --git a/examples/simple/README.md b/examples/simple/README.md new file mode 100644 index 00000000..52f15627 --- /dev/null +++ b/examples/simple/README.md @@ -0,0 +1,18 @@ +## Simple Examples + +| Filename | Description | +|:-----------------------------|:---------------------------------------------------------------------------| +| add_header.py | Simple script that just adds a header to every request. | +| custom_contentview.py | Add a custom content view to the mitmproxy UI. | +| filter_flows.py | This script demonstrates how to use mitmproxy's filter pattern in scripts. | +| io_read_dumpfile.py | Read a dumpfile generated by mitmproxy. | +| io_write_dumpfile.py | Only write selected flows into a mitmproxy dumpfile. | +| logging.py | Use mitmproxy's logging API. | +| modify_body_inject_iframe.py | Inject configurable iframe into pages. | +| modify_form.py | Modify HTTP form submissions. | +| modify_querystring.py | Modify HTTP query strings. | +| redirect_requests.py | Redirect a request to a different server. | +| script_arguments.py | Add arguments to a script. | +| send_reply_from_proxy.py | Send a HTTP response directly from the proxy. | +| upsidedownternet.py | Turn all images upside down. | +| wsgi_flask_app.py | Embed a WSGI app into mitmproxy. |
\ No newline at end of file diff --git a/examples/simple/add_header.py b/examples/simple/add_header.py new file mode 100644 index 00000000..3e0b5f1e --- /dev/null +++ b/examples/simple/add_header.py @@ -0,0 +1,2 @@ +def response(flow): + flow.response.headers["newheader"] = "foo" diff --git a/examples/simple/add_header_class.py b/examples/simple/add_header_class.py new file mode 100644 index 00000000..6443798a --- /dev/null +++ b/examples/simple/add_header_class.py @@ -0,0 +1,7 @@ +class AddHeader: + def response(self, flow): + flow.response.headers["newheader"] = "foo" + + +def start(): + return AddHeader() diff --git a/examples/simple/custom_contentview.py b/examples/simple/custom_contentview.py new file mode 100644 index 00000000..35216397 --- /dev/null +++ b/examples/simple/custom_contentview.py @@ -0,0 +1,28 @@ +""" +This example shows how one can add a custom contentview to mitmproxy. +The content view API is explained in the mitmproxy.contentviews module. +""" +from mitmproxy import contentviews + + +class ViewSwapCase(contentviews.View): + name = "swapcase" + + # We don't have a good solution for the keyboard shortcut yet - + # you manually need to find a free letter. Contributions welcome :) + prompt = ("swap case text", "p") + content_types = ["text/plain"] + + def __call__(self, data: bytes, **metadata): + return "case-swapped text", contentviews.format_text(data.swapcase()) + + +view = ViewSwapCase() + + +def start(): + contentviews.add(view) + + +def done(): + contentviews.remove(view) diff --git a/examples/simple/filter_flows.py b/examples/simple/filter_flows.py new file mode 100644 index 00000000..29d0a9b8 --- /dev/null +++ b/examples/simple/filter_flows.py @@ -0,0 +1,23 @@ +""" +This scripts demonstrates how to use mitmproxy's filter pattern in scripts. +Usage: + mitmdump -s "flowfilter.py FILTER" +""" +import sys +from mitmproxy import flowfilter + + +class Filter: + def __init__(self, spec): + self.filter = flowfilter.parse(spec) + + def response(self, flow): + if flowfilter.match(self.filter, flow): + print("Flow matches filter:") + print(flow) + + +def start(): + if len(sys.argv) != 2: + raise ValueError("Usage: -s 'filt.py FILTER'") + return Filter(sys.argv[1]) diff --git a/examples/simple/io_read_dumpfile.py b/examples/simple/io_read_dumpfile.py new file mode 100644 index 00000000..edbbe2dd --- /dev/null +++ b/examples/simple/io_read_dumpfile.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# +# Simple script showing how to read a mitmproxy dump file +# + +from mitmproxy import io +from mitmproxy.exceptions import FlowReadException +import pprint +import sys + +with open(sys.argv[1], "rb") as logfile: + freader = io.FlowReader(logfile) + pp = pprint.PrettyPrinter(indent=4) + try: + for f in freader.stream(): + print(f) + print(f.request.host) + pp.pprint(f.get_state()) + print("") + except FlowReadException as e: + print("Flow file corrupted: {}".format(e)) diff --git a/examples/simple/io_write_dumpfile.py b/examples/simple/io_write_dumpfile.py new file mode 100644 index 00000000..ff1fd0f4 --- /dev/null +++ b/examples/simple/io_write_dumpfile.py @@ -0,0 +1,29 @@ +""" +This script how to generate a mitmproxy dump file, +as it would also be generated by passing `-w` to mitmproxy. +In contrast to `-w`, this gives you full control over which +flows should be saved and also allows you to rotate files or log +to multiple files in parallel. +""" +import random +import sys +from mitmproxy import io + + +class Writer: + def __init__(self, path): + if path == "-": + f = sys.stdout + else: + f = open(path, "wb") + self.w = io.FlowWriter(f) + + def response(self, flow): + if random.choice([True, False]): + self.w.add(flow) + + +def start(): + if len(sys.argv) != 2: + raise ValueError('Usage: -s "flowriter.py filename"') + return Writer(sys.argv[1]) diff --git a/examples/simple/logging.py b/examples/simple/logging.py new file mode 100644 index 00000000..ab1baf75 --- /dev/null +++ b/examples/simple/logging.py @@ -0,0 +1,12 @@ +""" +It is recommended to use `ctx.log` for logging within a script. +This goes to the event log in mitmproxy and to stdout in mitmdump. + +If you want to help us out: https://github.com/mitmproxy/mitmproxy/issues/1530 :-) +""" +from mitmproxy import ctx + + +def start(): + ctx.log.info("This is some informative text.") + ctx.log.error("This is an error.") diff --git a/examples/simple/modify_body_inject_iframe.py b/examples/simple/modify_body_inject_iframe.py new file mode 100644 index 00000000..33d18bbd --- /dev/null +++ b/examples/simple/modify_body_inject_iframe.py @@ -0,0 +1,29 @@ +# Usage: mitmdump -s "iframe_injector.py url" +# (this script works best with --anticache) +import sys +from bs4 import BeautifulSoup + + +class Injector: + def __init__(self, iframe_url): + self.iframe_url = iframe_url + + def response(self, flow): + if flow.request.host in self.iframe_url: + return + html = BeautifulSoup(flow.response.content, "lxml") + if html.body: + iframe = html.new_tag( + "iframe", + src=self.iframe_url, + frameborder=0, + height=0, + width=0) + html.body.insert(0, iframe) + flow.response.content = str(html).encode("utf8") + + +def start(): + if len(sys.argv) != 2: + raise ValueError('Usage: -s "iframe_injector.py url"') + return Injector(sys.argv[1]) diff --git a/examples/simple/modify_form.py b/examples/simple/modify_form.py new file mode 100644 index 00000000..b425efb0 --- /dev/null +++ b/examples/simple/modify_form.py @@ -0,0 +1,10 @@ +def request(flow): + if flow.request.urlencoded_form: + # If there's already a form, one can just add items to the dict: + flow.request.urlencoded_form["mitmproxy"] = "rocks" + else: + # One can also just pass new form data. + # This sets the proper content type and overrides the body. + flow.request.urlencoded_form = [ + ("foo", "bar") + ] diff --git a/examples/simple/modify_querystring.py b/examples/simple/modify_querystring.py new file mode 100644 index 00000000..ee8a89ad --- /dev/null +++ b/examples/simple/modify_querystring.py @@ -0,0 +1,2 @@ +def request(flow): + flow.request.query["mitmproxy"] = "rocks" diff --git a/examples/simple/redirect_requests.py b/examples/simple/redirect_requests.py new file mode 100644 index 00000000..51876df7 --- /dev/null +++ b/examples/simple/redirect_requests.py @@ -0,0 +1,11 @@ +""" +This example shows two ways to redirect flows to another server. +""" + + +def request(flow): + # pretty_host takes the "Host" header of the request into account, + # which is useful in transparent mode where we usually only have the IP + # otherwise. + if flow.request.pretty_host == "example.org": + flow.request.host = "mitmproxy.org" diff --git a/examples/simple/script_arguments.py b/examples/simple/script_arguments.py new file mode 100644 index 00000000..70851192 --- /dev/null +++ b/examples/simple/script_arguments.py @@ -0,0 +1,17 @@ +import argparse + + +class Replacer: + def __init__(self, src, dst): + self.src, self.dst = src, dst + + def response(self, flow): + flow.response.replace(self.src, self.dst) + + +def start(): + parser = argparse.ArgumentParser() + parser.add_argument("src", type=str) + parser.add_argument("dst", type=str) + args = parser.parse_args() + return Replacer(args.src, args.dst) diff --git a/examples/simple/send_reply_from_proxy.py b/examples/simple/send_reply_from_proxy.py new file mode 100644 index 00000000..bef2e7e7 --- /dev/null +++ b/examples/simple/send_reply_from_proxy.py @@ -0,0 +1,17 @@ +""" +This example shows how to send a reply from the proxy immediately +without sending any data to the remote server. +""" +from mitmproxy import http + + +def request(flow): + # pretty_url takes the "Host" header of the request into account, which + # is useful in transparent mode where we usually only have the IP otherwise. + + if flow.request.pretty_url == "http://example.com/path": + flow.response = http.HTTPResponse.make( + 200, # (optional) status code + b"Hello World", # (optional) content + {"Content-Type": "text/html"} # (optional) headers + ) diff --git a/examples/simple/upsidedownternet.py b/examples/simple/upsidedownternet.py new file mode 100644 index 00000000..8ba450ab --- /dev/null +++ b/examples/simple/upsidedownternet.py @@ -0,0 +1,16 @@ +""" +This script rotates all images passing through the proxy by 180 degrees. +""" +import io + +from PIL import Image + + +def response(flow): + if flow.response.headers.get("content-type", "").startswith("image"): + s = io.BytesIO(flow.response.content) + img = Image.open(s).rotate(180) + s2 = io.BytesIO() + img.save(s2, "png") + flow.response.content = s2.getvalue() + flow.response.headers["content-type"] = "image/png" diff --git a/examples/simple/wsgi_flask_app.py b/examples/simple/wsgi_flask_app.py new file mode 100644 index 00000000..f95c41e5 --- /dev/null +++ b/examples/simple/wsgi_flask_app.py @@ -0,0 +1,25 @@ +""" +This example shows how to graft a WSGI app onto mitmproxy. In this +instance, we're using the Flask framework (http://flask.pocoo.org/) to expose +a single simplest-possible page. +""" +from flask import Flask +from mitmproxy.addons import wsgiapp + +app = Flask("proxapp") + + +@app.route('/') +def hello_world(): + return 'Hello World!' + + +def start(): + # Host app at the magic domain "proxapp" on port 80. Requests to this + # domain and port combination will now be routed to the WSGI app instance. + return wsgiapp.WSGIApp(app, "proxapp", 80) + + # SSL works too, but the magic domain needs to be resolvable from the mitmproxy machine due to mitmproxy's design. + # mitmproxy will connect to said domain and use serve its certificate (unless --no-upstream-cert is set) + # but won't send any data. + # mitmproxy.ctx.master.apps.add(app, "example.com", 443) |