From 7209a75201a25d7ec2448c6ad1a871c0c403c97e Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 27 Sep 2012 09:44:25 +1200 Subject: [PATCH] Add pathoc -c to specify a list of return codes to ignore. --- libpathod/pathoc.py | 40 +++++++++++++++++++++++----------------- pathoc | 28 +++++++++++++++++++--------- test/test_pathoc.py | 9 ++++++++- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/libpathod/pathoc.py b/libpathod/pathoc.py index 40f698fde..0cc0466d3 100644 --- a/libpathod/pathoc.py +++ b/libpathod/pathoc.py @@ -38,16 +38,17 @@ class Pathoc(tcp.TCPClient): print >> fp, "%s (unprintables escaped):"%header print >> fp, netlib.utils.cleanBin(data) - def print_request(self, spec, showreq, showresp, explain, hexdump, fp=sys.stdout): + def print_request(self, spec, showreq, showresp, explain, hexdump, ignorecodes, fp=sys.stdout): """ Performs a series of requests, and prints results to the specified file descriptor. - reqs: A sequence of request specifications + spec: A request specification showreq: Print requests showresp: Print responses explain: Print request explanation hexdump: When printing requests or responses, use hex dump output + ignorecodes: Sequence of return codes to ignore """ try: r = rparse.parse_request(self.settings, spec) @@ -59,20 +60,11 @@ class Pathoc(tcp.TCPClient): print >> fp, "File access error: %s"%v return - resp = None + resp, req = None, None if showreq: self.wfile.start_log() try: req = r.serve(self.wfile, None, self.host) - if explain: - print >> fp, ">> ", req["method"], repr(req["path"]) - for a in req["actions"]: - print >> fp, "\t", - for x in a: - print >> fp, x, - print >> fp - if showreq: - self._show(fp, ">> Request", self.wfile.get_log(), hexdump) self.wfile.flush() if showresp: self.rfile.start_log() @@ -83,8 +75,22 @@ class Pathoc(tcp.TCPClient): print >> fp, "<<", "Timeout" except tcp.NetLibDisconnect: # pragma: nocover print >> fp, "<<", "Disconnect" - if showresp: - self._show(fp, "<< Response", self.rfile.get_log(), hexdump) - else: - if resp: - self._show_summary(fp, *resp) + + if req: + if ignorecodes and resp and resp[1] in ignorecodes: + return + if explain: + print >> fp, ">>", req["method"], repr(req["path"]) + for a in req["actions"]: + print >> fp, "\t", + for x in a: + print >> fp, x, + print >> fp + if showreq: + self._show(fp, ">> Request", self.wfile.get_log(), hexdump) + + if showresp: + self._show(fp, "<< Response", self.rfile.get_log(), hexdump) + else: + if resp: + self._show_summary(fp, *resp) diff --git a/pathoc b/pathoc index 894709948..9ea5019c7 100755 --- a/pathoc +++ b/pathoc @@ -7,23 +7,23 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description='A perverse HTTP client.') parser.add_argument( "-i", dest="sni", type=str, default=False, - help="SSL Server Name Indication." + help="SSL Server Name Indication" ) parser.add_argument( "-n", dest='repeat', default=1, type=int, metavar="N", - help='Repeat requests N times.' + help='Repeat requests N times' ) parser.add_argument( "-p", dest="port", type=int, default=None, - help="Port. Defaults to 80, or 443 if SSL is active." + help="Port. Defaults to 80, or 443 if SSL is active" ) parser.add_argument( "-s", dest="ssl", action="store_true", default=False, - help="Connect with SSL." + help="Connect with SSL" ) parser.add_argument( "-t", dest="timeout", type=int, default=None, - help="Connection timeout." + help="Connection timeout" ) parser.add_argument( 'host', type=str, @@ -34,21 +34,25 @@ if __name__ == "__main__": help='Request specification' ) group = parser.add_argument_group('Controlling Output') + group.add_argument( + "-c", dest="ignorecodes", type=str, default="", + help="Comma-separated list of response codes filter" + ) group.add_argument( "-e", dest="explain", action="store_true", default=False, - help="Explain requests." + help="Explain requests" ) group.add_argument( "-q", dest="showreq", action="store_true", default=False, - help="Print full request." + help="Print full request" ) group.add_argument( "-r", dest="showresp", action="store_true", default=False, - help="Print full response." + help="Print full response" ) group.add_argument( "-x", dest="hexdump", action="store_true", default=False, - help="Output in hexdump format." + help="Output in hexdump format" ) args = parser.parse_args() @@ -58,6 +62,11 @@ if __name__ == "__main__": else: port = args.port + try: + codes = [int(i) for i in args.ignorecodes.split(",") if i] + except ValueError: + parser.error("Invalid return code specification: %s"%args.ignorecodes) + try: for i in range(args.repeat): p = pathoc.Pathoc(args.host, port) @@ -81,6 +90,7 @@ if __name__ == "__main__": showresp=args.showresp, explain=args.explain, hexdump=args.hexdump, + ignorecodes=codes ) sys.stdout.flush() except KeyboardInterrupt: diff --git a/test/test_pathoc.py b/test/test_pathoc.py index 0a37c4b78..e9690dd58 100644 --- a/test/test_pathoc.py +++ b/test/test_pathoc.py @@ -24,7 +24,7 @@ class TestDaemon: _, _, _, _, content = c.request("get:/api/info") assert tuple(json.loads(content)["version"]) == version.IVERSION - def tval(self, requests, showreq=False, showresp=False, explain=False, hexdump=False, timeout=None): + def tval(self, requests, showreq=False, showresp=False, explain=False, hexdump=False, timeout=None, ignorecodes=None): c = pathoc.Pathoc("127.0.0.1", self.d.port) c.connect() if timeout: @@ -37,10 +37,17 @@ class TestDaemon: showresp = showresp, explain = explain, hexdump = hexdump, + ignorecodes = ignorecodes, fp = s ) return s.getvalue() + def test_ignorecodes(self): + assert "200" in self.tval(["get:'/p/200:b@1'"]) + assert "200" not in self.tval(["get:'/p/200:b@1'"], ignorecodes=[200]) + assert "200" not in self.tval(["get:'/p/200:b@1'"], ignorecodes=[200, 201]) + assert "202" in self.tval(["get:'/p/202:b@1'"], ignorecodes=[200, 201]) + def test_timeout(self): assert "Timeout" in self.tval(["get:'/p/200:p0,10'"], timeout=0.01) assert "HTTP" in self.tval(["get:'/p/200:p5,10'"], showresp=True, timeout=0.01)