Merge remote-tracking branch 'origin/master'

This commit is contained in:
Maximilian Hils 2013-12-08 14:14:31 +01:00
commit e3c69fd105
16 changed files with 162 additions and 98 deletions

View File

@ -25,7 +25,7 @@ The new header will be added to all responses passing through the proxy.
## Events ## Events
### start(ScriptContext) ### start(ScriptContext, argv)
Called once on startup, before any other events. Called once on startup, before any other events.

View File

@ -67,3 +67,15 @@ rdr on en2 inet proto tcp to any port 443 -> 127.0.0.1 port 8080
</ol> </ol>
Note that the **rdr** rules in the pf.conf given above only apply to inbound
traffic. This means that they will NOT redirect traffic coming from the box
running pf itself. We can't distinguish between an outbound connection from a
non-mitmproxy app, and an outbound connection from mitmproxy itself - if you
want to intercept your OSX traffic, you should use an external host to run
mitmproxy. None the less, pf is flexible to cater for a range of creative
possibilities, like intercepting traffic emanating from VMs. See the
**pf.conf** man page for more.

View File

@ -1,8 +1,7 @@
""" """
This is a script stub, with definitions for all events. This is a script stub, with definitions for all events.
""" """
def start(ctx, argv):
def start(ctx):
""" """
Called once on script startup, before any other events. Called once on script startup, before any other events.
""" """

View File

@ -1,6 +1,8 @@
import proxy import proxy
import re, filt import re, filt
import argparse import argparse
import shlex
import os
APP_DOMAIN = "mitm" APP_DOMAIN = "mitm"
APP_IP = "1.1.1.1" APP_IP = "1.1.1.1"
@ -143,7 +145,7 @@ def get_common_options(options):
replacements = reps, replacements = reps,
setheaders = setheaders, setheaders = setheaders,
server_replay = options.server_replay, server_replay = options.server_replay,
script = options.script, scripts = options.scripts,
stickycookie = stickycookie, stickycookie = stickycookie,
stickyauth = stickyauth, stickyauth = stickyauth,
showhost = options.showhost, showhost = options.showhost,
@ -189,6 +191,11 @@ def common_options(parser):
action="store", dest="reverse_proxy", default=None, action="store", dest="reverse_proxy", default=None,
help="Reverse proxy to upstream server: http[s]://host[:port]" help="Reverse proxy to upstream server: http[s]://host[:port]"
) )
parser.add_argument(
"-F",
action="store", dest="forward_proxy", default=None,
help="Proxy to unconditionally forward to: http[s]://host[:port]"
)
parser.add_argument( parser.add_argument(
"-q", "-q",
action="store_true", dest="quiet", action="store_true", dest="quiet",
@ -201,8 +208,9 @@ def common_options(parser):
) )
parser.add_argument( parser.add_argument(
"-s", "-s",
action="store", dest="script", default=None, action="append", type=lambda x: shlex.split(x,posix=(os.name != "nt")), dest="scripts", default=[],
help="Run a script." metavar='"script.py --bar"',
help="Run a script. Surround with quotes to pass script arguments. Can be passed multiple times."
) )
parser.add_argument( parser.add_argument(
"-t", "-t",

View File

@ -459,7 +459,7 @@ class ConsoleMaster(flow.FlowMaster):
self._run_script_method("response", s, f) self._run_script_method("response", s, f)
if f.error: if f.error:
self._run_script_method("error", s, f) self._run_script_method("error", s, f)
s.run("done") s.unload()
self.refresh_flow(f) self.refresh_flow(f)
self.state.last_script = path self.state.last_script = path

View File

@ -190,7 +190,7 @@ def format_flow(f, focus, extended=False, hostheader=False, padding=2):
delta = f.response.timestamp_end - f.response.timestamp_start delta = f.response.timestamp_end - f.response.timestamp_start
size = len(f.response.content) + f.response.get_header_size() size = len(f.response.content) + f.response.get_header_size()
rate = utils.pretty_size(size / delta) rate = utils.pretty_size(size / ( delta if delta > 0 else 1 ) )
d.update(dict( d.update(dict(
resp_code = f.response.code, resp_code = f.response.code,

View File

@ -24,7 +24,7 @@ class Options(object):
"rheaders", "rheaders",
"setheaders", "setheaders",
"server_replay", "server_replay",
"script", "scripts",
"showhost", "showhost",
"stickycookie", "stickycookie",
"stickyauth", "stickyauth",
@ -109,8 +109,8 @@ class DumpMaster(flow.FlowMaster):
not options.keepserving not options.keepserving
) )
if options.script: for script_argv in options.scripts:
err = self.load_script(options.script) err = self.load_script(script_argv)
if err: if err:
raise DumpError(err) raise DumpError(err)
@ -221,8 +221,8 @@ class DumpMaster(flow.FlowMaster):
def run(self): # pragma: no cover def run(self): # pragma: no cover
if self.o.rfile and not self.o.keepserving: if self.o.rfile and not self.o.keepserving:
if self.script: for script in self.scripts:
self.load_script(None) self.unload_script(script)
return return
try: try:
return flow.FlowMaster.run(self) return flow.FlowMaster.run(self)

View File

@ -1349,7 +1349,7 @@ class FlowMaster(controller.Master):
self.server_playback = None self.server_playback = None
self.client_playback = None self.client_playback = None
self.kill_nonreplay = False self.kill_nonreplay = False
self.script = None self.scripts = []
self.pause_scripts = False self.pause_scripts = False
self.stickycookie_state = False self.stickycookie_state = False
@ -1385,36 +1385,42 @@ class FlowMaster(controller.Master):
""" """
pass pass
def get_script(self, path): def get_script(self, script_argv):
""" """
Returns an (error, script) tuple. Returns an (error, script) tuple.
""" """
s = script.Script(path, ScriptContext(self)) s = script.Script(script_argv, ScriptContext(self))
try: try:
s.load() s.load()
except script.ScriptError, v: except script.ScriptError, v:
return (v.args[0], None) return (v.args[0], None)
ret = s.run("start")
if not ret[0] and ret[1]:
return ("Error in script start:\n\n" + ret[1][1], None)
return (None, s) return (None, s)
def load_script(self, path): def unload_script(self,script):
script.unload()
self.scripts.remove(script)
def load_script(self, script_argv):
""" """
Loads a script. Returns an error description if something went Loads a script. Returns an error description if something went
wrong. If path is None, the current script is terminated. wrong.
""" """
if path is None: r = self.get_script(script_argv)
self.run_script_hook("done")
self.script = None
else:
r = self.get_script(path)
if r[0]: if r[0]:
return r[0] return r[0]
else: else:
if self.script: self.scripts.append(r[1])
self.run_script_hook("done")
self.script = r[1] def run_single_script_hook(self, script, name, *args, **kwargs):
if script and not self.pause_scripts:
ret = script.run(name, *args, **kwargs)
if not ret[0] and ret[1]:
e = "Script error:\n" + ret[1][1]
self.add_event(e, "error")
def run_script_hook(self, name, *args, **kwargs):
for script in self.scripts:
self.run_single_script_hook(script, name, *args, **kwargs)
def set_stickycookie(self, txt): def set_stickycookie(self, txt):
if txt: if txt:
@ -1565,13 +1571,6 @@ class FlowMaster(controller.Master):
if block: if block:
rt.join() rt.join()
def run_script_hook(self, name, *args, **kwargs):
if self.script and not self.pause_scripts:
ret = self.script.run(name, *args, **kwargs)
if not ret[0] and ret[1]:
e = "Script error:\n" + ret[1][1]
self.add_event(e, "error")
def handle_clientconnect(self, cc): def handle_clientconnect(self, cc):
self.run_script_hook("clientconnect", cc) self.run_script_hook("clientconnect", cc)
cc.reply() cc.reply()
@ -1580,6 +1579,13 @@ class FlowMaster(controller.Master):
self.run_script_hook("clientdisconnect", r) self.run_script_hook("clientdisconnect", r)
r.reply() r.reply()
def handle_serverconnection(self, sc):
# To unify the mitmproxy script API, we call the script hook "serverconnect" rather than "serverconnection".
# As things are handled differently in libmproxy (ClientConnect + ClientDisconnect vs ServerConnection class),
# there is no "serverdisonnect" event at the moment.
self.run_script_hook("serverconnect", sc)
sc.reply()
def handle_error(self, r): def handle_error(self, r):
f = self.state.add_error(r) f = self.state.add_error(r)
if f: if f:
@ -1613,8 +1619,8 @@ class FlowMaster(controller.Master):
return f return f
def shutdown(self): def shutdown(self):
if self.script: for script in self.scripts:
self.load_script(None) self.unload_script(script)
controller.Master.shutdown(self) controller.Master.shutdown(self)
if self.stream: if self.stream:
for i in self.state._flow_list: for i in self.state._flow_list:

View File

@ -23,13 +23,14 @@ class Log:
class ProxyConfig: class ProxyConfig:
def __init__(self, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None, authenticator=None): def __init__(self, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, forward_proxy=None, transparent_proxy=None, authenticator=None):
self.certfile = certfile self.certfile = certfile
self.cacert = cacert self.cacert = cacert
self.clientcerts = clientcerts self.clientcerts = clientcerts
self.no_upstream_cert = no_upstream_cert self.no_upstream_cert = no_upstream_cert
self.body_size_limit = body_size_limit self.body_size_limit = body_size_limit
self.reverse_proxy = reverse_proxy self.reverse_proxy = reverse_proxy
self.forward_proxy = forward_proxy
self.transparent_proxy = transparent_proxy self.transparent_proxy = transparent_proxy
self.authenticator = authenticator self.authenticator = authenticator
self.certstore = certutils.CertStore() self.certstore = certutils.CertStore()
@ -158,6 +159,7 @@ class ProxyHandler(tcp.BaseHandler):
if not self.server_conn: if not self.server_conn:
try: try:
self.server_conn = ServerConnection(self.config, scheme, host, port, sni) self.server_conn = ServerConnection(self.config, scheme, host, port, sni)
self.channel.ask(self.server_conn)
self.server_conn.connect() self.server_conn.connect()
except tcp.NetLibError, v: except tcp.NetLibError, v:
raise ProxyError(502, v) raise ProxyError(502, v)
@ -219,7 +221,12 @@ class ProxyHandler(tcp.BaseHandler):
# the case, we want to reconnect without sending an error # the case, we want to reconnect without sending an error
# to the client. # to the client.
while 1: while 1:
if self.config.forward_proxy:
forward_scheme, forward_host, forward_port = self.config.forward_proxy
sc = self.get_server_connection(cc, forward_scheme, forward_host, forward_port, self.sni)
else:
sc = self.get_server_connection(cc, scheme, host, port, self.sni) sc = self.get_server_connection(cc, scheme, host, port, self.sni)
sc.send(request) sc.send(request)
if sc.requestcount == 1: # add timestamps only for first request (others are not directly affected) if sc.requestcount == 1: # add timestamps only for first request (others are not directly affected)
request.tcp_setup_timestamp = sc.tcp_setup_timestamp request.tcp_setup_timestamp = sc.tcp_setup_timestamp
@ -258,13 +265,13 @@ class ProxyHandler(tcp.BaseHandler):
else: else:
response = response_reply response = response_reply
self.send_response(response) self.send_response(response)
if request and http.request_connection_close(request.httpversion, request.headers): if request and http.connection_close(request.httpversion, request.headers):
return return
# We could keep the client connection when the server # We could keep the client connection when the server
# connection needs to go away. However, we want to mimic # connection needs to go away. However, we want to mimic
# behaviour as closely as possible to the client, so we # behaviour as closely as possible to the client, so we
# disconnect. # disconnect.
if http.response_connection_close(response.httpversion, response.headers): if http.connection_close(response.httpversion, response.headers):
return return
except (IOError, ProxyError, http.HttpError, tcp.NetLibError), e: except (IOError, ProxyError, http.HttpError, tcp.NetLibError), e:
if hasattr(e, "code"): if hasattr(e, "code"):
@ -310,6 +317,17 @@ class ProxyHandler(tcp.BaseHandler):
raise ProxyError(502, "Unable to generate dummy cert.") raise ProxyError(502, "Unable to generate dummy cert.")
return ret return ret
def establish_ssl(self, client_conn, host, port):
dummycert = self.find_cert(client_conn, host, port, host)
sni = HandleSNI(
self, client_conn, host, port,
dummycert, self.config.certfile or self.config.cacert
)
try:
self.convert_to_ssl(dummycert, self.config.certfile or self.config.cacert, handle_sni=sni)
except tcp.NetLibError, v:
raise ProxyError(400, str(v))
def get_line(self, fp): def get_line(self, fp):
""" """
Get a line, possibly preceded by a blank. Get a line, possibly preceded by a blank.
@ -329,15 +347,7 @@ class ProxyHandler(tcp.BaseHandler):
if port in self.config.transparent_proxy["sslports"]: if port in self.config.transparent_proxy["sslports"]:
scheme = "https" scheme = "https"
if not self.ssl_established: if not self.ssl_established:
dummycert = self.find_cert(client_conn, host, port, host) self.establish_ssl(client_conn, host, port)
sni = HandleSNI(
self, client_conn, host, port,
dummycert, self.config.certfile or self.config.cacert
)
try:
self.convert_to_ssl(dummycert, self.config.certfile or self.config.cacert, handle_sni=sni)
except tcp.NetLibError, v:
raise ProxyError(400, str(v))
else: else:
scheme = "http" scheme = "http"
line = self.get_line(self.rfile) line = self.get_line(self.rfile)
@ -372,15 +382,7 @@ class ProxyHandler(tcp.BaseHandler):
'\r\n' '\r\n'
) )
self.wfile.flush() self.wfile.flush()
dummycert = self.find_cert(client_conn, host, port, host) self.establish_ssl(client_conn, host, port)
sni = HandleSNI(
self, client_conn, host, port,
dummycert, self.config.certfile or self.config.cacert
)
try:
self.convert_to_ssl(dummycert, self.config.certfile or self.config.cacert, handle_sni=sni)
except tcp.NetLibError, v:
raise ProxyError(400, str(v))
self.proxy_connect_state = (host, port, httpversion) self.proxy_connect_state = (host, port, httpversion)
line = self.rfile.readline(line) line = self.rfile.readline(line)
@ -414,10 +416,12 @@ class ProxyHandler(tcp.BaseHandler):
) )
def read_request_reverse(self, client_conn): def read_request_reverse(self, client_conn):
scheme, host, port = self.config.reverse_proxy
if scheme.lower() == "https" and not self.ssl_established:
self.establish_ssl(client_conn, host, port)
line = self.get_line(self.rfile) line = self.get_line(self.rfile)
if line == "": if line == "":
return None return None
scheme, host, port = self.config.reverse_proxy
r = http.parse_init_http(line) r = http.parse_init_http(line)
if not r: if not r:
raise ProxyError(400, "Bad HTTP request line: %s"%repr(line)) raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
@ -427,7 +431,7 @@ class ProxyHandler(tcp.BaseHandler):
self.rfile, self.wfile, headers, httpversion, self.config.body_size_limit self.rfile, self.wfile, headers, httpversion, self.config.body_size_limit
) )
return flow.Request( return flow.Request(
client_conn, httpversion, host, port, "http", method, path, headers, content, client_conn, httpversion, host, port, scheme, method, path, headers, content,
self.rfile.first_byte_timestamp, utils.timestamp() self.rfile.first_byte_timestamp, utils.timestamp()
) )
@ -594,6 +598,13 @@ def process_proxy_options(parser, options):
else: else:
rp = None rp = None
if options.forward_proxy:
fp = utils.parse_proxy_spec(options.forward_proxy)
if not fp:
return parser.error("Invalid forward proxy specification: %s"%options.forward_proxy)
else:
fp = None
if options.clientcerts: if options.clientcerts:
options.clientcerts = os.path.expanduser(options.clientcerts) options.clientcerts = os.path.expanduser(options.clientcerts)
if not os.path.exists(options.clientcerts) or not os.path.isdir(options.clientcerts): if not os.path.exists(options.clientcerts) or not os.path.isdir(options.clientcerts):
@ -623,6 +634,7 @@ def process_proxy_options(parser, options):
body_size_limit = body_size_limit, body_size_limit = body_size_limit,
no_upstream_cert = options.no_upstream_cert, no_upstream_cert = options.no_upstream_cert,
reverse_proxy = rp, reverse_proxy = rp,
forward_proxy = fp,
transparent_proxy = trans, transparent_proxy = trans,
authenticator = authenticator authenticator = authenticator
) )

View File

@ -8,12 +8,12 @@ class Script:
""" """
The instantiator should do something along this vein: The instantiator should do something along this vein:
s = Script(path, master) s = Script(argv, master)
s.load() s.load()
s.run("start")
""" """
def __init__(self, path, ctx): def __init__(self, argv, ctx):
self.path, self.ctx = path, ctx self.argv = argv
self.ctx = ctx
self.ns = None self.ns = None
def load(self): def load(self):
@ -23,17 +23,21 @@ class Script:
Raises ScriptError on failure, with argument equal to an error Raises ScriptError on failure, with argument equal to an error
message that may be a formatted traceback. message that may be a formatted traceback.
""" """
path = os.path.expanduser(self.path) path = os.path.expanduser(self.argv[0])
if not os.path.exists(path): if not os.path.exists(path):
raise ScriptError("No such file: %s"%self.path) raise ScriptError("No such file: %s" % path)
if not os.path.isfile(path): if not os.path.isfile(path):
raise ScriptError("Not a file: %s"%self.path) raise ScriptError("Not a file: %s" % path)
ns = {} ns = {}
try: try:
execfile(path, ns, ns) execfile(path, ns, ns)
self.ns = ns
self.run("start", self.argv)
except Exception, v: except Exception, v:
raise ScriptError(traceback.format_exc(v)) raise ScriptError(traceback.format_exc(v))
self.ns = ns
def unload(self):
return self.run("done")
def run(self, name, *args, **kwargs): def run(self, name, *args, **kwargs):
""" """

View File

@ -1,5 +1,13 @@
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--var', type=int)
var = 0 var = 0
def start(ctx, argv):
global var
var = parser.parse_args(argv[1:]).var
def here(ctx): def here(ctx):
global var global var
var += 1 var += 1

View File

@ -1,3 +1,3 @@
def start(ctx): def start(ctx, argv):
raise ValueError raise ValueError

View File

@ -1,6 +1,7 @@
import argparse import argparse
from libmproxy import cmdline from libmproxy import cmdline
import tutils import tutils
import os.path
def test_parse_replace_hook(): def test_parse_replace_hook():
@ -39,6 +40,18 @@ def test_parse_setheaders():
x = cmdline.parse_setheader("/foo/bar/voing") x = cmdline.parse_setheader("/foo/bar/voing")
assert x == ("foo", "bar", "voing") assert x == ("foo", "bar", "voing")
def test_shlex():
"""
shlex.split assumes posix=True by default, we do manual detection for windows.
Test whether script paths are parsed correctly
"""
absfilepath = os.path.normcase(os.path.abspath(__file__))
parser = argparse.ArgumentParser()
cmdline.common_options(parser)
opts = parser.parse_args(args=["-s",absfilepath])
assert os.path.isfile(opts.scripts[0][0])
def test_common(): def test_common():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()

View File

@ -544,9 +544,11 @@ class TestFlowMaster:
fm = flow.FlowMaster(None, s) fm = flow.FlowMaster(None, s)
assert not fm.load_script(tutils.test_data.path("scripts/a.py")) assert not fm.load_script(tutils.test_data.path("scripts/a.py"))
assert not fm.load_script(tutils.test_data.path("scripts/a.py")) assert not fm.load_script(tutils.test_data.path("scripts/a.py"))
assert not fm.load_script(None) assert not fm.unload_script(fm.scripts[0])
assert not fm.unload_script(fm.scripts[0])
assert fm.load_script("nonexistent") assert fm.load_script("nonexistent")
assert "ValueError" in fm.load_script(tutils.test_data.path("scripts/starterr.py")) assert "ValueError" in fm.load_script(tutils.test_data.path("scripts/starterr.py"))
assert len(fm.scripts) == 0
def test_replay(self): def test_replay(self):
s = flow.State() s = flow.State()
@ -572,20 +574,27 @@ class TestFlowMaster:
assert not fm.load_script(tutils.test_data.path("scripts/all.py")) assert not fm.load_script(tutils.test_data.path("scripts/all.py"))
req = tutils.treq() req = tutils.treq()
fm.handle_clientconnect(req.client_conn) fm.handle_clientconnect(req.client_conn)
assert fm.script.ns["log"][-1] == "clientconnect" assert fm.scripts[0].ns["log"][-1] == "clientconnect"
f = fm.handle_request(req) f = fm.handle_request(req)
assert fm.script.ns["log"][-1] == "request" assert fm.scripts[0].ns["log"][-1] == "request"
resp = tutils.tresp(req) resp = tutils.tresp(req)
fm.handle_response(resp) fm.handle_response(resp)
assert fm.script.ns["log"][-1] == "response" assert fm.scripts[0].ns["log"][-1] == "response"
#load second script
assert not fm.load_script(tutils.test_data.path("scripts/all.py"))
assert len(fm.scripts) == 2
dc = flow.ClientDisconnect(req.client_conn) dc = flow.ClientDisconnect(req.client_conn)
dc.reply = controller.DummyReply() dc.reply = controller.DummyReply()
fm.handle_clientdisconnect(dc) fm.handle_clientdisconnect(dc)
assert fm.script.ns["log"][-1] == "clientdisconnect" assert fm.scripts[0].ns["log"][-1] == "clientdisconnect"
assert fm.scripts[1].ns["log"][-1] == "clientdisconnect"
#unload first script
fm.unload_script(fm.scripts[0])
assert len(fm.scripts) == 1
err = flow.Error(f.request, "msg") err = flow.Error(f.request, "msg")
err.reply = controller.DummyReply() err.reply = controller.DummyReply()
fm.handle_error(err) fm.handle_error(err)
assert fm.script.ns["log"][-1] == "error" assert fm.scripts[0].ns["log"][-1] == "error"
def test_duplicate_flow(self): def test_duplicate_flow(self):
s = flow.State() s = flow.State()

View File

@ -1,5 +1,7 @@
from libmproxy import script, flow from libmproxy import script, flow
import tutils import tutils
import shlex
import os
class TestScript: class TestScript:
def test_simple(self): def test_simple(self):
@ -7,11 +9,12 @@ class TestScript:
fm = flow.FlowMaster(None, s) fm = flow.FlowMaster(None, s)
ctx = flow.ScriptContext(fm) ctx = flow.ScriptContext(fm)
p = script.Script(tutils.test_data.path("scripts/a.py"), ctx) p = script.Script(shlex.split(tutils.test_data.path("scripts/a.py")+" --var 40", posix=(os.name != "nt")), ctx)
p.load() p.load()
assert "here" in p.ns assert "here" in p.ns
assert p.run("here") == (True, 1) assert p.run("here") == (True, 41)
assert p.run("here") == (True, 2) assert p.run("here") == (True, 42)
ret = p.run("errargs") ret = p.run("errargs")
assert not ret[0] assert not ret[0]
@ -19,12 +22,12 @@ class TestScript:
# Check reload # Check reload
p.load() p.load()
assert p.run("here") == (True, 1) assert p.run("here") == (True, 41)
def test_duplicate_flow(self): def test_duplicate_flow(self):
s = flow.State() s = flow.State()
fm = flow.FlowMaster(None, s) fm = flow.FlowMaster(None, s)
fm.load_script(tutils.test_data.path("scripts/duplicate_flow.py")) fm.load_script([tutils.test_data.path("scripts/duplicate_flow.py")])
r = tutils.treq() r = tutils.treq()
fm.handle_request(r) fm.handle_request(r)
assert fm.state.flow_count() == 2 assert fm.state.flow_count() == 2
@ -37,25 +40,25 @@ class TestScript:
ctx = flow.ScriptContext(fm) ctx = flow.ScriptContext(fm)
s = script.Script("nonexistent", ctx) s = script.Script(["nonexistent"], ctx)
tutils.raises( tutils.raises(
"no such file", "no such file",
s.load s.load
) )
s = script.Script(tutils.test_data.path("scripts"), ctx) s = script.Script([tutils.test_data.path("scripts")], ctx)
tutils.raises( tutils.raises(
"not a file", "not a file",
s.load s.load
) )
s = script.Script(tutils.test_data.path("scripts/syntaxerr.py"), ctx) s = script.Script([tutils.test_data.path("scripts/syntaxerr.py")], ctx)
tutils.raises( tutils.raises(
script.ScriptError, script.ScriptError,
s.load s.load
) )
s = script.Script(tutils.test_data.path("scripts/loaderr.py"), ctx) s = script.Script([tutils.test_data.path("scripts/loaderr.py")], ctx)
tutils.raises( tutils.raises(
script.ScriptError, script.ScriptError,
s.load s.load

View File

@ -191,16 +191,6 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin):
assert p.request("get:/:i0,'invalid\r\n\r\n'").status_code == 400 assert p.request("get:/:i0,'invalid\r\n\r\n'").status_code == 400
class TestHTTPSNoUpstream(tservers.HTTPProxTest, CommonMixin):
ssl = True
no_upstream_cert = True
def test_cert_gen_error(self):
f = self.pathoc_raw()
f.connect((u"foo..bar".encode("utf8"), 0))
f.request("get:/")
assert "dummy cert" in "".join(self.proxy.log)
class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin): class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin):
ssl = True ssl = True
certfile = True certfile = True