mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 10:16:27 +00:00
update examples, fix #353
This commit is contained in:
parent
d06b4bfa4e
commit
ebd539b49f
@ -1,10 +1,23 @@
|
||||
add_header.py Simple script that just adds a header to every request.
|
||||
dup_and_replay.py Duplicates each request, changes it, and then replays the modified request.
|
||||
flowbasic Basic use of mitmproxy as a library.
|
||||
modify_form.py Modify all form submissions to add a parameter.
|
||||
modify_querystring.py Modify all query strings to add a parameters.
|
||||
proxapp How to embed a WSGI app in a mitmproxy server
|
||||
stub.py Script stub with a method definition for every event.
|
||||
stickycookies An example of writing a custom proxy with libmproxy.
|
||||
upsidedownternet.py Rewrites traffic to turn PNGs upside down.
|
||||
mitmproxywrapper.py Bracket mitmproxy run with proxy enable/disable on OS X
|
||||
# inline script examples
|
||||
add_header.py Simple script that just adds a header to every request.
|
||||
change_upstream_proxy.py Dynamically change the upstream proxy
|
||||
dup_and_replay.py Duplicates each request, changes it, and then replays the modified request.
|
||||
iframe_injector.py Inject configurable iframe into pages.
|
||||
modify_form.py Modify all form submissions to add a parameter.
|
||||
modify_querystring.py Modify all query strings to add a parameters.
|
||||
modify_response_body.py Replace arbitrary strings in all responses
|
||||
nonblocking.py Demonstrate parallel processing with a blocking script.
|
||||
proxapp.py How to embed a WSGI app in a mitmproxy server
|
||||
redirect_requests.py Redirect requests or directly reply to them.
|
||||
stub.py Script stub with a method definition for every event.
|
||||
upsidedownternet.py Rewrites traffic to turn images upside down.
|
||||
|
||||
|
||||
# libmproxy examples
|
||||
flowbasic Basic use of mitmproxy as a library.
|
||||
stickycookies An example of writing a custom proxy with libmproxy.
|
||||
|
||||
|
||||
# misc
|
||||
read_dumpfile Read a dumpfile generated by mitmproxy.
|
||||
mitmproxywrapper.py Bracket mitmproxy run with proxy enable/disable on OS X
|
||||
|
@ -1,2 +1,2 @@
|
||||
def response(ctx, flow):
|
||||
def response(context, flow):
|
||||
flow.response.headers["newheader"] = ["foo"]
|
@ -4,17 +4,18 @@
|
||||
# Usage: mitmdump -s "change_upstream_proxy.py host"
|
||||
from libmproxy.protocol.http import send_connect_request
|
||||
|
||||
alternative_upstream_proxy = ("localhost", 8082)
|
||||
def should_redirect(flow):
|
||||
return (flow.request.host == "example.com")
|
||||
alternative_upstream_proxy = ("localhost",8082)
|
||||
return flow.request.host == "example.com"
|
||||
|
||||
def request(ctx, flow):
|
||||
if flow.live and should_redirect(flow):
|
||||
|
||||
# If you want to change the target server, you should modify flow.request.host and flow.request.port
|
||||
# flow.live.change_server should only be used by inline scripts to change the upstream proxy,
|
||||
# unless you are sure that you know what you are doing.
|
||||
server_changed = flow.live.change_server(alternative_upstream_proxy, persistent_change=True)
|
||||
if flow.request.scheme == "https" and server_changed:
|
||||
send_connect_request(flow.live.c.server_conn, flow.request.host, flow.request.port)
|
||||
flow.live.c.establish_ssl(server=True)
|
||||
def request(context, flow):
|
||||
if flow.live and should_redirect(flow):
|
||||
|
||||
# If you want to change the target server, you should modify flow.request.host and flow.request.port
|
||||
# flow.live.change_server should only be used by inline scripts to change the upstream proxy,
|
||||
# unless you are sure that you know what you are doing.
|
||||
server_changed = flow.live.change_server(alternative_upstream_proxy, persistent_change=True)
|
||||
if flow.request.scheme == "https" and server_changed:
|
||||
send_connect_request(flow.live.c.server_conn, flow.request.host, flow.request.port)
|
||||
flow.live.c.establish_ssl(server=True)
|
||||
|
@ -1,4 +1,4 @@
|
||||
def request(ctx, flow):
|
||||
f = ctx.duplicate_flow(flow)
|
||||
def request(context, flow):
|
||||
f = context.duplicate_flow(flow)
|
||||
f.request.path = "/changed"
|
||||
ctx.replay_request(f)
|
||||
context.replay_request(f)
|
@ -12,6 +12,7 @@ import os
|
||||
from libmproxy import flow, proxy
|
||||
from libmproxy.proxy.server import ProxyServer
|
||||
|
||||
|
||||
class MyMaster(flow.FlowMaster):
|
||||
def run(self):
|
||||
try:
|
||||
@ -34,7 +35,7 @@ class MyMaster(flow.FlowMaster):
|
||||
|
||||
|
||||
config = proxy.ProxyConfig(
|
||||
ca_file = os.path.expanduser("~/.mitmproxy/mitmproxy-ca.pem")
|
||||
ca_file=os.path.expanduser("~/.mitmproxy/mitmproxy-ca.pem")
|
||||
)
|
||||
state = flow.State()
|
||||
server = ProxyServer(config, 8080)
|
||||
|
@ -3,16 +3,16 @@
|
||||
from libmproxy.protocol.http import decoded
|
||||
|
||||
|
||||
def start(ctx, argv):
|
||||
def start(context, argv):
|
||||
if len(argv) != 2:
|
||||
raise ValueError('Usage: -s "iframe_injector.py url"')
|
||||
ctx.iframe_url = argv[1]
|
||||
context.iframe_url = argv[1]
|
||||
|
||||
|
||||
def handle_response(ctx, flow):
|
||||
def handle_response(context, flow):
|
||||
with decoded(flow.response): # Remove content encoding (gzip, ...)
|
||||
c = flow.response.replace(
|
||||
'<body>',
|
||||
'<body><iframe src="%s" frameborder="0" height="0" width="0"></iframe>' % ctx.iframe_url)
|
||||
'<body><iframe src="%s" frameborder="0" height="0" width="0"></iframe>' % context.iframe_url)
|
||||
if c > 0:
|
||||
ctx.log("Iframe injected!")
|
||||
context.log("Iframe injected!")
|
@ -1,5 +1,5 @@
|
||||
|
||||
def request(ctx, flow):
|
||||
def request(context, flow):
|
||||
if "application/x-www-form-urlencoded" in flow.request.headers["content-type"]:
|
||||
form = flow.request.get_form_urlencoded()
|
||||
form["mitmproxy"] = ["rocks"]
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
def request(ctx, flow):
|
||||
def request(context, flow):
|
||||
q = flow.request.get_query()
|
||||
if q:
|
||||
q["mitmproxy"] = ["rocks"]
|
||||
|
@ -3,13 +3,13 @@
|
||||
from libmproxy.protocol.http import decoded
|
||||
|
||||
|
||||
def start(ctx, argv):
|
||||
def start(context, argv):
|
||||
if len(argv) != 3:
|
||||
raise ValueError('Usage: -s "modify-response-body.py old new"')
|
||||
# You may want to use Python's argparse for more sophisticated argument parsing.
|
||||
ctx.old, ctx.new = argv[1], argv[2]
|
||||
context.old, context.new = argv[1], argv[2]
|
||||
|
||||
|
||||
def response(ctx, flow):
|
||||
def response(context, flow):
|
||||
with decoded(flow.response): # automatically decode gzipped responses.
|
||||
flow.response.content = flow.response.content.replace(ctx.old, ctx.new)
|
||||
flow.response.content = flow.response.content.replace(context.old, context.new)
|
@ -2,7 +2,7 @@ import time
|
||||
from libmproxy.script import concurrent
|
||||
|
||||
|
||||
@concurrent
|
||||
@concurrent # Remove this and see what happens
|
||||
def request(context, flow):
|
||||
print "handle request: %s%s" % (flow.request.host, flow.request.path)
|
||||
time.sleep(5)
|
||||
|
@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
This example shows how to graft a WSGI app onto mitmproxy. In this
|
||||
instance, we're using the Bottle framework (http://bottlepy.org/) to expose
|
||||
a single simplest-possible page.
|
||||
"""
|
||||
import bottle
|
||||
import os
|
||||
from libmproxy import proxy, flow
|
||||
|
||||
@bottle.route('/')
|
||||
def index():
|
||||
return 'Hi!'
|
||||
|
||||
|
||||
class MyMaster(flow.FlowMaster):
|
||||
def run(self):
|
||||
try:
|
||||
flow.FlowMaster.run(self)
|
||||
except KeyboardInterrupt:
|
||||
self.shutdown()
|
||||
|
||||
def handle_request(self, f):
|
||||
f = flow.FlowMaster.handle_request(self, f)
|
||||
if f:
|
||||
f.reply()
|
||||
return f
|
||||
|
||||
def handle_response(self, f):
|
||||
f = flow.FlowMaster.handle_response(self, f)
|
||||
if f:
|
||||
f.reply()
|
||||
print f
|
||||
return f
|
||||
|
||||
|
||||
config = proxy.ProxyConfig(
|
||||
cacert = os.path.expanduser("~/.mitmproxy/mitmproxy-ca.pem")
|
||||
)
|
||||
state = flow.State()
|
||||
server = proxy.ProxyServer(config, 8080)
|
||||
# Register the app using the magic domain "proxapp" on port 80. Requests to
|
||||
# this domain and port combination will now be routed to the WSGI app instance.
|
||||
server.apps.add(bottle.app(), "proxapp", 80)
|
||||
m = MyMaster(server, state)
|
||||
m.run()
|
||||
|
24
examples/proxapp.py
Normal file
24
examples/proxapp.py
Normal file
@ -0,0 +1,24 @@
|
||||
"""
|
||||
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
|
||||
|
||||
app = Flask("proxapp")
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def hello_world():
|
||||
return 'Hello World!'
|
||||
|
||||
|
||||
# Register the app using the magic domain "proxapp" on port 80. Requests to
|
||||
# this domain and port combination will now be routed to the WSGI app instance.
|
||||
def start(context, argv):
|
||||
context.app_registry.add(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.
|
||||
context.app_registry.add(app, "example.com", 443)
|
@ -6,12 +6,13 @@
|
||||
from libmproxy import flow
|
||||
import json, sys
|
||||
|
||||
with open("logfile", "rb") as f:
|
||||
freader = flow.FlowReader(f)
|
||||
with open("logfile", "rb") as logfile:
|
||||
freader = flow.FlowReader(logfile)
|
||||
try:
|
||||
for i in freader.stream():
|
||||
print i.request.host
|
||||
json.dump(i._get_state(), sys.stdout, indent=4)
|
||||
for f in freader.stream():
|
||||
print(f)
|
||||
print(f.request.host)
|
||||
json.dump(f._get_state(), sys.stdout, indent=4)
|
||||
print ""
|
||||
except flow.FlowReadError, v:
|
||||
print "Flow file corrupted. Stopped loading."
|
@ -6,15 +6,19 @@ This example shows two ways to redirect flows to other destinations.
|
||||
"""
|
||||
|
||||
|
||||
def request(ctx, flow):
|
||||
def request(context, flow):
|
||||
# pretty_host(hostheader=True) takes the Host: header of the request into account,
|
||||
# which is useful in transparent mode where we usually only have the IP otherwise.
|
||||
|
||||
# Method 1: Answer with a locally generated response
|
||||
if flow.request.pretty_host(hostheader=True).endswith("example.com"):
|
||||
resp = HTTPResponse(
|
||||
[1, 1], 200, "OK",
|
||||
ODictCaseless([["Content-Type", "text/html"]]),
|
||||
"helloworld")
|
||||
flow.reply(resp)
|
||||
|
||||
# Method 2: Redirect the request to a different server
|
||||
if flow.request.pretty_host(hostheader=True).endswith("example.org"):
|
||||
flow.request.host = "mitmproxy.org"
|
||||
flow.request.update_host_header()
|
||||
|
@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
This example builds on mitmproxy's base proxying infrastructure to
|
||||
implement functionality similar to the "sticky cookies" option. This is at
|
||||
a lower level than the Flow mechanism, so we're dealing directly with
|
||||
request and response objects.
|
||||
implement functionality similar to the "sticky cookies" option.
|
||||
|
||||
Heads Up: In the majority of cases, you want to use inline scripts.
|
||||
"""
|
||||
import os
|
||||
from libmproxy import controller, proxy
|
||||
@ -21,19 +21,19 @@ class StickyMaster(controller.Master):
|
||||
except KeyboardInterrupt:
|
||||
self.shutdown()
|
||||
|
||||
def handle_request(self, msg):
|
||||
hid = (msg.host, msg.port)
|
||||
if msg.headers["cookie"]:
|
||||
self.stickyhosts[hid] = msg.headers["cookie"]
|
||||
def handle_request(self, flow):
|
||||
hid = (flow.request.host, flow.request.port)
|
||||
if flow.request.headers["cookie"]:
|
||||
self.stickyhosts[hid] = flow.request.headers["cookie"]
|
||||
elif hid in self.stickyhosts:
|
||||
msg.headers["cookie"] = self.stickyhosts[hid]
|
||||
msg.reply()
|
||||
flow.request.headers["cookie"] = self.stickyhosts[hid]
|
||||
flow.reply()
|
||||
|
||||
def handle_response(self, msg):
|
||||
hid = (msg.request.host, msg.request.port)
|
||||
if msg.headers["set-cookie"]:
|
||||
self.stickyhosts[hid] = msg.headers["set-cookie"]
|
||||
msg.reply()
|
||||
def handle_response(self, flow):
|
||||
hid = (flow.request.host, flow.request.port)
|
||||
if flow.response.headers["set-cookie"]:
|
||||
self.stickyhosts[hid] = flow.response.headers["set-cookie"]
|
||||
flow.reply()
|
||||
|
||||
|
||||
config = proxy.ProxyConfig(
|
||||
|
@ -1,4 +1,4 @@
|
||||
def responseheaders(ctx, flow):
|
||||
def responseheaders(context, flow):
|
||||
"""
|
||||
Enables streaming for all responses.
|
||||
"""
|
||||
|
@ -1,63 +1,63 @@
|
||||
"""
|
||||
This is a script stub, with definitions for all events.
|
||||
"""
|
||||
def start(ctx, argv):
|
||||
def start(context, argv):
|
||||
"""
|
||||
Called once on script startup, before any other events.
|
||||
"""
|
||||
ctx.log("start")
|
||||
context.log("start")
|
||||
|
||||
def clientconnect(ctx, conn_handler):
|
||||
def clientconnect(context, conn_handler):
|
||||
"""
|
||||
Called when a client initiates a connection to the proxy. Note that a
|
||||
connection can correspond to multiple HTTP requests
|
||||
"""
|
||||
ctx.log("clientconnect")
|
||||
context.log("clientconnect")
|
||||
|
||||
def serverconnect(ctx, conn_handler):
|
||||
def serverconnect(context, conn_handler):
|
||||
"""
|
||||
Called when the proxy initiates a connection to the target server. Note that a
|
||||
connection can correspond to multiple HTTP requests
|
||||
"""
|
||||
ctx.log("serverconnect")
|
||||
context.log("serverconnect")
|
||||
|
||||
def request(ctx, flow):
|
||||
def request(context, flow):
|
||||
"""
|
||||
Called when a client request has been received.
|
||||
"""
|
||||
ctx.log("request")
|
||||
context.log("request")
|
||||
|
||||
|
||||
def responseheaders(ctx, flow):
|
||||
def responseheaders(context, flow):
|
||||
"""
|
||||
Called when the response headers for a server response have been received,
|
||||
but the response body has not been processed yet. Can be used to tell mitmproxy
|
||||
to stream the response.
|
||||
"""
|
||||
ctx.log("responseheaders")
|
||||
context.log("responseheaders")
|
||||
|
||||
def response(ctx, flow):
|
||||
def response(context, flow):
|
||||
"""
|
||||
Called when a server response has been received.
|
||||
"""
|
||||
ctx.log("response")
|
||||
context.log("response")
|
||||
|
||||
def error(ctx, flow):
|
||||
def error(context, flow):
|
||||
"""
|
||||
Called when a flow error has occured, e.g. invalid server responses, or
|
||||
interrupted connections. This is distinct from a valid server HTTP error
|
||||
response, which is simply a response with an HTTP error code.
|
||||
"""
|
||||
ctx.log("error")
|
||||
context.log("error")
|
||||
|
||||
def clientdisconnect(ctx, conn_handler):
|
||||
def clientdisconnect(context, conn_handler):
|
||||
"""
|
||||
Called when a client disconnects from the proxy.
|
||||
"""
|
||||
ctx.log("clientdisconnect")
|
||||
context.log("clientdisconnect")
|
||||
|
||||
def done(ctx):
|
||||
def done(context):
|
||||
"""
|
||||
Called once on script shutdown, after any other events.
|
||||
"""
|
||||
ctx.log("done")
|
||||
context.log("done")
|
||||
|
@ -1,10 +1,16 @@
|
||||
import cStringIO
|
||||
from PIL import Image
|
||||
from libmproxy.protocol.http import decoded
|
||||
|
||||
def response(ctx, flow):
|
||||
if flow.response.headers["content-type"] == ["image/png"]:
|
||||
s = cStringIO.StringIO(flow.response.content)
|
||||
img = Image.open(s).rotate(180)
|
||||
s2 = cStringIO.StringIO()
|
||||
img.save(s2, "png")
|
||||
flow.response.content = s2.getvalue()
|
||||
def response(context, flow):
|
||||
if flow.response.headers.get_first("content-type", "").startswith("image"):
|
||||
with decoded(flow.response): # automatically decode gzipped responses.
|
||||
try:
|
||||
s = cStringIO.StringIO(flow.response.content)
|
||||
img = Image.open(s).rotate(180)
|
||||
s2 = cStringIO.StringIO()
|
||||
img.save(s2, "png")
|
||||
flow.response.content = s2.getvalue()
|
||||
flow.response.headers["content-type"] = ["image/png"]
|
||||
except: # Unknown image types etc.
|
||||
pass
|
@ -1095,7 +1095,8 @@ class HTTPHandler(ProtocolHandler):
|
||||
if request.form_in == "absolute":
|
||||
if request.scheme != "http":
|
||||
raise http.HttpError(400, "Invalid request scheme: %s" % request.scheme)
|
||||
if request.form_out == "relative":
|
||||
if self.c.config.mode == "regular":
|
||||
# Update info so that an inline script sees the correct value at flow.server_conn
|
||||
self.c.set_server_address((request.host, request.port))
|
||||
flow.server_conn = self.c.server_conn
|
||||
|
||||
|
@ -38,6 +38,10 @@ class ScriptContext:
|
||||
"""
|
||||
self._master.replay_request(f)
|
||||
|
||||
@property
|
||||
def app_registry(self):
|
||||
return self._master.apps
|
||||
|
||||
|
||||
class Script:
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user