mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-27 02:24:18 +00:00
Make parse_pathoc a generator
This lets us do things like this: get:/:ir,@1:x1000000000 It will also let us expand the language to include a "repeat forever" concept.
This commit is contained in:
parent
7412ec83f5
commit
0da3e51e1c
@ -135,7 +135,7 @@ def make_app(noapi, debug):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if is_request:
|
if is_request:
|
||||||
r = language.parse_pathoc(spec)[0]
|
r = language.parse_pathoc(spec).next()
|
||||||
else:
|
else:
|
||||||
r = language.parse_pathod(spec)
|
r = language.parse_pathod(spec)
|
||||||
except language.ParseException as v:
|
except language.ParseException as v:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
import itertools
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
@ -189,7 +190,7 @@ def args_pathoc(argv, stdout=sys.stdout, stderr=sys.stderr):
|
|||||||
data = open(r).read()
|
data = open(r).read()
|
||||||
r = data
|
r = data
|
||||||
try:
|
try:
|
||||||
reqs.extend(language.parse_pathoc(r))
|
reqs.append(language.parse_pathoc(r))
|
||||||
except language.ParseException as v:
|
except language.ParseException as v:
|
||||||
print >> stderr, "Error parsing request spec: %s" % v.msg
|
print >> stderr, "Error parsing request spec: %s" % v.msg
|
||||||
print >> stderr, v.marked()
|
print >> stderr, v.marked()
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import itertools
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import pyparsing as pp
|
import pyparsing as pp
|
||||||
@ -28,6 +29,14 @@ def parse_pathod(s):
|
|||||||
raise exceptions.ParseException(v.msg, v.line, v.col)
|
raise exceptions.ParseException(v.msg, v.line, v.col)
|
||||||
|
|
||||||
|
|
||||||
|
def expand(req):
|
||||||
|
if req.times:
|
||||||
|
for j in xrange(int(req.times.value)):
|
||||||
|
yield req.strike_token("times")
|
||||||
|
else:
|
||||||
|
yield req
|
||||||
|
|
||||||
|
|
||||||
def parse_pathoc(s):
|
def parse_pathoc(s):
|
||||||
"""
|
"""
|
||||||
May raise ParseException
|
May raise ParseException
|
||||||
@ -47,14 +56,7 @@ def parse_pathoc(s):
|
|||||||
).parseString(s, parseAll=True)
|
).parseString(s, parseAll=True)
|
||||||
except pp.ParseException as v:
|
except pp.ParseException as v:
|
||||||
raise exceptions.ParseException(v.msg, v.line, v.col)
|
raise exceptions.ParseException(v.msg, v.line, v.col)
|
||||||
expanded = []
|
return itertools.chain(*[expand(i) for i in reqs])
|
||||||
for i in reqs:
|
|
||||||
if i.times:
|
|
||||||
for j in range(int(i.times.value)):
|
|
||||||
expanded.append(i.strike_token("times"))
|
|
||||||
else:
|
|
||||||
expanded.append(i)
|
|
||||||
return expanded
|
|
||||||
|
|
||||||
|
|
||||||
def parse_websocket_frame(s):
|
def parse_websocket_frame(s):
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import itertools
|
||||||
import hashlib
|
import hashlib
|
||||||
import Queue
|
import Queue
|
||||||
import random
|
import random
|
||||||
@ -287,7 +288,7 @@ class Pathoc(tcp.TCPClient):
|
|||||||
"""
|
"""
|
||||||
with self.log() as log:
|
with self.log() as log:
|
||||||
if isinstance(r, basestring):
|
if isinstance(r, basestring):
|
||||||
r = language.parse_pathoc(r)[0]
|
r = language.parse_pathoc(r).next()
|
||||||
log(">> %s" % r)
|
log(">> %s" % r)
|
||||||
try:
|
try:
|
||||||
language.serve(r, self.wfile, self.settings)
|
language.serve(r, self.wfile, self.settings)
|
||||||
@ -330,7 +331,7 @@ class Pathoc(tcp.TCPClient):
|
|||||||
"""
|
"""
|
||||||
with self.log() as log:
|
with self.log() as log:
|
||||||
if isinstance(r, basestring):
|
if isinstance(r, basestring):
|
||||||
r = language.parse_pathoc(r)[0]
|
r = language.parse_pathoc(r).next()
|
||||||
log(">> %s" % r)
|
log(">> %s" % r)
|
||||||
resp, req = None, None
|
resp, req = None, None
|
||||||
try:
|
try:
|
||||||
@ -369,7 +370,7 @@ class Pathoc(tcp.TCPClient):
|
|||||||
May raise http.HTTPError, tcp.NetLibError
|
May raise http.HTTPError, tcp.NetLibError
|
||||||
"""
|
"""
|
||||||
if isinstance(r, basestring):
|
if isinstance(r, basestring):
|
||||||
r = language.parse_pathoc(r)[0]
|
r = language.parse_pathoc(r).next()
|
||||||
if isinstance(r, language.http.Request):
|
if isinstance(r, language.http.Request):
|
||||||
if r.ws:
|
if r.ws:
|
||||||
return self.websocket_start(r, self.websocket_get_frame)
|
return self.websocket_start(r, self.websocket_get_frame)
|
||||||
@ -388,17 +389,13 @@ def main(args): # pragma: nocover
|
|||||||
while True:
|
while True:
|
||||||
if cnt == args.repeat and args.repeat != 0:
|
if cnt == args.repeat and args.repeat != 0:
|
||||||
break
|
break
|
||||||
if trycount > args.memolimit:
|
|
||||||
print >> sys.stderr, "Memo limit exceeded..."
|
|
||||||
return
|
|
||||||
if args.wait and cnt != 0:
|
if args.wait and cnt != 0:
|
||||||
time.sleep(args.wait)
|
time.sleep(args.wait)
|
||||||
|
|
||||||
cnt += 1
|
cnt += 1
|
||||||
|
playlist = itertools.chain(*args.requests)
|
||||||
if args.random:
|
if args.random:
|
||||||
playlist = [random.choice(args.requests)]
|
playlist = random.choice(args.requests)
|
||||||
else:
|
|
||||||
playlist = args.requests
|
|
||||||
p = Pathoc(
|
p = Pathoc(
|
||||||
(args.host, args.port),
|
(args.host, args.port),
|
||||||
ssl = args.ssl,
|
ssl = args.ssl,
|
||||||
@ -414,22 +411,6 @@ def main(args): # pragma: nocover
|
|||||||
ignoretimeout = args.ignoretimeout,
|
ignoretimeout = args.ignoretimeout,
|
||||||
showsummary = True
|
showsummary = True
|
||||||
)
|
)
|
||||||
if args.explain or args.memo:
|
|
||||||
playlist = [
|
|
||||||
i.freeze(p.settings) for i in playlist
|
|
||||||
]
|
|
||||||
if args.memo:
|
|
||||||
newlist = []
|
|
||||||
for spec in playlist:
|
|
||||||
h = hashlib.sha256(spec.spec()).digest()
|
|
||||||
if h not in memo:
|
|
||||||
memo.add(h)
|
|
||||||
newlist.append(spec)
|
|
||||||
playlist = newlist
|
|
||||||
if not playlist:
|
|
||||||
trycount += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
trycount = 0
|
trycount = 0
|
||||||
try:
|
try:
|
||||||
p.connect(args.connect_to, args.showssl)
|
p.connect(args.connect_to, args.showssl)
|
||||||
@ -442,6 +423,20 @@ def main(args): # pragma: nocover
|
|||||||
if args.timeout:
|
if args.timeout:
|
||||||
p.settimeout(args.timeout)
|
p.settimeout(args.timeout)
|
||||||
for spec in playlist:
|
for spec in playlist:
|
||||||
|
if args.explain or args.memo:
|
||||||
|
spec = spec.freeze(p.settings)
|
||||||
|
if args.memo:
|
||||||
|
h = hashlib.sha256(spec.spec()).digest()
|
||||||
|
if h not in memo:
|
||||||
|
trycount = 0
|
||||||
|
memo.add(h)
|
||||||
|
else:
|
||||||
|
trycount += 1
|
||||||
|
if trycount > args.memolimit:
|
||||||
|
print >> sys.stderr, "Memo limit exceeded..."
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
ret = p.request(spec)
|
ret = p.request(spec)
|
||||||
if ret and args.oneshot:
|
if ret and args.oneshot:
|
||||||
|
@ -75,7 +75,7 @@ class PathodHandler(tcp.BaseHandler):
|
|||||||
def handle_sni(self, connection):
|
def handle_sni(self, connection):
|
||||||
self.sni = connection.get_servername()
|
self.sni = connection.get_servername()
|
||||||
|
|
||||||
def serve_crafted(self, crafted):
|
def http_serve_crafted(self, crafted):
|
||||||
error, crafted = self.server.check_policy(
|
error, crafted = self.server.check_policy(
|
||||||
crafted, self.settings
|
crafted, self.settings
|
||||||
)
|
)
|
||||||
@ -304,7 +304,7 @@ class PathodHandler(tcp.BaseHandler):
|
|||||||
|
|
||||||
if anchor_spec:
|
if anchor_spec:
|
||||||
lg("crafting spec: %s" % anchor_spec)
|
lg("crafting spec: %s" % anchor_spec)
|
||||||
nexthandler, retlog["response"] = self.serve_crafted(
|
nexthandler, retlog["response"] = self.http_serve_crafted(
|
||||||
anchor_spec
|
anchor_spec
|
||||||
)
|
)
|
||||||
if nexthandler and websocket_key:
|
if nexthandler and websocket_key:
|
||||||
|
@ -135,7 +135,7 @@ def test_pathoc(perror):
|
|||||||
tutils.test_data.path("data/request")
|
tutils.test_data.path("data/request")
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
assert len(a.requests) == 1
|
assert len(list(a.requests)) == 1
|
||||||
|
|
||||||
a = cmdline.args_pathod(
|
a = cmdline.args_pathod(
|
||||||
[
|
[
|
||||||
|
@ -5,7 +5,7 @@ from libpathod import language
|
|||||||
|
|
||||||
|
|
||||||
def parse_request(s):
|
def parse_request(s):
|
||||||
return language.parse_pathoc(s)[0]
|
return language.parse_pathoc(s).next()
|
||||||
|
|
||||||
|
|
||||||
def test_unique_name():
|
def test_unique_name():
|
||||||
|
@ -6,11 +6,11 @@ import nose.tools as nt
|
|||||||
|
|
||||||
|
|
||||||
def parse_request(s):
|
def parse_request(s):
|
||||||
return language.parse_pathoc(s)[0]
|
return language.parse_pathoc(s).next()
|
||||||
|
|
||||||
|
|
||||||
def test_times():
|
def test_times():
|
||||||
reqs = language.parse_pathoc("get:/:x5")
|
reqs = list(language.parse_pathoc("get:/:x5"))
|
||||||
assert len(reqs) == 5
|
assert len(reqs) == 5
|
||||||
assert not reqs[0].times
|
assert not reqs[0].times
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import tutils
|
|||||||
|
|
||||||
|
|
||||||
def parse_request(s):
|
def parse_request(s):
|
||||||
return language.parse_pathoc(s)[0]
|
return language.parse_pathoc(s).next()
|
||||||
|
|
||||||
|
|
||||||
def test_make_error_response():
|
def test_make_error_response():
|
||||||
@ -32,7 +32,7 @@ class TestRequest:
|
|||||||
assert len(r.path.string()) == 1024
|
assert len(r.path.string()) == 1024
|
||||||
|
|
||||||
def test_multiple(self):
|
def test_multiple(self):
|
||||||
r = language.parse_pathoc("GET:/ PUT:/")
|
r = list(language.parse_pathoc("GET:/ PUT:/"))
|
||||||
assert r[0].method.string() == "GET"
|
assert r[0].method.string() == "GET"
|
||||||
assert r[1].method.string() == "PUT"
|
assert r[1].method.string() == "PUT"
|
||||||
assert len(r) == 2
|
assert len(r) == 2
|
||||||
@ -52,7 +52,7 @@ class TestRequest:
|
|||||||
|
|
||||||
ir,@1
|
ir,@1
|
||||||
"""
|
"""
|
||||||
r = language.parse_pathoc(l)
|
r = list(language.parse_pathoc(l))
|
||||||
assert len(r) == 2
|
assert len(r) == 2
|
||||||
assert r[0].method.string() == "GET"
|
assert r[0].method.string() == "GET"
|
||||||
assert r[1].method.string() == "PUT"
|
assert r[1].method.string() == "PUT"
|
||||||
@ -61,14 +61,14 @@ class TestRequest:
|
|||||||
get:"http://localhost:9999/p/200":ir,@1
|
get:"http://localhost:9999/p/200":ir,@1
|
||||||
get:"http://localhost:9999/p/200":ir,@2
|
get:"http://localhost:9999/p/200":ir,@2
|
||||||
"""
|
"""
|
||||||
r = language.parse_pathoc(l)
|
r = list(language.parse_pathoc(l))
|
||||||
assert len(r) == 2
|
assert len(r) == 2
|
||||||
assert r[0].method.string() == "GET"
|
assert r[0].method.string() == "GET"
|
||||||
assert r[1].method.string() == "GET"
|
assert r[1].method.string() == "GET"
|
||||||
|
|
||||||
def test_nested_response(self):
|
def test_nested_response(self):
|
||||||
l = "get:/p:s'200'"
|
l = "get:/p:s'200'"
|
||||||
r = language.parse_pathoc(l)
|
r = list(language.parse_pathoc(l))
|
||||||
assert len(r) == 1
|
assert len(r) == 1
|
||||||
assert len(r[0].tokens) == 3
|
assert len(r[0].tokens) == 3
|
||||||
assert isinstance(r[0].tokens[2], http.NestedResponse)
|
assert isinstance(r[0].tokens[2], http.NestedResponse)
|
||||||
|
@ -6,7 +6,7 @@ import tutils
|
|||||||
|
|
||||||
|
|
||||||
def parse_request(s):
|
def parse_request(s):
|
||||||
return language.parse_pathoc(s)[0]
|
return language.parse_pathoc(s).next()
|
||||||
|
|
||||||
|
|
||||||
class TestWebsocketFrame:
|
class TestWebsocketFrame:
|
||||||
|
@ -73,7 +73,7 @@ class _TestDaemon:
|
|||||||
if timeout:
|
if timeout:
|
||||||
c.settimeout(timeout)
|
c.settimeout(timeout)
|
||||||
for i in requests:
|
for i in requests:
|
||||||
r = language.parse_pathoc(i)[0]
|
r = language.parse_pathoc(i).next()
|
||||||
if explain:
|
if explain:
|
||||||
r = r.freeze(language.Settings())
|
r = r.freeze(language.Settings())
|
||||||
try:
|
try:
|
||||||
|
Loading…
Reference in New Issue
Block a user