From b4105be21e967f79d819749c44eff6ed4311f65d Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 28 Apr 2012 12:42:03 +1200 Subject: Initial checkin. --- pathod | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100755 pathod (limited to 'pathod') diff --git a/pathod b/pathod new file mode 100755 index 00000000..ab8cc93f --- /dev/null +++ b/pathod @@ -0,0 +1,21 @@ +#!/usr/bin/env python +import argparse +import libomnid +import tornado.ioloop + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Process some integers.') + parser.add_argument("-p", dest='port', default=8888, type=int, help='Port.') + parser.add_argument( + "-s", dest='staticdir', default=None, type=str, + help='Directory for static files.' + ) + args = parser.parse_args() + + libomnid.application(staticdir=args.staticdir).listen(args.port) + print "omnid listening on port %s"%args.port + try: + tornado.ioloop.IOLoop.instance().start() + except KeyboardInterrupt: + pass + -- cgit v1.2.3 From 2c8f17eae7b23b7c252bead15ba9bf043f03e8d2 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 28 Apr 2012 13:16:51 +1200 Subject: First pass at static file serving. --- pathod | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index ab8cc93f..4340e2d1 100755 --- a/pathod +++ b/pathod @@ -1,6 +1,6 @@ #!/usr/bin/env python import argparse -import libomnid +import libpathod import tornado.ioloop if __name__ == "__main__": @@ -12,8 +12,8 @@ if __name__ == "__main__": ) args = parser.parse_args() - libomnid.application(staticdir=args.staticdir).listen(args.port) - print "omnid listening on port %s"%args.port + libpathod.application(staticdir=args.staticdir).listen(args.port) + print "pathod listening on port %s"%args.port try: tornado.ioloop.IOLoop.instance().start() except KeyboardInterrupt: -- cgit v1.2.3 From 77eca33f2695eea690dff7999c0e1bd3df0e1733 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 29 Apr 2012 10:56:33 +1200 Subject: Refactor application definitions and startup. Also, create one of the dodgiest web testing trusses in history. Tornado just seems to have no nice way of doing this. --- pathod | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 4340e2d1..100a70a2 100755 --- a/pathod +++ b/pathod @@ -1,6 +1,6 @@ #!/usr/bin/env python import argparse -import libpathod +from libpathod import app import tornado.ioloop if __name__ == "__main__": @@ -12,10 +12,11 @@ if __name__ == "__main__": ) args = parser.parse_args() - libpathod.application(staticdir=args.staticdir).listen(args.port) + application = app.PathodApp( + staticdir=args.staticdir + ) print "pathod listening on port %s"%args.port try: - tornado.ioloop.IOLoop.instance().start() + app.run(application, args.port, None) except KeyboardInterrupt: pass - -- cgit v1.2.3 From 7ca5c7ae90c32cfc238d893eb302acc06deb2e70 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 29 Apr 2012 11:18:56 +1200 Subject: Basic SSL support. --- pathod | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 100a70a2..810763e2 100755 --- a/pathod +++ b/pathod @@ -1,22 +1,44 @@ #!/usr/bin/env python import argparse -from libpathod import app +from libpathod import app, utils import tornado.ioloop if __name__ == "__main__": parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument("-p", dest='port', default=8888, type=int, help='Port.') parser.add_argument( - "-s", dest='staticdir', default=None, type=str, + "-d", dest='staticdir', default=None, type=str, help='Directory for static files.' ) + parser.add_argument( + "-s", dest='ssl', default=False, + action="store_true", + help='Serve with SSL.' + ) + parser.add_argument( + "--keyfile", dest='ssl_keyfile', default=None, + type=str, + help='SSL key file. If not specified, a default key is used.' + ) + parser.add_argument( + "--certfile", dest='ssl_certfile', default=None, + type=str, + help='SSL cert file. If not specified, a default cert is used.' + ) args = parser.parse_args() application = app.PathodApp( staticdir=args.staticdir ) + if args.ssl: + ssl = dict( + keyfile = args.ssl_keyfile or utils.data.path("resources/server.key"), + certfile = args.ssl_certfile or utils.data.path("resources/server.crt"), + ) + else: + ssl = None print "pathod listening on port %s"%args.port try: - app.run(application, args.port, None) + app.run(application, args.port, ssl) except KeyboardInterrupt: pass -- cgit v1.2.3 From 2d88d88f8c27b50f5d4d532ae54a8c643e6dc868 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 29 Apr 2012 12:05:38 +1200 Subject: Basic anchor adding. --- pathod | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 810763e2..fd321da1 100755 --- a/pathod +++ b/pathod @@ -1,11 +1,15 @@ #!/usr/bin/env python -import argparse +import argparse, sys from libpathod import app, utils import tornado.ioloop if __name__ == "__main__": parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument("-p", dest='port', default=8888, type=int, help='Port.') + parser.add_argument( + "-a", dest='anchors', default=[], type=str, action="append", + help='Add an anchor. Specified as a string with the form pattern=pagespec' + ) parser.add_argument( "-d", dest='staticdir', default=None, type=str, help='Directory for static files.' @@ -26,10 +30,17 @@ if __name__ == "__main__": help='SSL cert file. If not specified, a default cert is used.' ) args = parser.parse_args() + settings = dict( + staticdir=args.staticdir + ) + application = app.PathodApp(**settings) + for i in args.anchors: + try: + rex, spec = utils.parse_anchor_spec(i, settings) + except utils.AnchorError, v: + parser.error(str(v)) + application.add_anchor(rex, spec) - application = app.PathodApp( - staticdir=args.staticdir - ) if args.ssl: ssl = dict( keyfile = args.ssl_keyfile or utils.data.path("resources/server.key"), -- cgit v1.2.3 From 5650086ca1927fd7aa21d102048c790d5a28b729 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 29 Apr 2012 17:37:47 +1200 Subject: First pass at a README. --- pathod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index fd321da1..cae06e4a 100755 --- a/pathod +++ b/pathod @@ -5,7 +5,7 @@ import tornado.ioloop if __name__ == "__main__": parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument("-p", dest='port', default=8888, type=int, help='Port.') + parser.add_argument("-p", dest='port', default=9999, type=int, help='Port.') parser.add_argument( "-a", dest='anchors', default=[], type=str, action="append", help='Add an anchor. Specified as a string with the form pattern=pagespec' -- cgit v1.2.3 From c2029496b8612f82ba2bb83beb9b9981d4a2e911 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 29 Apr 2012 21:41:56 +1200 Subject: Doc tweaks. --- pathod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index cae06e4a..a4e81e91 100755 --- a/pathod +++ b/pathod @@ -1,6 +1,6 @@ #!/usr/bin/env python import argparse, sys -from libpathod import app, utils +from libpathod import app, utils, version import tornado.ioloop if __name__ == "__main__": @@ -48,7 +48,7 @@ if __name__ == "__main__": ) else: ssl = None - print "pathod listening on port %s"%args.port + print "%s listening on port %s"%(version.NAMEVERSION, args.port) try: app.run(application, args.port, ssl) except KeyboardInterrupt: -- cgit v1.2.3 From 049d3d2b45d42245a305bd0bd3b5164a44dc7ba2 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 7 Jun 2012 08:50:06 +1200 Subject: lippathod/app.py -> libpathod/pathod.py --- pathod | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index a4e81e91..7fbf3bd7 100755 --- a/pathod +++ b/pathod @@ -1,6 +1,6 @@ #!/usr/bin/env python import argparse, sys -from libpathod import app, utils, version +from libpathod import pathod, utils, version import tornado.ioloop if __name__ == "__main__": @@ -33,7 +33,7 @@ if __name__ == "__main__": settings = dict( staticdir=args.staticdir ) - application = app.PathodApp(**settings) + application = pathod.PathodApp(**settings) for i in args.anchors: try: rex, spec = utils.parse_anchor_spec(i, settings) @@ -50,6 +50,6 @@ if __name__ == "__main__": ssl = None print "%s listening on port %s"%(version.NAMEVERSION, args.port) try: - app.run(application, args.port, ssl) + pathod.run(application, args.port, ssl) except KeyboardInterrupt: pass -- cgit v1.2.3 From b5a74a26ee6548b493cdece5a05f4fcba71c0012 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 7 Jun 2012 10:17:30 +1200 Subject: Let Pathod pick an arbitrary empty port if -p 0 is specified. --- pathod | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 7fbf3bd7..6245fc41 100755 --- a/pathod +++ b/pathod @@ -5,7 +5,8 @@ import tornado.ioloop if __name__ == "__main__": parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument("-p", dest='port', default=9999, type=int, help='Port.') + parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') + parser.add_argument("-l", dest='address', default="0.0.0.0", type=str, help='Listening address.') parser.add_argument( "-a", dest='anchors', default=[], type=str, action="append", help='Add an anchor. Specified as a string with the form pattern=pagespec' @@ -48,8 +49,9 @@ if __name__ == "__main__": ) else: ssl = None - print "%s listening on port %s"%(version.NAMEVERSION, args.port) try: - pathod.run(application, args.port, ssl) + port = pathod.make_server(application, args.port, args.address, ssl) + print "%s listening on port %s"%(version.NAMEVERSION, port) + pathod.run() except KeyboardInterrupt: pass -- cgit v1.2.3 From 14b2a69d2119d8b9d0260aa31190fc7869b45e05 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 7 Jun 2012 11:23:23 +1200 Subject: Start building a Pathod unit testing truss. - Add test.py, which will house the testing API. - Extend API with a shutdown method, used to terminate the test daemon. - Refactor to allow clean shutdown. --- pathod | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 6245fc41..946da92d 100755 --- a/pathod +++ b/pathod @@ -31,16 +31,11 @@ if __name__ == "__main__": help='SSL cert file. If not specified, a default cert is used.' ) args = parser.parse_args() - settings = dict( - staticdir=args.staticdir - ) - application = pathod.PathodApp(**settings) - for i in args.anchors: - try: - rex, spec = utils.parse_anchor_spec(i, settings) - except utils.AnchorError, v: - parser.error(str(v)) - application.add_anchor(rex, spec) + + try: + app = pathod.make_app(staticdir=args.staticdir, anchors=args.anchors) + except utils.AnchorError, v: + parser.error(str(v)) if args.ssl: ssl = dict( @@ -50,8 +45,8 @@ if __name__ == "__main__": else: ssl = None try: - port = pathod.make_server(application, args.port, args.address, ssl) + server, port = pathod.make_server(app, args.port, args.address, ssl) print "%s listening on port %s"%(version.NAMEVERSION, port) - pathod.run() + pathod.run(server) except KeyboardInterrupt: pass -- cgit v1.2.3 From 81fc990314e1f251f12e22b029cb20a64947f150 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 7 Jun 2012 16:36:54 +1200 Subject: Fail if only one of certfile or keyfile is specified. --- pathod | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'pathod') diff --git a/pathod b/pathod index 946da92d..f49baa34 100755 --- a/pathod +++ b/pathod @@ -37,6 +37,10 @@ if __name__ == "__main__": except utils.AnchorError, v: parser.error(str(v)) + sl = [args.ssl_keyfile, args.ssl_certfile] + if any(sl) and not all(sl): + parser.error("Both --certfile and --keyfile must be specified.") + if args.ssl: ssl = dict( keyfile = args.ssl_keyfile or utils.data.path("resources/server.key"), -- cgit v1.2.3 From bd99a13f3965bfdd09a58020424c3b36d97f6877 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 17 Jun 2012 07:57:24 +1200 Subject: Start refactoring towards netlib, adding SNI and client testing. --- pathod | 57 +++------------------------------------------------------ 1 file changed, 3 insertions(+), 54 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index f49baa34..910b936d 100755 --- a/pathod +++ b/pathod @@ -1,56 +1,5 @@ #!/usr/bin/env python -import argparse, sys -from libpathod import pathod, utils, version -import tornado.ioloop +from libpathod import pathod -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') - parser.add_argument("-l", dest='address', default="0.0.0.0", type=str, help='Listening address.') - parser.add_argument( - "-a", dest='anchors', default=[], type=str, action="append", - help='Add an anchor. Specified as a string with the form pattern=pagespec' - ) - parser.add_argument( - "-d", dest='staticdir', default=None, type=str, - help='Directory for static files.' - ) - parser.add_argument( - "-s", dest='ssl', default=False, - action="store_true", - help='Serve with SSL.' - ) - parser.add_argument( - "--keyfile", dest='ssl_keyfile', default=None, - type=str, - help='SSL key file. If not specified, a default key is used.' - ) - parser.add_argument( - "--certfile", dest='ssl_certfile', default=None, - type=str, - help='SSL cert file. If not specified, a default cert is used.' - ) - args = parser.parse_args() - - try: - app = pathod.make_app(staticdir=args.staticdir, anchors=args.anchors) - except utils.AnchorError, v: - parser.error(str(v)) - - sl = [args.ssl_keyfile, args.ssl_certfile] - if any(sl) and not all(sl): - parser.error("Both --certfile and --keyfile must be specified.") - - if args.ssl: - ssl = dict( - keyfile = args.ssl_keyfile or utils.data.path("resources/server.key"), - certfile = args.ssl_certfile or utils.data.path("resources/server.crt"), - ) - else: - ssl = None - try: - server, port = pathod.make_server(app, args.port, args.address, ssl) - print "%s listening on port %s"%(version.NAMEVERSION, port) - pathod.run(server) - except KeyboardInterrupt: - pass +s = pathod.PathodServer(("127.0.0.1", 8888)) +s.serve_forever() -- cgit v1.2.3 From 892ee2a9041166ca4ae1e35893174791b96cccfa Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Tue, 19 Jun 2012 16:57:57 +1200 Subject: Start porting web app to Flask. --- pathod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index 910b936d..f1cdc96c 100755 --- a/pathod +++ b/pathod @@ -1,5 +1,5 @@ #!/usr/bin/env python from libpathod import pathod -s = pathod.PathodServer(("127.0.0.1", 8888)) +s = pathod.Pathod(("127.0.0.1", 8888)) s.serve_forever() -- cgit v1.2.3 From 12c140b951705c08131cc4b86a247bccc9c493c0 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 21 Jun 2012 14:29:49 +1200 Subject: Restore client argument parsing. Add thread-safe logging subsystem. --- pathod | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index f1cdc96c..d8565144 100755 --- a/pathod +++ b/pathod @@ -1,5 +1,57 @@ #!/usr/bin/env python -from libpathod import pathod +import argparse, sys +from libpathod import pathod, utils, version +import tornado.ioloop -s = pathod.Pathod(("127.0.0.1", 8888)) -s.serve_forever() +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Process some integers.') + parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') + parser.add_argument("-l", dest='address', default="0.0.0.0", type=str, help='Listening address.') + parser.add_argument( + "-a", dest='anchors', default=[], type=str, action="append", + help='Add an anchor. Specified as a string with the form pattern=pagespec' + ) + parser.add_argument( + "-d", dest='staticdir', default=None, type=str, + help='Directory for static files.' + ) + parser.add_argument( + "-s", dest='ssl', default=False, + action="store_true", + help='Serve with SSL.' + ) + parser.add_argument( + "--keyfile", dest='ssl_keyfile', default=None, + type=str, + help='SSL key file. If not specified, a default key is used.' + ) + parser.add_argument( + "--certfile", dest='ssl_certfile', default=None, + type=str, + help='SSL cert file. If not specified, a default cert is used.' + ) + args = parser.parse_args() + + sl = [args.ssl_keyfile, args.ssl_certfile] + if any(sl) and not all(sl): + parser.error("Both --certfile and --keyfile must be specified.") + + if args.ssl: + ssl = dict( + keyfile = args.ssl_keyfile or utils.data.path("resources/server.key"), + certfile = args.ssl_certfile or utils.data.path("resources/server.crt"), + ) + else: + ssl = None + + pd = pathod.Pathod( + (args.address, args.port), + ssloptions = ssl, + staticdir = args.staticdir, + anchors = args.anchors + ) + try: + print "%s listening on port %s"%(version.NAMEVERSION, pd.port) + pd.serve_forever() + except KeyboardInterrupt: + pass -- cgit v1.2.3 From b335b3a3358113b3c34565b70288f02fc1cabe06 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 21 Jun 2012 16:58:10 +1200 Subject: Remove last vestige of Tornado pathod. --- pathod | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index d8565144..6b5f6d96 100755 --- a/pathod +++ b/pathod @@ -1,7 +1,6 @@ #!/usr/bin/env python import argparse, sys from libpathod import pathod, utils, version -import tornado.ioloop if __name__ == "__main__": parser = argparse.ArgumentParser(description='Process some integers.') @@ -45,7 +44,7 @@ if __name__ == "__main__": ssl = None pd = pathod.Pathod( - (args.address, args.port), + (args.address, args.port), ssloptions = ssl, staticdir = args.staticdir, anchors = args.anchors -- cgit v1.2.3 From 4fc64ac04ffbec8e3a51ea3f7a129f17530ee3ef Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 24 Jun 2012 16:38:32 +1200 Subject: Enable anchors on command line. --- pathod | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 6b5f6d96..3c8cc08d 100755 --- a/pathod +++ b/pathod @@ -7,7 +7,7 @@ if __name__ == "__main__": parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') parser.add_argument("-l", dest='address', default="0.0.0.0", type=str, help='Listening address.') parser.add_argument( - "-a", dest='anchors', default=[], type=str, action="append", + "-a", dest='anchors', default=[], type=str, action="append", metavar="ANCHOR", help='Add an anchor. Specified as a string with the form pattern=pagespec' ) parser.add_argument( @@ -43,12 +43,22 @@ if __name__ == "__main__": else: ssl = None - pd = pathod.Pathod( - (args.address, args.port), - ssloptions = ssl, - staticdir = args.staticdir, - anchors = args.anchors - ) + alst = [] + for i in args.anchors: + parts = utils.parse_anchor_spec(i) + if not parts: + parser.error("Invalid anchor specification: %s"%i) + alst.append(parts) + + try: + pd = pathod.Pathod( + (args.address, args.port), + ssloptions = ssl, + staticdir = args.staticdir, + anchors = alst + ) + except pathod.PathodError, v: + parser.error(str(v)) try: print "%s listening on port %s"%(version.NAMEVERSION, pd.port) pd.serve_forever() -- cgit v1.2.3 From 90c6fb394de8b56c55aee3db7c7ea6ff72903456 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 24 Jun 2012 21:10:10 +1200 Subject: Sketch out pathoc commandline interaction. --- pathod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index 3c8cc08d..b4ee7eb3 100755 --- a/pathod +++ b/pathod @@ -3,7 +3,7 @@ import argparse, sys from libpathod import pathod, utils, version if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Process some integers.') + parser = argparse.ArgumentParser(description='A pathological HTTP/S daemon.') parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') parser.add_argument("-l", dest='address', default="0.0.0.0", type=str, help='Listening address.') parser.add_argument( -- cgit v1.2.3 From 65487ead6d44970fa13740284a58a703dfd39eac Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 24 Jun 2012 21:40:31 +1200 Subject: Logging truss for pathod. --- pathod | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index b4ee7eb3..7ba5ad80 100755 --- a/pathod +++ b/pathod @@ -1,5 +1,5 @@ #!/usr/bin/env python -import argparse, sys +import argparse, sys, logging from libpathod import pathod, utils, version if __name__ == "__main__": @@ -14,6 +14,11 @@ if __name__ == "__main__": "-d", dest='staticdir', default=None, type=str, help='Directory for static files.' ) + parser.add_argument( + "--debug", dest='debug', default=False, + action="store_true", + help='Enable debug output.' + ) parser.add_argument( "-s", dest='ssl', default=False, action="store_true", @@ -50,6 +55,18 @@ if __name__ == "__main__": parser.error("Invalid anchor specification: %s"%i) alst.append(parts) + root = logging.getLogger() + if root.handlers: + for handler in root.handlers: + root.removeHandler(handler) + logging.basicConfig( + format='%(asctime)s: %(message)s', + datefmt='%d-%m-%y %I:%M:%S', + level=logging.DEBUG + ) + if not args.debug: + logging.disable(logging.DEBUG) + try: pd = pathod.Pathod( (args.address, args.port), -- cgit v1.2.3 From 1c45f5b05c7e066c28dfd4c9d1cde3b794f8983c Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Mon, 23 Jul 2012 15:03:56 +1200 Subject: Use policy hook to apply a size limit in pathod, add corresponding cmdline arg. --- pathod | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index 7ba5ad80..052b94bb 100755 --- a/pathod +++ b/pathod @@ -24,6 +24,11 @@ if __name__ == "__main__": action="store_true", help='Serve with SSL.' ) + parser.add_argument( + "--limit-size", dest='sizelimit', default=None, + type=str, + help='Size limit of served responses. Understands size suffixes, i.e. 100k.' + ) parser.add_argument( "--keyfile", dest='ssl_keyfile', default=None, type=str, @@ -67,12 +72,20 @@ if __name__ == "__main__": if not args.debug: logging.disable(logging.DEBUG) + sizelimit = None + if args.sizelimit: + try: + sizelimit = utils.parse_size(args.sizelimit) + except ValueError, v: + parser.error(v) + try: pd = pathod.Pathod( (args.address, args.port), ssloptions = ssl, staticdir = args.staticdir, - anchors = alst + anchors = alst, + sizelimit = sizelimit, ) except pathod.PathodError, v: parser.error(str(v)) -- cgit v1.2.3 From 622a2b560753f2e4aa96bfb4e97bfcac4d0bedbd Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Mon, 23 Jul 2012 19:55:33 +1200 Subject: Add a --noweb option to turn web iface off, refactor unit tests. --- pathod | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 052b94bb..d2635ff5 100755 --- a/pathod +++ b/pathod @@ -15,28 +15,27 @@ if __name__ == "__main__": help='Directory for static files.' ) parser.add_argument( - "--debug", dest='debug', default=False, - action="store_true", + "--debug", dest='debug', default=False, action="store_true", help='Enable debug output.' ) parser.add_argument( - "-s", dest='ssl', default=False, - action="store_true", + "-s", dest='ssl', default=False, action="store_true", help='Serve with SSL.' ) parser.add_argument( - "--limit-size", dest='sizelimit', default=None, - type=str, + "--limit-size", dest='sizelimit', default=None, type=str, help='Size limit of served responses. Understands size suffixes, i.e. 100k.' ) parser.add_argument( - "--keyfile", dest='ssl_keyfile', default=None, - type=str, + "--noweb", dest='noweb', default=False, action="store_true", + help='Disable web interface and API.' + ) + parser.add_argument( + "--keyfile", dest='ssl_keyfile', default=None, type=str, help='SSL key file. If not specified, a default key is used.' ) parser.add_argument( - "--certfile", dest='ssl_certfile', default=None, - type=str, + "--certfile", dest='ssl_certfile', default=None, type=str, help='SSL cert file. If not specified, a default cert is used.' ) args = parser.parse_args() @@ -86,6 +85,7 @@ if __name__ == "__main__": staticdir = args.staticdir, anchors = alst, sizelimit = sizelimit, + noweb = args.noweb ) except pathod.PathodError, v: parser.error(str(v)) -- cgit v1.2.3 From 190392ea13f998fe298d48738131779f522d62e9 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Mon, 23 Jul 2012 21:39:31 +1200 Subject: Add a --nocraft option to pathod that turns off crafting. --- pathod | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index d2635ff5..0bb8da31 100755 --- a/pathod +++ b/pathod @@ -30,6 +30,10 @@ if __name__ == "__main__": "--noweb", dest='noweb', default=False, action="store_true", help='Disable web interface and API.' ) + parser.add_argument( + "--nocraft", dest='nocraft', default=False, action="store_true", + help='Disable response crafting. If anchors are specified, they still work.' + ) parser.add_argument( "--keyfile", dest='ssl_keyfile', default=None, type=str, help='SSL key file. If not specified, a default key is used.' @@ -85,7 +89,8 @@ if __name__ == "__main__": staticdir = args.staticdir, anchors = alst, sizelimit = sizelimit, - noweb = args.noweb + noweb = args.noweb, + nocraft = args.nocraft ) except pathod.PathodError, v: parser.error(str(v)) -- cgit v1.2.3 From a950a4d7a3097685d54f325f32a169034e9435f1 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Mon, 23 Jul 2012 23:31:26 +1200 Subject: Add pathod --noapi to turn off the service API. --- pathod | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 0bb8da31..a5cc02ca 100755 --- a/pathod +++ b/pathod @@ -26,9 +26,13 @@ if __name__ == "__main__": "--limit-size", dest='sizelimit', default=None, type=str, help='Size limit of served responses. Understands size suffixes, i.e. 100k.' ) + parser.add_argument( + "--noapi", dest='noapi', default=False, action="store_true", + help='Disable API.' + ) parser.add_argument( "--noweb", dest='noweb', default=False, action="store_true", - help='Disable web interface and API.' + help='Disable both web interface and API.' ) parser.add_argument( "--nocraft", dest='nocraft', default=False, action="store_true", @@ -90,7 +94,8 @@ if __name__ == "__main__": anchors = alst, sizelimit = sizelimit, noweb = args.noweb, - nocraft = args.nocraft + nocraft = args.nocraft, + noapi = args.noapi ) except pathod.PathodError, v: parser.error(str(v)) -- cgit v1.2.3 From eb1f2c3fc40ccfc0db60776412add6a35af93bf9 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Tue, 24 Jul 2012 21:51:43 +1200 Subject: Add option to specify craft anchor point. --- pathod | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'pathod') diff --git a/pathod b/pathod index a5cc02ca..df044ae7 100755 --- a/pathod +++ b/pathod @@ -10,6 +10,10 @@ if __name__ == "__main__": "-a", dest='anchors', default=[], type=str, action="append", metavar="ANCHOR", help='Add an anchor. Specified as a string with the form pattern=pagespec' ) + parser.add_argument( + "-c", dest='craftanchor', default="/p/", type=str, + help='Anchorpoint for URL crafting commands.' + ) parser.add_argument( "-d", dest='staticdir', default=None, type=str, help='Directory for static files.' @@ -89,6 +93,7 @@ if __name__ == "__main__": try: pd = pathod.Pathod( (args.address, args.port), + craftanchor = args.craftanchor, ssloptions = ssl, staticdir = args.staticdir, anchors = alst, -- cgit v1.2.3 From 3e158211a830bbcba2dd463189a79ec3ad17c8d4 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 26 Jul 2012 20:01:51 +1200 Subject: Add a --nohang flag that turns off pauses in response generation. --- pathod | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index df044ae7..56f6e3fe 100755 --- a/pathod +++ b/pathod @@ -34,6 +34,10 @@ if __name__ == "__main__": "--noapi", dest='noapi', default=False, action="store_true", help='Disable API.' ) + parser.add_argument( + "--nohang", dest='nohang', default=False, action="store_true", + help='Disable pauses during crafted response generation.' + ) parser.add_argument( "--noweb", dest='noweb', default=False, action="store_true", help='Disable both web interface and API.' @@ -100,7 +104,8 @@ if __name__ == "__main__": sizelimit = sizelimit, noweb = args.noweb, nocraft = args.nocraft, - noapi = args.noapi + noapi = args.noapi, + nohang = args.nohang ) except pathod.PathodError, v: parser.error(str(v)) -- cgit v1.2.3 From d8c53cbc57574bfce0be617d36e7ccf6f1b55885 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 27 Jul 2012 14:03:15 +1200 Subject: Add an option to specify a log file to pathod. --- pathod | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 56f6e3fe..144e01b5 100755 --- a/pathod +++ b/pathod @@ -1,5 +1,5 @@ #!/usr/bin/env python -import argparse, sys, logging +import argparse, sys, logging, logging.handlers from libpathod import pathod, utils, version if __name__ == "__main__": @@ -18,6 +18,10 @@ if __name__ == "__main__": "-d", dest='staticdir', default=None, type=str, help='Directory for static files.' ) + parser.add_argument( + "-f", dest='logfile', default=None, type=str, + help='Log file.' + ) parser.add_argument( "--debug", dest='debug', default=False, action="store_true", help='Enable debug output.' @@ -86,6 +90,10 @@ if __name__ == "__main__": ) if not args.debug: logging.disable(logging.DEBUG) + if args.logfile: + ch = logging.handlers.WatchedFileHandler(args.logfile) + root.addHandler(ch) + sizelimit = None if args.sizelimit: @@ -104,7 +112,7 @@ if __name__ == "__main__": sizelimit = sizelimit, noweb = args.noweb, nocraft = args.nocraft, - noapi = args.noapi, + noapi = args.noapi, nohang = args.nohang ) except pathod.PathodError, v: -- cgit v1.2.3 From bc84cc99cdc6785f8e1f93113435914fc7a138f4 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 29 Jul 2012 16:10:22 +1200 Subject: Handle file access denied in pathod. --- pathod | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index 144e01b5..ba290dcf 100755 --- a/pathod +++ b/pathod @@ -1,6 +1,6 @@ #!/usr/bin/env python import argparse, sys, logging, logging.handlers -from libpathod import pathod, utils, version +from libpathod import pathod, utils, version, rparse if __name__ == "__main__": parser = argparse.ArgumentParser(description='A pathological HTTP/S daemon.') @@ -117,6 +117,9 @@ if __name__ == "__main__": ) except pathod.PathodError, v: parser.error(str(v)) + except rparse.FileAccessDenied, v: + parser.error("%s You probably want to a -d argument."%str(v)) + try: print "%s listening on port %s"%(version.NAMEVERSION, pd.port) pd.serve_forever() -- cgit v1.2.3 From d7db6757b24ed8ab415d6fe979738325199ed82b Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 29 Jul 2012 17:29:38 +1200 Subject: Listen on localhost by default. --- pathod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index ba290dcf..c136d531 100755 --- a/pathod +++ b/pathod @@ -5,7 +5,7 @@ from libpathod import pathod, utils, version, rparse if __name__ == "__main__": parser = argparse.ArgumentParser(description='A pathological HTTP/S daemon.') parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') - parser.add_argument("-l", dest='address', default="0.0.0.0", type=str, help='Listening address.') + parser.add_argument("-l", dest='address', default="127.0.0.1", type=str, help='Listening address.') parser.add_argument( "-a", dest='anchors', default=[], type=str, action="append", metavar="ANCHOR", help='Add an anchor. Specified as a string with the form pattern=pagespec' @@ -121,7 +121,7 @@ if __name__ == "__main__": parser.error("%s You probably want to a -d argument."%str(v)) try: - print "%s listening on port %s"%(version.NAMEVERSION, pd.port) + print "%s listening on %s:%s"%(version.NAMEVERSION, args.address, pd.port) pd.serve_forever() except KeyboardInterrupt: pass -- cgit v1.2.3 From ea2ca98bea2334d7ad925a929db1a688b9ad7e9c Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 16 Aug 2012 16:07:23 +1200 Subject: Add -D to daemonize pathod. --- pathod | 151 ++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 94 insertions(+), 57 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index c136d531..9d5d64bf 100755 --- a/pathod +++ b/pathod @@ -1,65 +1,35 @@ #!/usr/bin/env python import argparse, sys, logging, logging.handlers +import os from libpathod import pathod, utils, version, rparse -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='A pathological HTTP/S daemon.') - parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') - parser.add_argument("-l", dest='address', default="127.0.0.1", type=str, help='Listening address.') - parser.add_argument( - "-a", dest='anchors', default=[], type=str, action="append", metavar="ANCHOR", - help='Add an anchor. Specified as a string with the form pattern=pagespec' - ) - parser.add_argument( - "-c", dest='craftanchor', default="/p/", type=str, - help='Anchorpoint for URL crafting commands.' - ) - parser.add_argument( - "-d", dest='staticdir', default=None, type=str, - help='Directory for static files.' - ) - parser.add_argument( - "-f", dest='logfile', default=None, type=str, - help='Log file.' - ) - parser.add_argument( - "--debug", dest='debug', default=False, action="store_true", - help='Enable debug output.' - ) - parser.add_argument( - "-s", dest='ssl', default=False, action="store_true", - help='Serve with SSL.' - ) - parser.add_argument( - "--limit-size", dest='sizelimit', default=None, type=str, - help='Size limit of served responses. Understands size suffixes, i.e. 100k.' - ) - parser.add_argument( - "--noapi", dest='noapi', default=False, action="store_true", - help='Disable API.' - ) - parser.add_argument( - "--nohang", dest='nohang', default=False, action="store_true", - help='Disable pauses during crafted response generation.' - ) - parser.add_argument( - "--noweb", dest='noweb', default=False, action="store_true", - help='Disable both web interface and API.' - ) - parser.add_argument( - "--nocraft", dest='nocraft', default=False, action="store_true", - help='Disable response crafting. If anchors are specified, they still work.' - ) - parser.add_argument( - "--keyfile", dest='ssl_keyfile', default=None, type=str, - help='SSL key file. If not specified, a default key is used.' - ) - parser.add_argument( - "--certfile", dest='ssl_certfile', default=None, type=str, - help='SSL cert file. If not specified, a default cert is used.' - ) - args = parser.parse_args() +def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): + try: + pid = os.fork() + if pid > 0: + sys.exit(0) + except OSError, e: + sys.stderr.write ("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror) ) + sys.exit(1) + os.chdir("/") + os.umask(0) + os.setsid() + try: + pid = os.fork() + if pid > 0: + sys.exit(0) + except OSError, e: + sys.stderr.write ("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) ) + sys.exit(1) + si = open(stdin, 'r') + so = open(stdout, 'a+') + se = open(stderr, 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + +def main(parser, args): sl = [args.ssl_keyfile, args.ssl_certfile] if any(sl) and not all(sl): parser.error("Both --certfile and --keyfile must be specified.") @@ -125,3 +95,70 @@ if __name__ == "__main__": pd.serve_forever() except KeyboardInterrupt: pass + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='A pathological HTTP/S daemon.') + parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') + parser.add_argument("-l", dest='address', default="127.0.0.1", type=str, help='Listening address.') + parser.add_argument( + "-a", dest='anchors', default=[], type=str, action="append", metavar="ANCHOR", + help='Add an anchor. Specified as a string with the form pattern=pagespec' + ) + parser.add_argument( + "-c", dest='craftanchor', default="/p/", type=str, + help='Anchorpoint for URL crafting commands.' + ) + parser.add_argument( + "-d", dest='staticdir', default=None, type=str, + help='Directory for static files.' + ) + parser.add_argument( + "-D", dest='daemonize', default=False, action="store_true", + help='Daemonize.' + ) + parser.add_argument( + "-f", dest='logfile', default=None, type=str, + help='Log file.' + ) + parser.add_argument( + "--debug", dest='debug', default=False, action="store_true", + help='Enable debug output.' + ) + parser.add_argument( + "-s", dest='ssl', default=False, action="store_true", + help='Serve with SSL.' + ) + parser.add_argument( + "--limit-size", dest='sizelimit', default=None, type=str, + help='Size limit of served responses. Understands size suffixes, i.e. 100k.' + ) + parser.add_argument( + "--noapi", dest='noapi', default=False, action="store_true", + help='Disable API.' + ) + parser.add_argument( + "--nohang", dest='nohang', default=False, action="store_true", + help='Disable pauses during crafted response generation.' + ) + parser.add_argument( + "--noweb", dest='noweb', default=False, action="store_true", + help='Disable both web interface and API.' + ) + parser.add_argument( + "--nocraft", dest='nocraft', default=False, action="store_true", + help='Disable response crafting. If anchors are specified, they still work.' + ) + parser.add_argument( + "--keyfile", dest='ssl_keyfile', default=None, type=str, + help='SSL key file. If not specified, a default key is used.' + ) + parser.add_argument( + "--certfile", dest='ssl_certfile', default=None, type=str, + help='SSL cert file. If not specified, a default cert is used.' + ) + args = parser.parse_args() + if args.daemonize: + daemonize() + main(parser, args) + -- cgit v1.2.3 From d758409b76454db983b28b023653aad977181717 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 23 Aug 2012 12:00:16 +1200 Subject: Make sure date stamps are added to all logs. --- pathod | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 9d5d64bf..ba7662ea 100755 --- a/pathod +++ b/pathod @@ -3,6 +3,7 @@ import argparse, sys, logging, logging.handlers import os from libpathod import pathod, utils, version, rparse + def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): try: pid = os.fork() @@ -53,17 +54,21 @@ def main(parser, args): if root.handlers: for handler in root.handlers: root.removeHandler(handler) - logging.basicConfig( - format='%(asctime)s: %(message)s', + + log = logging.getLogger('pathod') + log.setLevel(logging.DEBUG) + fmt = logging.Formatter( + '%(asctime)s: %(message)s', datefmt='%d-%m-%y %I:%M:%S', - level=logging.DEBUG ) - if not args.debug: - logging.disable(logging.DEBUG) if args.logfile: - ch = logging.handlers.WatchedFileHandler(args.logfile) - root.addHandler(ch) - + fh = logging.handlers.WatchedFileHandler(args.logfile) + fh.setFormatter(fmt) + log.addHandler(fh) + if not args.daemonize: + sh = logging.StreamHandler() + sh.setFormatter(fmt) + log.addHandler(sh) sizelimit = None if args.sizelimit: -- cgit v1.2.3 From 60b016365f627f7c26561056b4257a2ce739f018 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 23 Aug 2012 17:22:17 +1200 Subject: Use 24-hour clock for log timestamps. --- pathod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index ba7662ea..82a7edc0 100755 --- a/pathod +++ b/pathod @@ -59,7 +59,7 @@ def main(parser, args): log.setLevel(logging.DEBUG) fmt = logging.Formatter( '%(asctime)s: %(message)s', - datefmt='%d-%m-%y %I:%M:%S', + datefmt='%d-%m-%y %H:%M:%S', ) if args.logfile: fh = logging.handlers.WatchedFileHandler(args.logfile) -- cgit v1.2.3 From 915bcfbd305d7b18de07f4f40dab1e49a06b132c Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Mon, 1 Oct 2012 12:01:02 +1300 Subject: Add timeout argument to Pathod, and matching -t command-line option. --- pathod | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index 82a7edc0..91cd13e3 100755 --- a/pathod +++ b/pathod @@ -88,7 +88,8 @@ def main(parser, args): noweb = args.noweb, nocraft = args.nocraft, noapi = args.noapi, - nohang = args.nohang + nohang = args.nohang, + timeout = args.timeout ) except pathod.PathodError, v: parser.error(str(v)) @@ -134,6 +135,10 @@ if __name__ == "__main__": "-s", dest='ssl', default=False, action="store_true", help='Serve with SSL.' ) + parser.add_argument( + "-t", dest="timeout", type=int, default=None, + help="Connection timeout" + ) parser.add_argument( "--limit-size", dest='sizelimit', default=None, type=str, help='Size limit of served responses. Understands size suffixes, i.e. 100k.' -- cgit v1.2.3 From 41f1c66772c6546fc39b9dcf64d8c04992a2e1ab Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Mon, 1 Oct 2012 12:48:26 +1300 Subject: Add -q and -r flags to pathod, logging request and respnose bytes. - These flags also mean that a bytes log is included in the internal log buffer. - There's an -x flag to turn on hex dump output in the text logs (does not affect the log buffer). --- pathod | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 91cd13e3..e692a935 100755 --- a/pathod +++ b/pathod @@ -89,7 +89,10 @@ def main(parser, args): nocraft = args.nocraft, noapi = args.noapi, nohang = args.nohang, - timeout = args.timeout + timeout = args.timeout, + logreq = args.logreq, + logresp = args.logresp, + hexdump = args.hexdump ) except pathod.PathodError, v: parser.error(str(v)) @@ -123,14 +126,6 @@ if __name__ == "__main__": "-D", dest='daemonize', default=False, action="store_true", help='Daemonize.' ) - parser.add_argument( - "-f", dest='logfile', default=None, type=str, - help='Log file.' - ) - parser.add_argument( - "--debug", dest='debug', default=False, action="store_true", - help='Enable debug output.' - ) parser.add_argument( "-s", dest='ssl', default=False, action="store_true", help='Serve with SSL.' @@ -167,6 +162,26 @@ if __name__ == "__main__": "--certfile", dest='ssl_certfile', default=None, type=str, help='SSL cert file. If not specified, a default cert is used.' ) + + + group = parser.add_argument_group('Controlling Output') + group.add_argument( + "-f", dest='logfile', default=None, type=str, + help='Log to file.' + ) + group.add_argument( + "-q", dest="logreq", action="store_true", default=False, + help="Log full request" + ) + group.add_argument( + "-r", dest="logresp", action="store_true", default=False, + help="Log full response" + ) + group.add_argument( + "-x", dest="hexdump", action="store_true", default=False, + help="Log request/response in hexdump format" + ) + args = parser.parse_args() if args.daemonize: daemonize() -- cgit v1.2.3 From f5d5cc49887d3a54bc5edc7905b90e5912ae9e8a Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 5 Oct 2012 10:30:32 +1300 Subject: rparse.py -> language.py --- pathod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index e692a935..41b7578d 100755 --- a/pathod +++ b/pathod @@ -1,7 +1,7 @@ #!/usr/bin/env python import argparse, sys, logging, logging.handlers import os -from libpathod import pathod, utils, version, rparse +from libpathod import pathod, utils, version, language def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): @@ -96,7 +96,7 @@ def main(parser, args): ) except pathod.PathodError, v: parser.error(str(v)) - except rparse.FileAccessDenied, v: + except language.FileAccessDenied, v: parser.error("%s You probably want to a -d argument."%str(v)) try: -- cgit v1.2.3 From 3f50930dc06a980ac5dcf012fa23ecc0a70ce1b4 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 31 Oct 2012 11:23:53 +1300 Subject: Use .freeze to implement the -e explain flags for pathod and pathoc. This now prints (in pathoc) or logs (in pathod) a frozen specification that includes an expanded record of all generated values and locations. --- pathod | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 41b7578d..09facad4 100755 --- a/pathod +++ b/pathod @@ -92,7 +92,8 @@ def main(parser, args): timeout = args.timeout, logreq = args.logreq, logresp = args.logresp, - hexdump = args.hexdump + hexdump = args.hexdump, + explain = args.explain ) except pathod.PathodError, v: parser.error(str(v)) @@ -164,7 +165,17 @@ if __name__ == "__main__": ) - group = parser.add_argument_group('Controlling Output') + group = parser.add_argument_group( + 'Controlling Logging', + """ + Some of these options expand generated values for logging - if + you're generating large data, use them with caution. + """ + ) + group.add_argument( + "-e", dest="explain", action="store_true", default=False, + help="Explain responses" + ) group.add_argument( "-f", dest='logfile', default=None, type=str, help='Log to file.' -- cgit v1.2.3 From b07ab253b7a2adec01233989d983d2f180c9fe4e Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Mon, 31 Dec 2012 12:23:42 +1300 Subject: Require requests > 1.0.4 This changes the API slightly, since json is now a method, not a property. --- pathod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index 09facad4..27e7e040 100755 --- a/pathod +++ b/pathod @@ -166,7 +166,7 @@ if __name__ == "__main__": group = parser.add_argument_group( - 'Controlling Logging', + 'Controlling Logging', """ Some of these options expand generated values for logging - if you're generating large data, use them with caution. -- cgit v1.2.3 From 3886ccae9379d065e54e0eb7e961992ff3c0ee62 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 5 Jan 2013 15:25:09 +1300 Subject: Provisional proxy mode support for pathod. --- pathod | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 27e7e040..685352ba 100755 --- a/pathod +++ b/pathod @@ -36,12 +36,13 @@ def main(parser, args): parser.error("Both --certfile and --keyfile must be specified.") if args.ssl: - ssl = dict( + ssloptions = dict( keyfile = args.ssl_keyfile or utils.data.path("resources/server.key"), certfile = args.ssl_certfile or utils.data.path("resources/server.crt"), + ssl_after_connect = args.ssl_after_connect ) else: - ssl = None + ssloptions = None alst = [] for i in args.anchors: @@ -81,7 +82,7 @@ def main(parser, args): pd = pathod.Pathod( (args.address, args.port), craftanchor = args.craftanchor, - ssloptions = ssl, + ssloptions = ssloptions, staticdir = args.staticdir, anchors = alst, sizelimit = sizelimit, @@ -93,7 +94,7 @@ def main(parser, args): logreq = args.logreq, logresp = args.logresp, hexdump = args.hexdump, - explain = args.explain + explain = args.explain, ) except pathod.PathodError, v: parser.error(str(v)) @@ -127,10 +128,6 @@ if __name__ == "__main__": "-D", dest='daemonize', default=False, action="store_true", help='Daemonize.' ) - parser.add_argument( - "-s", dest='ssl', default=False, action="store_true", - help='Serve with SSL.' - ) parser.add_argument( "-t", dest="timeout", type=int, default=None, help="Connection timeout" @@ -155,11 +152,24 @@ if __name__ == "__main__": "--nocraft", dest='nocraft', default=False, action="store_true", help='Disable response crafting. If anchors are specified, they still work.' ) - parser.add_argument( + + + group = parser.add_argument_group( + 'SSL', + ) + group.add_argument( + "-C", dest='ssl_after_connect', default=False, action="store_true", + help='Expect SSL after a CONNECT request.' + ) + group.add_argument( + "-s", dest='ssl', default=False, action="store_true", + help='Serve with SSL.' + ) + group.add_argument( "--keyfile", dest='ssl_keyfile', default=None, type=str, help='SSL key file. If not specified, a default key is used.' ) - parser.add_argument( + group.add_argument( "--certfile", dest='ssl_certfile', default=None, type=str, help='SSL cert file. If not specified, a default cert is used.' ) -- cgit v1.2.3 From 1e932e704577ff8159f93d424d4b7041dec29eea Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 5 Jan 2013 16:48:49 +1300 Subject: Collect SSL options into an SSLOptions object Also split SSL cert specifications from SSL service mode - we can now enter SSL service mode through a proxy CONNECT request as well. --- pathod | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 685352ba..29f59193 100755 --- a/pathod +++ b/pathod @@ -35,14 +35,11 @@ def main(parser, args): if any(sl) and not all(sl): parser.error("Both --certfile and --keyfile must be specified.") - if args.ssl: - ssloptions = dict( - keyfile = args.ssl_keyfile or utils.data.path("resources/server.key"), - certfile = args.ssl_certfile or utils.data.path("resources/server.crt"), - ssl_after_connect = args.ssl_after_connect - ) - else: - ssloptions = None + ssloptions = pathod.SSLOptions( + keyfile = args.ssl_keyfile, + certfile = args.ssl_certfile, + not_after_connect = args.ssl_not_after_connect + ) alst = [] for i in args.anchors: @@ -82,6 +79,7 @@ def main(parser, args): pd = pathod.Pathod( (args.address, args.port), craftanchor = args.craftanchor, + ssl = args.ssl, ssloptions = ssloptions, staticdir = args.staticdir, anchors = alst, @@ -158,12 +156,12 @@ if __name__ == "__main__": 'SSL', ) group.add_argument( - "-C", dest='ssl_after_connect', default=False, action="store_true", - help='Expect SSL after a CONNECT request.' + "-C", dest='ssl_not_after_connect', default=False, action="store_true", + help="Don't expect SSL after a CONNECT request." ) group.add_argument( "-s", dest='ssl', default=False, action="store_true", - help='Serve with SSL.' + help='Run in HTTPS mode.' ) group.add_argument( "--keyfile", dest='ssl_keyfile', default=None, type=str, -- cgit v1.2.3 From 9e7f08acea55e2da53f5f2c93d6948c447cf1861 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 15 May 2013 18:56:05 +1200 Subject: Download path, version flags for both tools. --- pathod | 1 + 1 file changed, 1 insertion(+) (limited to 'pathod') diff --git a/pathod b/pathod index 29f59193..60ade46e 100755 --- a/pathod +++ b/pathod @@ -108,6 +108,7 @@ def main(parser, args): if __name__ == "__main__": parser = argparse.ArgumentParser(description='A pathological HTTP/S daemon.') + parser.add_argument('--version', action='version', version="pathod " + version.VERSION) parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') parser.add_argument("-l", dest='address', default="127.0.0.1", type=str, help='Listening address.') parser.add_argument( -- cgit v1.2.3 From 42aede6181c643bb5bbd35ca81b6c1b1c69ec4b5 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 19 Aug 2013 19:21:47 +0200 Subject: ensure binary read on windows --- pathod | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 60ade46e..10e9ba55 100755 --- a/pathod +++ b/pathod @@ -22,9 +22,9 @@ def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): except OSError, e: sys.stderr.write ("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) ) sys.exit(1) - si = open(stdin, 'r') - so = open(stdout, 'a+') - se = open(stderr, 'a+', 0) + si = open(stdin, 'rb') + so = open(stdout, 'a+b') + se = open(stderr, 'a+b', 0) os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) -- cgit v1.2.3 From 0c04abb6e4c549646c06ef9e270d1b42c1ffaf1d Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Sat, 8 Feb 2014 22:42:27 +0100 Subject: fix pathod main script --- pathod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index 10e9ba55..4e292cb1 100755 --- a/pathod +++ b/pathod @@ -100,7 +100,7 @@ def main(parser, args): parser.error("%s You probably want to a -d argument."%str(v)) try: - print "%s listening on %s:%s"%(version.NAMEVERSION, args.address, pd.port) + print "%s listening on %s:%s"%(version.NAMEVERSION, args.address, pd.address.port) pd.serve_forever() except KeyboardInterrupt: pass -- cgit v1.2.3 From a1d0da2b533b986967a8714c02d567c943d11929 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 27 Feb 2014 18:33:48 +1300 Subject: Expand SSL support - Cipher suite selection for both pathoc and pathod - SSL version specification for pathod - Expose SSLv23 as an option, and use it by default --- pathod | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 4e292cb1..ceadfa98 100755 --- a/pathod +++ b/pathod @@ -38,7 +38,9 @@ def main(parser, args): ssloptions = pathod.SSLOptions( keyfile = args.ssl_keyfile, certfile = args.ssl_certfile, - not_after_connect = args.ssl_not_after_connect + not_after_connect = args.ssl_not_after_connect, + ciphers = args.ciphers, + sslversion = utils.SSLVERSIONS[args.sslversion] ) alst = [] @@ -100,7 +102,7 @@ def main(parser, args): parser.error("%s You probably want to a -d argument."%str(v)) try: - print "%s listening on %s:%s"%(version.NAMEVERSION, args.address, pd.address.port) + print "%s listening on %s:%s"%(version.NAMEVERSION, pd.address.host, pd.address.port) pd.serve_forever() except KeyboardInterrupt: pass @@ -172,7 +174,15 @@ if __name__ == "__main__": "--certfile", dest='ssl_certfile', default=None, type=str, help='SSL cert file. If not specified, a default cert is used.' ) - + group.add_argument( + "--ciphers", dest="ciphers", type=str, default=False, + help="SSL cipher specification" + ) + group.add_argument( + "--sslversion", dest="sslversion", type=int, default=4, + choices=[1, 2, 3, 4], + help="Use a specified protocol - TLSv1, SSLv2, SSLv3, SSLv23. Default to SSLv23." + ) group = parser.add_argument_group( 'Controlling Logging', -- cgit v1.2.3 From 091e539a0203ca272e3a4ba2a9f23331bbd85005 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 2 Mar 2014 13:45:35 +1300 Subject: Big improvements to SSL handling - pathod now dynamically generates SSL certs, using the ~/.mitmproxy cacert - pathoc returns data on SSL peer certificates - Pathod certificate CN can be specified on command line - Support SSLv23 --- pathod | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index ceadfa98..5b82f97e 100755 --- a/pathod +++ b/pathod @@ -31,16 +31,13 @@ def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): def main(parser, args): - sl = [args.ssl_keyfile, args.ssl_certfile] - if any(sl) and not all(sl): - parser.error("Both --certfile and --keyfile must be specified.") - ssloptions = pathod.SSLOptions( - keyfile = args.ssl_keyfile, - certfile = args.ssl_certfile, - not_after_connect = args.ssl_not_after_connect, - ciphers = args.ciphers, - sslversion = utils.SSLVERSIONS[args.sslversion] + cn = args.cn, + confdir = args.confdir, + certfile = args.ssl_certfile, + not_after_connect = args.ssl_not_after_connect, + ciphers = args.ciphers, + sslversion = utils.SSLVERSIONS[args.sslversion] ) alst = [] @@ -121,6 +118,11 @@ if __name__ == "__main__": "-c", dest='craftanchor', default="/p/", type=str, help='Anchorpoint for URL crafting commands.' ) + parser.add_argument( + "--confdir", + action="store", type = str, dest="confdir", default='~/.mitmproxy', + help = "Configuration directory. (~/.mitmproxy)" + ) parser.add_argument( "-d", dest='staticdir', default=None, type=str, help='Directory for static files.' @@ -158,17 +160,17 @@ if __name__ == "__main__": group = parser.add_argument_group( 'SSL', ) - group.add_argument( - "-C", dest='ssl_not_after_connect', default=False, action="store_true", - help="Don't expect SSL after a CONNECT request." - ) group.add_argument( "-s", dest='ssl', default=False, action="store_true", help='Run in HTTPS mode.' ) group.add_argument( - "--keyfile", dest='ssl_keyfile', default=None, type=str, - help='SSL key file. If not specified, a default key is used.' + "--cn", dest="cn", type=str, default=None, + help="CN for generated SSL certs. Default: %s"%pathod.DEFAULT_CERT_DOMAIN + ) + group.add_argument( + "-C", dest='ssl_not_after_connect', default=False, action="store_true", + help="Don't expect SSL after a CONNECT request." ) group.add_argument( "--certfile", dest='ssl_certfile', default=None, type=str, @@ -181,7 +183,7 @@ if __name__ == "__main__": group.add_argument( "--sslversion", dest="sslversion", type=int, default=4, choices=[1, 2, 3, 4], - help="Use a specified protocol - TLSv1, SSLv2, SSLv3, SSLv23. Default to SSLv23." + help="Use a specified protocol - TLSv1, SSLv2, SSLv3, SSLv23. Default to SSLv23." ) group = parser.add_argument_group( -- cgit v1.2.3 From 0177eb899a87995d0faaed8a836904cac7f844ce Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 2 Mar 2014 15:56:36 +1300 Subject: Support cert/key combo files in args. Improve argument names in SSLOptions --- pathod | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index 5b82f97e..d150eac0 100755 --- a/pathod +++ b/pathod @@ -35,6 +35,7 @@ def main(parser, args): cn = args.cn, confdir = args.confdir, certfile = args.ssl_certfile, + keyfile = args.ssl_keyfile or args.ssl_certfile, not_after_connect = args.ssl_not_after_connect, ciphers = args.ciphers, sslversion = utils.SSLVERSIONS[args.sslversion] @@ -174,7 +175,11 @@ if __name__ == "__main__": ) group.add_argument( "--certfile", dest='ssl_certfile', default=None, type=str, - help='SSL cert file. If not specified, a default cert is used.' + help='SSL certificate in PEM format, optionally with the key in the same file.' + ) + group.add_argument( + "--keyfile", dest='ssl_keyfile', default=None, type=str, + help='Key matching certfile.' ) group.add_argument( "--ciphers", dest="ciphers", type=str, default=False, -- cgit v1.2.3 From e54bf1a804d4f93f2f3750ba9491934b3f44fc7d Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 5 Mar 2014 15:03:31 +1300 Subject: Adjust for upstream cert store changes, improve cert handling significantly --- pathod | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index d150eac0..2e9fafc4 100755 --- a/pathod +++ b/pathod @@ -31,14 +31,23 @@ def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): def main(parser, args): + certs = [] + for i in args.ssl_certs: + parts = i.split("=", 1) + if len(parts) == 1: + parts = ["*", parts[0]] + parts[1] = os.path.expanduser(parts[1]) + if not os.path.exists(parts[1]): + parser.error("Certificate file does not exist: %s"%parts[1]) + certs.append(parts) + ssloptions = pathod.SSLOptions( cn = args.cn, confdir = args.confdir, - certfile = args.ssl_certfile, - keyfile = args.ssl_keyfile or args.ssl_certfile, not_after_connect = args.ssl_not_after_connect, ciphers = args.ciphers, - sslversion = utils.SSLVERSIONS[args.sslversion] + sslversion = utils.SSLVERSIONS[args.sslversion], + certs = certs ) alst = [] @@ -174,12 +183,12 @@ if __name__ == "__main__": help="Don't expect SSL after a CONNECT request." ) group.add_argument( - "--certfile", dest='ssl_certfile', default=None, type=str, - help='SSL certificate in PEM format, optionally with the key in the same file.' - ) - group.add_argument( - "--keyfile", dest='ssl_keyfile', default=None, type=str, - help='Key matching certfile.' + "--cert", dest='ssl_certs', default=[], type=str, + metavar = "SPEC", action="append", + help='Add an SSL certificate. SPEC is of the form "[domain=]path". '\ + 'The domain may include a wildcard, and is equal to "*" if not specified. '\ + 'The file at path is a certificate in PEM format. If a private key is included in the PEM, '\ + 'it is used, else the default key in the conf dir is used. Can be passed multiple times.' ) group.add_argument( "--ciphers", dest="ciphers", type=str, default=False, @@ -218,7 +227,6 @@ if __name__ == "__main__": "-x", dest="hexdump", action="store_true", default=False, help="Log request/response in hexdump format" ) - args = parser.parse_args() if args.daemonize: daemonize() -- cgit v1.2.3 From 658a56a1ac74f42c1dc0903d3092335a5b851382 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Sun, 31 Aug 2014 02:09:04 +0200 Subject: use setuptools entrypoints rather than scripts --- pathod | 234 ----------------------------------------------------------------- 1 file changed, 234 deletions(-) delete mode 100755 pathod (limited to 'pathod') diff --git a/pathod b/pathod deleted file mode 100755 index 2e9fafc4..00000000 --- a/pathod +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/env python -import argparse, sys, logging, logging.handlers -import os -from libpathod import pathod, utils, version, language - - -def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): - try: - pid = os.fork() - if pid > 0: - sys.exit(0) - except OSError, e: - sys.stderr.write ("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror) ) - sys.exit(1) - os.chdir("/") - os.umask(0) - os.setsid() - try: - pid = os.fork() - if pid > 0: - sys.exit(0) - except OSError, e: - sys.stderr.write ("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) ) - sys.exit(1) - si = open(stdin, 'rb') - so = open(stdout, 'a+b') - se = open(stderr, 'a+b', 0) - os.dup2(si.fileno(), sys.stdin.fileno()) - os.dup2(so.fileno(), sys.stdout.fileno()) - os.dup2(se.fileno(), sys.stderr.fileno()) - - -def main(parser, args): - certs = [] - for i in args.ssl_certs: - parts = i.split("=", 1) - if len(parts) == 1: - parts = ["*", parts[0]] - parts[1] = os.path.expanduser(parts[1]) - if not os.path.exists(parts[1]): - parser.error("Certificate file does not exist: %s"%parts[1]) - certs.append(parts) - - ssloptions = pathod.SSLOptions( - cn = args.cn, - confdir = args.confdir, - not_after_connect = args.ssl_not_after_connect, - ciphers = args.ciphers, - sslversion = utils.SSLVERSIONS[args.sslversion], - certs = certs - ) - - alst = [] - for i in args.anchors: - parts = utils.parse_anchor_spec(i) - if not parts: - parser.error("Invalid anchor specification: %s"%i) - alst.append(parts) - - root = logging.getLogger() - if root.handlers: - for handler in root.handlers: - root.removeHandler(handler) - - log = logging.getLogger('pathod') - log.setLevel(logging.DEBUG) - fmt = logging.Formatter( - '%(asctime)s: %(message)s', - datefmt='%d-%m-%y %H:%M:%S', - ) - if args.logfile: - fh = logging.handlers.WatchedFileHandler(args.logfile) - fh.setFormatter(fmt) - log.addHandler(fh) - if not args.daemonize: - sh = logging.StreamHandler() - sh.setFormatter(fmt) - log.addHandler(sh) - - sizelimit = None - if args.sizelimit: - try: - sizelimit = utils.parse_size(args.sizelimit) - except ValueError, v: - parser.error(v) - - try: - pd = pathod.Pathod( - (args.address, args.port), - craftanchor = args.craftanchor, - ssl = args.ssl, - ssloptions = ssloptions, - staticdir = args.staticdir, - anchors = alst, - sizelimit = sizelimit, - noweb = args.noweb, - nocraft = args.nocraft, - noapi = args.noapi, - nohang = args.nohang, - timeout = args.timeout, - logreq = args.logreq, - logresp = args.logresp, - hexdump = args.hexdump, - explain = args.explain, - ) - except pathod.PathodError, v: - parser.error(str(v)) - except language.FileAccessDenied, v: - parser.error("%s You probably want to a -d argument."%str(v)) - - try: - print "%s listening on %s:%s"%(version.NAMEVERSION, pd.address.host, pd.address.port) - pd.serve_forever() - except KeyboardInterrupt: - pass - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='A pathological HTTP/S daemon.') - parser.add_argument('--version', action='version', version="pathod " + version.VERSION) - parser.add_argument("-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port.') - parser.add_argument("-l", dest='address', default="127.0.0.1", type=str, help='Listening address.') - parser.add_argument( - "-a", dest='anchors', default=[], type=str, action="append", metavar="ANCHOR", - help='Add an anchor. Specified as a string with the form pattern=pagespec' - ) - parser.add_argument( - "-c", dest='craftanchor', default="/p/", type=str, - help='Anchorpoint for URL crafting commands.' - ) - parser.add_argument( - "--confdir", - action="store", type = str, dest="confdir", default='~/.mitmproxy', - help = "Configuration directory. (~/.mitmproxy)" - ) - parser.add_argument( - "-d", dest='staticdir', default=None, type=str, - help='Directory for static files.' - ) - parser.add_argument( - "-D", dest='daemonize', default=False, action="store_true", - help='Daemonize.' - ) - parser.add_argument( - "-t", dest="timeout", type=int, default=None, - help="Connection timeout" - ) - parser.add_argument( - "--limit-size", dest='sizelimit', default=None, type=str, - help='Size limit of served responses. Understands size suffixes, i.e. 100k.' - ) - parser.add_argument( - "--noapi", dest='noapi', default=False, action="store_true", - help='Disable API.' - ) - parser.add_argument( - "--nohang", dest='nohang', default=False, action="store_true", - help='Disable pauses during crafted response generation.' - ) - parser.add_argument( - "--noweb", dest='noweb', default=False, action="store_true", - help='Disable both web interface and API.' - ) - parser.add_argument( - "--nocraft", dest='nocraft', default=False, action="store_true", - help='Disable response crafting. If anchors are specified, they still work.' - ) - - - group = parser.add_argument_group( - 'SSL', - ) - group.add_argument( - "-s", dest='ssl', default=False, action="store_true", - help='Run in HTTPS mode.' - ) - group.add_argument( - "--cn", dest="cn", type=str, default=None, - help="CN for generated SSL certs. Default: %s"%pathod.DEFAULT_CERT_DOMAIN - ) - group.add_argument( - "-C", dest='ssl_not_after_connect', default=False, action="store_true", - help="Don't expect SSL after a CONNECT request." - ) - group.add_argument( - "--cert", dest='ssl_certs', default=[], type=str, - metavar = "SPEC", action="append", - help='Add an SSL certificate. SPEC is of the form "[domain=]path". '\ - 'The domain may include a wildcard, and is equal to "*" if not specified. '\ - 'The file at path is a certificate in PEM format. If a private key is included in the PEM, '\ - 'it is used, else the default key in the conf dir is used. Can be passed multiple times.' - ) - group.add_argument( - "--ciphers", dest="ciphers", type=str, default=False, - help="SSL cipher specification" - ) - group.add_argument( - "--sslversion", dest="sslversion", type=int, default=4, - choices=[1, 2, 3, 4], - help="Use a specified protocol - TLSv1, SSLv2, SSLv3, SSLv23. Default to SSLv23." - ) - - group = parser.add_argument_group( - 'Controlling Logging', - """ - Some of these options expand generated values for logging - if - you're generating large data, use them with caution. - """ - ) - group.add_argument( - "-e", dest="explain", action="store_true", default=False, - help="Explain responses" - ) - group.add_argument( - "-f", dest='logfile', default=None, type=str, - help='Log to file.' - ) - group.add_argument( - "-q", dest="logreq", action="store_true", default=False, - help="Log full request" - ) - group.add_argument( - "-r", dest="logresp", action="store_true", default=False, - help="Log full response" - ) - group.add_argument( - "-x", dest="hexdump", action="store_true", default=False, - help="Log request/response in hexdump format" - ) - args = parser.parse_args() - if args.daemonize: - daemonize() - main(parser, args) - -- cgit v1.2.3 From 962a414327d93b604a59a4b8c8582d359745009d Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 24 Oct 2014 14:01:34 +1300 Subject: Fix tests, re-add scripts --- pathod | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 pathod (limited to 'pathod') diff --git a/pathod b/pathod new file mode 100755 index 00000000..2c9700a7 --- /dev/null +++ b/pathod @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from libpathod import main + +if __name__ == "__main__": + main.pathod() -- cgit v1.2.3 From cd481fdd14a96afeb61ce5d2b8d899f24af1051f Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 24 Oct 2014 17:12:54 +1300 Subject: Refactor and whitespace --- pathod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pathod') diff --git a/pathod b/pathod index 2c9700a7..ca0baa57 100755 --- a/pathod +++ b/pathod @@ -1,5 +1,5 @@ #!/usr/bin/env python -from libpathod import main +from libpathod import cmdline if __name__ == "__main__": - main.pathod() + cmdline.go_pathod() -- cgit v1.2.3 From 18a4456397d0b4b1275ac2c8ab393d041176e949 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 8 Jun 2015 16:03:33 +0200 Subject: refactor cmdline tests --- pathod | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod b/pathod index ca0baa57..a79becf1 100755 --- a/pathod +++ b/pathod @@ -1,5 +1,6 @@ #!/usr/bin/env python -from libpathod import cmdline + +from libpathod import pathod_cmdline as cmdline if __name__ == "__main__": cmdline.go_pathod() -- cgit v1.2.3 From 95cef3c0e965202a36841a36c189d3917d7706ec Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 15 Feb 2016 15:43:59 +0100 Subject: merge metadata files --- pathod/.appveyor.yml | 11 ------- pathod/.env | 6 ---- pathod/.gitignore | 15 ---------- pathod/.landscape.yml | 16 ----------- pathod/.travis.yml | 70 --------------------------------------------- pathod/CONTRIBUTORS | 6 ---- pathod/LICENSE | 19 ------------ pathod/libpathod/version.py | 10 +------ pathod/release/pathoc.spec | 22 -------------- pathod/release/pathod.spec | 22 -------------- pathod/requirements.txt | 2 -- 11 files changed, 1 insertion(+), 198 deletions(-) delete mode 100644 pathod/.appveyor.yml delete mode 100644 pathod/.env delete mode 100644 pathod/.gitignore delete mode 100644 pathod/.landscape.yml delete mode 100644 pathod/.travis.yml delete mode 100644 pathod/CONTRIBUTORS delete mode 100644 pathod/LICENSE delete mode 100644 pathod/release/pathoc.spec delete mode 100644 pathod/release/pathod.spec delete mode 100644 pathod/requirements.txt (limited to 'pathod') diff --git a/pathod/.appveyor.yml b/pathod/.appveyor.yml deleted file mode 100644 index dbb6d2fa..00000000 --- a/pathod/.appveyor.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: '{build}' -shallow_clone: true -environment: - matrix: - - PYTHON: "C:\\Python27" -install: - - "%PYTHON%\\Scripts\\pip install --src . -r requirements.txt" - - "%PYTHON%\\python -c \"from OpenSSL import SSL; print(SSL.SSLeay_version(SSL.SSLEAY_VERSION))\"" -build: off # Not a C# project -test_script: - - "%PYTHON%\\Scripts\\py.test -n 4" \ No newline at end of file diff --git a/pathod/.env b/pathod/.env deleted file mode 100644 index 69ac3f05..00000000 --- a/pathod/.env +++ /dev/null @@ -1,6 +0,0 @@ -DIR="$( dirname "${BASH_SOURCE[0]}" )" -ACTIVATE_DIR="$(if [ -f "$DIR/../venv.mitmproxy/bin/activate" ]; then echo 'bin'; else echo 'Scripts'; fi;)" -if [ -z "$VIRTUAL_ENV" ] && [ -f "$DIR/../venv.mitmproxy/$ACTIVATE_DIR/activate" ]; then - echo "Activating mitmproxy virtualenv..." - source "$DIR/../venv.mitmproxy/$ACTIVATE_DIR/activate" -fi diff --git a/pathod/.gitignore b/pathod/.gitignore deleted file mode 100644 index 7eeeb614..00000000 --- a/pathod/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# Python object files -*.py[cd] -MANIFEST -/build -/dist -# Vim swap files -*.swp -/doc -.coverage -.noseids -netlib -venv -.idea/ -pathod.egg-info/ -.cache/ \ No newline at end of file diff --git a/pathod/.landscape.yml b/pathod/.landscape.yml deleted file mode 100644 index 9a3b615f..00000000 --- a/pathod/.landscape.yml +++ /dev/null @@ -1,16 +0,0 @@ -max-line-length: 120 -pylint: - options: - dummy-variables-rgx: _$|.+_$|dummy_.+ - - disable: - - missing-docstring - - protected-access - - too-few-public-methods - - too-many-arguments - - too-many-instance-attributes - - too-many-locals - - too-many-public-methods - - too-many-return-statements - - too-many-statements - - unpacking-non-sequence \ No newline at end of file diff --git a/pathod/.travis.yml b/pathod/.travis.yml deleted file mode 100644 index 92634df7..00000000 --- a/pathod/.travis.yml +++ /dev/null @@ -1,70 +0,0 @@ -sudo: false -language: python - -matrix: - fast_finish: true - include: - - python: 2.7 - - python: 2.7 - env: OPENSSL=1.0.2 - addons: - apt: - sources: - # Debian sid currently holds OpenSSL 1.0.2 - # change this with future releases! - - debian-sid - packages: - - libssl-dev - - python: pypy - - python: pypy - env: OPENSSL=1.0.2 - addons: - apt: - sources: - # Debian sid currently holds OpenSSL 1.0.2 - # change this with future releases! - - debian-sid - packages: - - libssl-dev - allow_failures: - # We allow pypy to fail until Travis fixes their infrastructure to a pypy - # with a recent enought CFFI library to run cryptography 1.0+. - - python: pypy - -install: - - "pip install --src . -r requirements.txt" - -before_script: - - "openssl version -a" - -script: - - "py.test --cov libpathod -v" - -after_success: - - coveralls - -notifications: - irc: - channels: - - "irc.oftc.net#mitmproxy" - on_success: change - on_failure: always - slack: - rooms: - - mitmproxy:YaDGC9Gt9TEM7o8zkC2OLNsu#ci - on_success: always - on_failure: always - -# exclude cryptography from cache -# it depends on libssl-dev version -# which needs to be compiled specifically to each version -before_cache: - - pip uninstall -y cryptography - -cache: - directories: - - $HOME/.cache/pip - - /home/travis/virtualenv/python2.7.9/lib/python2.7/site-packages - - /home/travis/virtualenv/python2.7.9/bin - - /home/travis/virtualenv/pypy-2.5.0/site-packages - - /home/travis/virtualenv/pypy-2.5.0/bin diff --git a/pathod/CONTRIBUTORS b/pathod/CONTRIBUTORS deleted file mode 100644 index ab76a35c..00000000 --- a/pathod/CONTRIBUTORS +++ /dev/null @@ -1,6 +0,0 @@ - 426 Aldo Cortesi - 74 Maximilian Hils - 50 Thomas Kriechbaumer - 1 Felix Yan - 1 requires.io - 1 starenka diff --git a/pathod/LICENSE b/pathod/LICENSE deleted file mode 100644 index 908aa13f..00000000 --- a/pathod/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2008, Aldo Cortesi. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/pathod/libpathod/version.py b/pathod/libpathod/version.py index b99ae40b..63f60a8d 100644 --- a/pathod/libpathod/version.py +++ b/pathod/libpathod/version.py @@ -1,11 +1,3 @@ from __future__ import (absolute_import, print_function, division) -IVERSION = (0, 17) -VERSION = ".".join(str(i) for i in IVERSION) -MINORVERSION = ".".join(str(i) for i in IVERSION[:2]) -NAME = "pathod" -NAMEVERSION = NAME + " " + VERSION - -NEXT_MINORVERSION = list(IVERSION) -NEXT_MINORVERSION[1] += 1 -NEXT_MINORVERSION = ".".join(str(i) for i in NEXT_MINORVERSION[:2]) +from netlib.version import * \ No newline at end of file diff --git a/pathod/release/pathoc.spec b/pathod/release/pathoc.spec deleted file mode 100644 index 22649076..00000000 --- a/pathod/release/pathoc.spec +++ /dev/null @@ -1,22 +0,0 @@ -# -*- mode: python -*- - -from PyInstaller.utils.hooks import collect_data_files - -a = Analysis(['../pathoc'], - binaries=None, - datas=None, - hiddenimports=['_cffi_backend'], - hookspath=None, - runtime_hooks=None, - excludes=None) -pyz = PYZ(a.pure, a.zipped_data) -exe = EXE(pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, - name='pathoc', - debug=False, - strip=None, - upx=True, - console=True ) diff --git a/pathod/release/pathod.spec b/pathod/release/pathod.spec deleted file mode 100644 index 706b6b68..00000000 --- a/pathod/release/pathod.spec +++ /dev/null @@ -1,22 +0,0 @@ -# -*- mode: python -*- - -from PyInstaller.utils.hooks import collect_data_files - -a = Analysis(['../pathod'], - binaries=None, - datas=collect_data_files("libpathod"), - hiddenimports=['_cffi_backend'], - hookspath=None, - runtime_hooks=None, - excludes=None) -pyz = PYZ(a.pure, a.zipped_data) -exe = EXE(pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, - name='pathod', - debug=False, - strip=None, - upx=True, - console=True ) diff --git a/pathod/requirements.txt b/pathod/requirements.txt deleted file mode 100644 index 69bd183b..00000000 --- a/pathod/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ --e git+https://github.com/mitmproxy/netlib.git#egg=netlib --e .[dev] \ No newline at end of file -- cgit v1.2.3 From d7158f975e671b78f0a064dd873cfa7805667528 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 15 Feb 2016 16:34:22 +0100 Subject: move tests into shared folder --- pathod/test/data/clientcert/.gitignore | 3 - pathod/test/data/clientcert/client.cnf | 5 - pathod/test/data/clientcert/client.pem | 42 ---- pathod/test/data/clientcert/make | 8 - pathod/test/data/file | 1 - pathod/test/data/request | 1 - pathod/test/data/response | 1 - pathod/test/data/testkey.pem | 68 ------ pathod/test/scripts/generate.sh | 17 -- pathod/test/scripts/openssl.cnf | 39 ---- pathod/test/test_app.py | 85 -------- pathod/test/test_language_actions.py | 135 ------------ pathod/test/test_language_base.py | 352 ------------------------------- pathod/test/test_language_generators.py | 42 ---- pathod/test/test_language_http.py | 358 -------------------------------- pathod/test/test_language_http2.py | 233 --------------------- pathod/test/test_language_websocket.py | 142 ------------- pathod/test/test_language_writer.py | 91 -------- pathod/test/test_log.py | 25 --- pathod/test/test_pathoc.py | 308 --------------------------- pathod/test/test_pathoc_cmdline.py | 59 ------ pathod/test/test_pathod.py | 289 -------------------------- pathod/test/test_pathod_cmdline.py | 85 -------- pathod/test/test_test.py | 45 ---- pathod/test/test_utils.py | 39 ---- pathod/test/tutils.py | 128 ------------ 26 files changed, 2601 deletions(-) delete mode 100644 pathod/test/data/clientcert/.gitignore delete mode 100644 pathod/test/data/clientcert/client.cnf delete mode 100644 pathod/test/data/clientcert/client.pem delete mode 100755 pathod/test/data/clientcert/make delete mode 100644 pathod/test/data/file delete mode 100644 pathod/test/data/request delete mode 100644 pathod/test/data/response delete mode 100644 pathod/test/data/testkey.pem delete mode 100755 pathod/test/scripts/generate.sh delete mode 100644 pathod/test/scripts/openssl.cnf delete mode 100644 pathod/test/test_app.py delete mode 100644 pathod/test/test_language_actions.py delete mode 100644 pathod/test/test_language_base.py delete mode 100644 pathod/test/test_language_generators.py delete mode 100644 pathod/test/test_language_http.py delete mode 100644 pathod/test/test_language_http2.py delete mode 100644 pathod/test/test_language_websocket.py delete mode 100644 pathod/test/test_language_writer.py delete mode 100644 pathod/test/test_log.py delete mode 100644 pathod/test/test_pathoc.py delete mode 100644 pathod/test/test_pathoc_cmdline.py delete mode 100644 pathod/test/test_pathod.py delete mode 100644 pathod/test/test_pathod_cmdline.py delete mode 100644 pathod/test/test_test.py delete mode 100644 pathod/test/test_utils.py delete mode 100644 pathod/test/tutils.py (limited to 'pathod') diff --git a/pathod/test/data/clientcert/.gitignore b/pathod/test/data/clientcert/.gitignore deleted file mode 100644 index 07bc53d2..00000000 --- a/pathod/test/data/clientcert/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -client.crt -client.key -client.req diff --git a/pathod/test/data/clientcert/client.cnf b/pathod/test/data/clientcert/client.cnf deleted file mode 100644 index 5046a944..00000000 --- a/pathod/test/data/clientcert/client.cnf +++ /dev/null @@ -1,5 +0,0 @@ -[ ssl_client ] -basicConstraints = CA:FALSE -nsCertType = client -keyUsage = digitalSignature, keyEncipherment -extendedKeyUsage = clientAuth diff --git a/pathod/test/data/clientcert/client.pem b/pathod/test/data/clientcert/client.pem deleted file mode 100644 index 4927bca2..00000000 --- a/pathod/test/data/clientcert/client.pem +++ /dev/null @@ -1,42 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAzCpoRjSTfIN24kkNap/GYmP9zVWj0Gk8R5BB/PvvN0OB1Zk0 -EEYPsWCcuhEdK0ehiDZX030doF0DOncKKa6mop/d0x2o+ts42peDhZM6JNUrm6d+ -ZWQVtio33mpp77UMhR093vaA+ExDnmE26kBTVijJ1+fRAVDXG/cmQINEri91Kk/G -3YJ5e45UrohGI5seBZ4vV0xbHtmczFRhYFlGOvYsoIe4Lvz/eFS2pIrTIpYQ2VM/ -SQQl+JFy+NlQRsWG2NrxtKOzMnnDE7YN4I3z5D5eZFo1EtwZ48LNCeSwrEOdfuzP -G5q5qbs5KpE/x85H9umuRwSCIArbMwBYV8a8JwIDAQABAoIBAFE3FV/IDltbmHEP -iky93hbJm+6QgKepFReKpRVTyqb7LaygUvueQyPWQMIriKTsy675nxo8DQr7tQsO -y3YlSZgra/xNMikIB6e82c7K8DgyrDQw/rCqjZB3Xt4VCqsWJDLXnQMSn98lx0g7 -d7Lbf8soUpKWXqfdVpSDTi4fibSX6kshXyfSTpcz4AdoncEpViUfU1xkEEmZrjT8 -1GcCsDC41xdNmzCpqRuZX7DKSFRoB+0hUzsC1oiqM7FD5kixonRd4F5PbRXImIzt -6YCsT2okxTA04jX7yByis7LlOLTlkmLtKQYuc3erOFvwx89s4vW+AeFei+GGNitn -tHfSwbECgYEA7SzV+nN62hAERHlg8cEQT4TxnsWvbronYWcc/ev44eHSPDWL5tPi -GHfSbW6YAq5Wa0I9jMWfXyhOYEC3MZTC5EEeLOB71qVrTwcy/sY66rOrcgjFI76Q -5JFHQ4wy3SWU50KxE0oWJO9LIowprG+pW1vzqC3VF0T7q0FqESrY4LUCgYEA3F7Z -80ndnCUlooJAb+Hfotv7peFf1o6+m1PTRcz1lLnVt5R5lXj86kn+tXEpYZo1RiGR -2rE2N0seeznWCooakHcsBN7/qmFIhhooJNF7yW+JP2I4P2UV5+tJ+8bcs/voUkQD -1x+rGOuMn8nvHBd2+Vharft8eGL2mgooPVI2XusCgYEAlMZpO3+w8pTVeHaDP2MR -7i/AuQ3cbCLNjSX3Y7jgGCFllWspZRRIYXzYPNkA9b2SbBnTLjjRLgnEkFBIGgvs -7O2EFjaCuDRvydUEQhjq4ErwIsopj7B8h0QyZcbOKTbn3uFQ3n68wVJx2Sv/ADHT -FIHrp/WIE96r19Niy34LKXkCgYB2W59VsuOKnMz01l5DeR5C+0HSWxS9SReIl2IO -yEFSKullWyJeLIgyUaGy0990430feKI8whcrZXYumuah7IDN/KOwzhCk8vEfzWao -N7bzfqtJVrh9HA7C7DVlO+6H4JFrtcoWPZUIomJ549w/yz6EN3ckoMC+a/Ck1TW9 -ka1QFwKBgQCywG6TrZz0UmOjyLQZ+8Q4uvZklSW5NAKBkNnyuQ2kd5rzyYgMPE8C -Er8T88fdVIKvkhDyHhwcI7n58xE5Gr7wkwsrk/Hbd9/ZB2GgAPY3cATskK1v1McU -YeX38CU0fUS4aoy26hWQXkViB47IGQ3jWo3ZCtzIJl8DI9/RsBWTnw== ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIICYDCCAckCAQEwDQYJKoZIhvcNAQEFBQAwKDESMBAGA1UEAxMJbWl0bXByb3h5 -MRIwEAYDVQQKEwltaXRtcHJveHkwHhcNMTMwMTIwMDEwODEzWhcNMTUxMDE3MDEw -ODEzWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UE -ChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAzCpoRjSTfIN24kkNap/GYmP9zVWj0Gk8R5BB/PvvN0OB1Zk0 -EEYPsWCcuhEdK0ehiDZX030doF0DOncKKa6mop/d0x2o+ts42peDhZM6JNUrm6d+ -ZWQVtio33mpp77UMhR093vaA+ExDnmE26kBTVijJ1+fRAVDXG/cmQINEri91Kk/G -3YJ5e45UrohGI5seBZ4vV0xbHtmczFRhYFlGOvYsoIe4Lvz/eFS2pIrTIpYQ2VM/ -SQQl+JFy+NlQRsWG2NrxtKOzMnnDE7YN4I3z5D5eZFo1EtwZ48LNCeSwrEOdfuzP -G5q5qbs5KpE/x85H9umuRwSCIArbMwBYV8a8JwIDAQABMA0GCSqGSIb3DQEBBQUA -A4GBAFvI+cd47B85PQ970n2dU/PlA2/Hb1ldrrXh2guR4hX6vYx/uuk5yRI/n0Rd -KOXJ3czO0bd2Fpe3ZoNpkW0pOSDej/Q+58ScuJd0gWCT/Sh1eRk6ZdC0kusOuWoY -bPOPMkG45LPgUMFOnZEsfJP6P5mZIxlbCvSMFC25nPHWlct7 ------END CERTIFICATE----- diff --git a/pathod/test/data/clientcert/make b/pathod/test/data/clientcert/make deleted file mode 100755 index d1caea81..00000000 --- a/pathod/test/data/clientcert/make +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -openssl genrsa -out client.key 2048 -openssl req -key client.key -new -out client.req -openssl x509 -req -days 365 -in client.req -signkey client.key -out client.crt -extfile client.cnf -extensions ssl_client -openssl x509 -req -days 1000 -in client.req -CA ~/.mitmproxy/mitmproxy-ca.pem -CAkey ~/.mitmproxy/mitmproxy-ca.pem -set_serial 00001 -out client.crt -extensions ssl_client -cat client.key client.crt > client.pem -openssl x509 -text -noout -in client.pem diff --git a/pathod/test/data/file b/pathod/test/data/file deleted file mode 100644 index 26918572..00000000 --- a/pathod/test/data/file +++ /dev/null @@ -1 +0,0 @@ -testfile diff --git a/pathod/test/data/request b/pathod/test/data/request deleted file mode 100644 index c4c90e76..00000000 --- a/pathod/test/data/request +++ /dev/null @@ -1 +0,0 @@ -get:/foo diff --git a/pathod/test/data/response b/pathod/test/data/response deleted file mode 100644 index 8f897c85..00000000 --- a/pathod/test/data/response +++ /dev/null @@ -1 +0,0 @@ -202 diff --git a/pathod/test/data/testkey.pem b/pathod/test/data/testkey.pem deleted file mode 100644 index b804bd4c..00000000 --- a/pathod/test/data/testkey.pem +++ /dev/null @@ -1,68 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIG5QIBAAKCAYEAwvtKxoZvBV2AxPAkCx8PXbuE7KeqK9bBvk8x+JchPMdf/KZj -sdu2v6Gm8Hi053i7ZGxouFvonJxHAiK6cwk9OYQwa9fbOFf2mgWKEBO4fbCH93tW -DCTdWVxFyNViAvxGHlJs3/IU03pIG29AgUnhRW8pGbabAfx8emcOZJZ3ykEuimaC -4s7mRwdc63GXnbcjTtRkrJsBATI+xvPwuR2+4daX7sPCf0kel3bN2jMpwXfvk/Ww -kJ2BIEeZCg0qIvyMjH9qrUirUnsmQnpPln0CGBbQEBsW9yMfGoFdREiMYls5jZeq -NxjWNv1RTRIm/4RjMwyxnoTA9eDS9wwO2NnJS4vfXAnUTP4BYx8Pe4ZMA2Gm6YrC -ysT6YA1xdHNpcuHXClxwmPj/cm8Z5kIg5clbNIK60ts9yFr/Ao3KPPYJ2GBv8/Oe -ApPBJuubews+/9/13Ew/SJ1t2u28+sPbgXUG8dC2n4vWTvJwKf6Duqxgnm82zdzj -SZoXRQsP984qiN7NAgMBAAECggGBALB6rqWdzCL5DLI0AQun40qdjaR95UKksNvF -5p7we379nl2ZZKb5DSHJ+MWzG1pfJo2wqeAkIBiQQp0mPcgdVrMWeJVD3QHUbDng -RaRjlRr+izJvCeUYANj+8ZLjwECfgf+z7yOLg1oeVeGvAp2C90jXYkYJx6c2lpxb -ZuWYY3hHIw7V1iXfywIDIhFg0TBJMMYK68xmx7QDfFqrNPj4eWsDxqSvvv1iezPw -rkWPBX49RjWPrW5XgSZsZ5J3c+oS1rZmIY7EAgopTWB/3wJjZR1Idz/9l9LIWlBP -6zVC27CIZzSEeGguqNVeyzJ0TPWh5idYNRmSZr6eTUF0245LNO/gqvWKgRSNIZko -HoBa2F1AvCiB67S1kxjwS5y3VkudZE4jkgGKcC2Ws/9QmOZ0HAsjI8VAMp2hj6iN -0HdPMTNtsLgbhKyXsoZuW4YmwfSTPxGi2gvcI7GUozpTz84n1cOneJnz1ygx6Uru -v8DpQg+VX6xTy4X6AK1F8OYNMZ/jaQKBwQDv30NevQStnGbTmcSr+0fd4rmWFklK -V6B2X7zWynVpSGvCWkqVSp3mG6aiZItAltVMRL/9LT6zIheyClyd+vXIjR2+W210 -XMxrvz7A8qCXkvB2dyEhrMdCfZ7p8+kf+eD2c/Mnxb7VpmDfHYLx30JeQoBwjrwU -Eul+dE1P+r8bWBaLTjlsipTya74yItWWAToXAo+s1BXBtXhEsLoe4FghlC0u724d -ucjDaeICdLcerApdvg6Q6p4kVHaoF6ka6I8CgcEA0Bdc05ery9gLC6CclV+BhA5Q -dfDq2P7qhc7e1ipwNRrQo2gy5HhgOkTL3dJWc+8rV6CBP/JfchnsW40tDOnPCTLT -gg3n7vv3RHrtncApXuhIFR+B5xjohTPBzxRUMiAOre2d0F5b6eBXFjptf/1i2tQ+ -qdqJoyOGOZP0hKVslGIfz+CKc6WEkIqX7c91Msdr5myeaWDI5TsurfuKRBH395T3 -BMAi6oinAAEb1rdySenLO2A/0kVmBVlTpaN3TNjjAoHBAMvS4uQ1qSv8okNbfgrF -UqPwa9JkzZImM2tinovFLU9xAl/7aTTCWrmU9Vs4JDuV71kHcjwnngeJCKl4tIpp -HUB06Lk/5xnhYLKNpz087cjeSwXe5IBA2HBfXhFd+NH6+nVwwUUieq4A2n+8C/CK -zVJbH9iE8Lv99fpFyQwU/R63EzD8Hz9j4ny7oLnpb6QvFrVGr98jt/kJwlBb+0sR -RtIBnwMq4F7R5w5lgm6jzpZ5ibVuMeJh+k7Ulp7uu/rpcQKBwQDE3sWIvf7f7PaO -OpbJz0CmYjCHVLWrNIlGrPAv6Jid9U+cuXEkrCpGFl5V77CxIH59+bEuga0BMztl -ZkxP4khoqHhom6VpeWJ3nGGAFJRPYS0JJvTsYalilBPxSYdaoO+iZ6MdxpfozcE2 -m3KLW3uSEqlyYvpCqNJNWQhGEoeGXstADWyPevHPGgAhElwL/ZW8u9inU9Tc4sAI -BGnMer+BsaJ+ERU3lK+Clony+z2aZiFLfIUE93lM6DT2CZBN2QcCgcAVk4L0bfA6 -HFnP/ZWNlnYWpOVFKcq57PX+J5/k7Tf34e2cYM2P0eqYggWZbzVd8qoCOQCHrAx0 -aZSSvEyKAVvzRNeqbm1oXaMojksMnrSX5henHjPbZlr1EmM7+zMnSTMkfVOx/6g1 -97sASej31XdOAgKCBJGymrwvYrCLW+P5cHqd+D8v/PvfpRIQM54p5ixRt3EYZvtR -zGrzsr0OGyOLZtj1DB0a3kvajAAOCl3TawJSzviKo2mwc+/xj28MCQM= ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIE4TCCA0mgAwIBAgIJALONCAWZxPhUMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV -BAYTAk5aMQ4wDAYDVQQIDAVPdGFnbzEPMA0GA1UECgwGUGF0aG9kMREwDwYDVQQD -DAh0ZXN0LmNvbTAeFw0xNTA0MTgyMjA0NTNaFw00MjA5MDIyMjA0NTNaMEExCzAJ -BgNVBAYTAk5aMQ4wDAYDVQQIDAVPdGFnbzEPMA0GA1UECgwGUGF0aG9kMREwDwYD -VQQDDAh0ZXN0LmNvbTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAML7 -SsaGbwVdgMTwJAsfD127hOynqivWwb5PMfiXITzHX/ymY7Hbtr+hpvB4tOd4u2Rs -aLhb6JycRwIiunMJPTmEMGvX2zhX9poFihATuH2wh/d7Vgwk3VlcRcjVYgL8Rh5S -bN/yFNN6SBtvQIFJ4UVvKRm2mwH8fHpnDmSWd8pBLopmguLO5kcHXOtxl523I07U -ZKybAQEyPsbz8LkdvuHWl+7Dwn9JHpd2zdozKcF375P1sJCdgSBHmQoNKiL8jIx/ -aq1Iq1J7JkJ6T5Z9AhgW0BAbFvcjHxqBXURIjGJbOY2XqjcY1jb9UU0SJv+EYzMM -sZ6EwPXg0vcMDtjZyUuL31wJ1Ez+AWMfD3uGTANhpumKwsrE+mANcXRzaXLh1wpc -cJj4/3JvGeZCIOXJWzSCutLbPcha/wKNyjz2Cdhgb/PzngKTwSbrm3sLPv/f9dxM -P0idbdrtvPrD24F1BvHQtp+L1k7ycCn+g7qsYJ5vNs3c40maF0ULD/fOKojezQID -AQABo4HbMIHYMAsGA1UdDwQEAwIFoDAdBgNVHQ4EFgQUbEgfTauEqEP/bnBtby1K -bihJvcswcQYDVR0jBGowaIAUbEgfTauEqEP/bnBtby1KbihJvcuhRaRDMEExCzAJ -BgNVBAYTAk5aMQ4wDAYDVQQIDAVPdGFnbzEPMA0GA1UECgwGUGF0aG9kMREwDwYD -VQQDDAh0ZXN0LmNvbYIJALONCAWZxPhUMAwGA1UdEwQFMAMBAf8wKQYDVR0RBCIw -IIIIdGVzdC5jb22CCXRlc3QyLmNvbYIJdGVzdDMuY29tMA0GCSqGSIb3DQEBCwUA -A4IBgQBcTedXtUb91DxQRtg73iomz7cQ4niZntUBW8iE5rpoA7prtQNGHMCbHwaX -tbWFkzBmL5JTBWvd/6AQ2LtiB3rYB3W/iRhbpsNJ501xaoOguPEQ9720Ph8TEveM -208gNzGsEOcNALwyXj2y9M19NGu9zMa8eu1Tc3IsQaVaGKHx8XZn5HTNUx8EdcwI -Z/Ji9ETDCL7+e5INv0tqfFSazWaQUwxM4IzPMkKTYRcMuN/6eog609k9r9pp32Ut -rKlzc6GIkAlgJJ0Wkoz1V46DmJNJdJG7eLu/mtsB85j6hytIQeWTf1fll5YnMZLF -HgNZtfYn8Q0oTdBQ0ZOaZeQCfZ8emYBdLJf2YB83uGRMjQ1FoeIxzQqiRq8WHRdb -9Q45i0DINMnNp0DbLMA4numZ7wT9SQb6sql9eUyuCNDw7nGIWTHUNfLtU1Er3h1d -icJuApx9+//UN/pGh0yTXb3fZbiI4IehRmkpnIWonIAwaVGm6JZU04wiIn8CuBho -/qQdlS8= ------END CERTIFICATE----- diff --git a/pathod/test/scripts/generate.sh b/pathod/test/scripts/generate.sh deleted file mode 100755 index eec3077d..00000000 --- a/pathod/test/scripts/generate.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -if [ ! -f ./private.key ] -then - openssl genrsa -out private.key 3072 -fi -openssl req \ - -batch \ - -new -x509 \ - -key private.key \ - -sha256 \ - -out cert.pem \ - -days 9999 \ - -config ./openssl.cnf -openssl x509 -in cert.pem -text -noout -cat ./private.key ./cert.pem > testcert.pem -rm ./private.key ./cert.pem diff --git a/pathod/test/scripts/openssl.cnf b/pathod/test/scripts/openssl.cnf deleted file mode 100644 index 5c890354..00000000 --- a/pathod/test/scripts/openssl.cnf +++ /dev/null @@ -1,39 +0,0 @@ -[ req ] -default_bits = 1024 -default_keyfile = privkey.pem -distinguished_name = req_distinguished_name -x509_extensions = v3_ca - -[ req_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = NZ -countryName_min = 2 -countryName_max = 2 -stateOrProvinceName = State or Province Name (full name) -stateOrProvinceName_default = Otago -localityName = Locality Name (eg, city) -0.organizationName = Organization Name (eg, company) -0.organizationName_default = Pathod -commonName = Common Name (e.g. server FQDN or YOUR name) -commonName_default = test.com -commonName_max = 64 - -[ v3_req ] - -basicConstraints = CA:FALSE -keyUsage = nonRepudiation, digitalSignature, keyEncipherment - -[ v3_ca ] - -keyUsage = digitalSignature, keyEncipherment -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid:always,issuer:always -basicConstraints = CA:true -subjectAltName = @alternate_names - - -[ alternate_names ] - -DNS.1 = test.com -DNS.2 = test2.com -DNS.3 = test3.com diff --git a/pathod/test/test_app.py b/pathod/test/test_app.py deleted file mode 100644 index 4536db8e..00000000 --- a/pathod/test/test_app.py +++ /dev/null @@ -1,85 +0,0 @@ -import tutils - - -class TestApp(tutils.DaemonTests): - SSL = False - - def test_index(self): - r = self.getpath("/") - assert r.status_code == 200 - assert r.content - - def test_about(self): - r = self.getpath("/about") - assert r.ok - - def test_download(self): - r = self.getpath("/download") - assert r.ok - - def test_docs(self): - assert self.getpath("/docs/pathod").status_code == 200 - assert self.getpath("/docs/pathoc").status_code == 200 - assert self.getpath("/docs/language").status_code == 200 - assert self.getpath("/docs/libpathod").status_code == 200 - assert self.getpath("/docs/test").status_code == 200 - - def test_log(self): - assert self.getpath("/log").status_code == 200 - assert self.get("200:da").status_code == 200 - id = self.d.log()[0]["id"] - assert self.getpath("/log").status_code == 200 - assert self.getpath("/log/%s" % id).status_code == 200 - assert self.getpath("/log/9999999").status_code == 404 - - def test_log_binary(self): - assert self.get("200:h@10b=@10b:da") - - def test_response_preview(self): - r = self.getpath("/response_preview", params=dict(spec="200")) - assert r.status_code == 200 - assert 'Response' in r.content - - r = self.getpath("/response_preview", params=dict(spec="foo")) - assert r.status_code == 200 - assert 'Error' in r.content - - r = self.getpath("/response_preview", params=dict(spec="200:b@100m")) - assert r.status_code == 200 - assert "too large" in r.content - - r = self.getpath("/response_preview", params=dict(spec="200:b@5k")) - assert r.status_code == 200 - assert 'Response' in r.content - - r = self.getpath( - "/response_preview", - params=dict( - spec="200:b 100 - - def test_path_generator(self): - r = parse_request("GET:@100").freeze(language.Settings()) - assert len(r.spec()) > 100 - - def test_websocket(self): - r = parse_request('ws:/path/') - res = r.resolve(language.Settings()) - assert res.method.string().lower() == "get" - assert res.tok(http.Path).value.val == "/path/" - assert res.tok(http.Method).value.val.lower() == "get" - assert http.get_header("Upgrade", res.headers).value.val == "websocket" - - r = parse_request('ws:put:/path/') - res = r.resolve(language.Settings()) - assert r.method.string().lower() == "put" - assert res.tok(http.Path).value.val == "/path/" - assert res.tok(http.Method).value.val.lower() == "put" - assert http.get_header("Upgrade", res.headers).value.val == "websocket" - - -class TestResponse: - - def dummy_response(self): - return language.parse_pathod("400'msg'").next() - - def test_response(self): - r = language.parse_pathod("400:m'msg'").next() - assert r.status_code.string() == "400" - assert r.reason.string() == "msg" - - r = language.parse_pathod("400:m'msg':b@100b").next() - assert r.reason.string() == "msg" - assert r.body.values({}) - assert str(r) - - r = language.parse_pathod("200").next() - assert r.status_code.string() == "200" - assert not r.reason - assert "OK" in [i[:] for i in r.preamble({})] - - def test_render(self): - s = cStringIO.StringIO() - r = language.parse_pathod("400:m'msg'").next() - assert language.serve(r, s, {}) - - r = language.parse_pathod("400:p0,100:dr").next() - assert "p0" in r.spec() - s = r.preview_safe() - assert "p0" not in s.spec() - - def test_raw(self): - s = cStringIO.StringIO() - r = language.parse_pathod("400:b'foo'").next() - language.serve(r, s, {}) - v = s.getvalue() - assert "Content-Length" in v - - s = cStringIO.StringIO() - r = language.parse_pathod("400:b'foo':r").next() - language.serve(r, s, {}) - v = s.getvalue() - assert "Content-Length" not in v - - def test_length(self): - def testlen(x): - s = cStringIO.StringIO() - x = x.next() - language.serve(x, s, language.Settings()) - assert x.length(language.Settings()) == len(s.getvalue()) - testlen(language.parse_pathod("400:m'msg':r")) - testlen(language.parse_pathod("400:m'msg':h'foo'='bar':r")) - testlen(language.parse_pathod("400:m'msg':h'foo'='bar':b@100b:r")) - - def test_maximum_length(self): - def testlen(x): - x = x.next() - s = cStringIO.StringIO() - m = x.maximum_length({}) - language.serve(x, s, {}) - assert m >= len(s.getvalue()) - - r = language.parse_pathod("400:m'msg':b@100:d0") - testlen(r) - - r = language.parse_pathod("400:m'msg':b@100:d0:i0,'foo'") - testlen(r) - - r = language.parse_pathod("400:m'msg':b@100:d0:i0,'foo'") - testlen(r) - - def test_parse_err(self): - tutils.raises( - language.ParseException, language.parse_pathod, "400:msg,b:" - ) - try: - language.parse_pathod("400'msg':b:") - except language.ParseException as v: - assert v.marked() - assert str(v) - - def test_nonascii(self): - tutils.raises("ascii", language.parse_pathod, "foo:b\xf0") - - def test_parse_header(self): - r = language.parse_pathod('400:h"foo"="bar"').next() - assert http.get_header("foo", r.headers) - - def test_parse_pause_before(self): - r = language.parse_pathod("400:p0,10").next() - assert r.actions[0].spec() == "p0,10" - - def test_parse_pause_after(self): - r = language.parse_pathod("400:pa,10").next() - assert r.actions[0].spec() == "pa,10" - - def test_parse_pause_random(self): - r = language.parse_pathod("400:pr,10").next() - assert r.actions[0].spec() == "pr,10" - - def test_parse_stress(self): - # While larger values are known to work on linux, len() technically - # returns an int and a python 2.7 int on windows has 32bit precision. - # Therefore, we should keep the body length < 2147483647 bytes in our - # tests. - r = language.parse_pathod("400:b@1g").next() - assert r.length({}) - - def test_spec(self): - def rt(s): - s = language.parse_pathod(s).next().spec() - assert language.parse_pathod(s).next().spec() == s - rt("400:b@100g") - rt("400") - rt("400:da") - - def test_websockets(self): - r = language.parse_pathod("ws").next() - tutils.raises("no websocket key", r.resolve, language.Settings()) - res = r.resolve(language.Settings(websocket_key="foo")) - assert res.status_code.string() == "101" - - -def test_ctype_shortcut(): - e = http.ShortcutContentType.expr() - v = e.parseString("c'foo'")[0] - assert v.key.val == "Content-Type" - assert v.value.val == "foo" - - s = v.spec() - assert s == e.parseString(s)[0].spec() - - e = http.ShortcutContentType.expr() - v = e.parseString("c@100")[0] - v2 = v.freeze({}) - v3 = v2.freeze({}) - assert v2.value.val == v3.value.val - - -def test_location_shortcut(): - e = http.ShortcutLocation.expr() - v = e.parseString("l'foo'")[0] - assert v.key.val == "Location" - assert v.value.val == "foo" - - s = v.spec() - assert s == e.parseString(s)[0].spec() - - e = http.ShortcutLocation.expr() - v = e.parseString("l@100")[0] - v2 = v.freeze({}) - v3 = v2.freeze({}) - assert v2.value.val == v3.value.val - - -def test_shortcuts(): - assert language.parse_pathod( - "400:c'foo'").next().headers[0].key.val == "Content-Type" - assert language.parse_pathod( - "400:l'foo'").next().headers[0].key.val == "Location" - - assert "Android" in tutils.render(parse_request("get:/:ua")) - assert "User-Agent" in tutils.render(parse_request("get:/:ua")) - - -def test_user_agent(): - e = http.ShortcutUserAgent.expr() - v = e.parseString("ua")[0] - assert "Android" in v.string() - - e = http.ShortcutUserAgent.expr() - v = e.parseString("u'a'")[0] - assert "Android" not in v.string() - - v = e.parseString("u@100'")[0] - assert len(str(v.freeze({}).value)) > 100 - v2 = v.freeze({}) - v3 = v2.freeze({}) - assert v2.value.val == v3.value.val - - -def test_nested_response(): - e = http.NestedResponse.expr() - v = e.parseString("s'200'")[0] - assert v.value.val == "200" - tutils.raises( - language.ParseException, - e.parseString, - "s'foo'" - ) - - v = e.parseString('s"200:b@1"')[0] - assert "@1" in v.spec() - f = v.freeze({}) - assert "@1" not in f.spec() - - -def test_nested_response_freeze(): - e = http.NestedResponse( - base.TokValueLiteral( - "200:b'foo':i10,'\\x27'".encode( - "string_escape" - ) - ) - ) - assert e.freeze({}) - assert e.values({}) - - -def test_unique_components(): - tutils.raises( - "multiple body clauses", - language.parse_pathod, - "400:b@1:b@1" - ) diff --git a/pathod/test/test_language_http2.py b/pathod/test/test_language_http2.py deleted file mode 100644 index 9be49452..00000000 --- a/pathod/test/test_language_http2.py +++ /dev/null @@ -1,233 +0,0 @@ -import cStringIO - -import netlib -from netlib import tcp -from netlib.http import user_agents - -from libpathod import language -from libpathod.language import http2, base -import tutils - - -def parse_request(s): - return language.parse_pathoc(s, True).next() - - -def parse_response(s): - return language.parse_pathod(s, True).next() - - -def default_settings(): - return language.Settings( - request_host="foo.com", - protocol=netlib.http.http2.HTTP2Protocol(tcp.TCPClient(('localhost', 1234))) - ) - - -def test_make_error_response(): - d = cStringIO.StringIO() - s = http2.make_error_response("foo", "bar") - language.serve(s, d, default_settings()) - - -class TestRequest: - - def test_cached_values(self): - req = parse_request("get:/") - req_id = id(req) - assert req_id == id(req.resolve(default_settings())) - assert req.values(default_settings()) == req.values(default_settings()) - - def test_nonascii(self): - tutils.raises("ascii", parse_request, "get:\xf0") - - def test_err(self): - tutils.raises(language.ParseException, parse_request, 'GET') - - def test_simple(self): - r = parse_request('GET:"/foo"') - assert r.method.string() == "GET" - assert r.path.string() == "/foo" - r = parse_request('GET:/foo') - assert r.path.string() == "/foo" - - def test_multiple(self): - r = list(language.parse_pathoc("GET:/ PUT:/")) - assert r[0].method.string() == "GET" - assert r[1].method.string() == "PUT" - assert len(r) == 2 - - l = """ - GET - "/foo" - - PUT - - "/foo - - - - bar" - """ - r = list(language.parse_pathoc(l, True)) - assert len(r) == 2 - assert r[0].method.string() == "GET" - assert r[1].method.string() == "PUT" - - l = """ - get:"http://localhost:9999/p/200" - get:"http://localhost:9999/p/200" - """ - r = list(language.parse_pathoc(l, True)) - assert len(r) == 2 - assert r[0].method.string() == "GET" - assert r[1].method.string() == "GET" - - def test_render_simple(self): - s = cStringIO.StringIO() - r = parse_request("GET:'/foo'") - assert language.serve( - r, - s, - default_settings(), - ) - - def test_raw_content_length(self): - r = parse_request('GET:/:r') - assert len(r.headers) == 0 - - r = parse_request('GET:/:r:b"foobar"') - assert len(r.headers) == 0 - - r = parse_request('GET:/') - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("content-length", "0") - - r = parse_request('GET:/:b"foobar"') - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("content-length", "6") - - r = parse_request('GET:/:b"foobar":h"content-length"="42"') - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("content-length", "42") - - r = parse_request('GET:/:r:b"foobar":h"content-length"="42"') - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("content-length", "42") - - def test_content_type(self): - r = parse_request('GET:/:r:c"foobar"') - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("content-type", "foobar") - - def test_user_agent(self): - r = parse_request('GET:/:r:ua') - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("user-agent", user_agents.get_by_shortcut('a')[2]) - - def test_render_with_headers(self): - s = cStringIO.StringIO() - r = parse_request('GET:/foo:h"foo"="bar"') - assert language.serve( - r, - s, - default_settings(), - ) - - def test_nested_response(self): - l = "get:/p/:s'200'" - r = parse_request(l) - assert len(r.tokens) == 3 - assert isinstance(r.tokens[2], http2.NestedResponse) - assert r.values(default_settings()) - - - def test_render_with_body(self): - s = cStringIO.StringIO() - r = parse_request("GET:'/foo':bfoobar") - assert language.serve( - r, - s, - default_settings(), - ) - - def test_spec(self): - def rt(s): - s = parse_request(s).spec() - assert parse_request(s).spec() == s - rt("get:/foo") - - -class TestResponse: - - def test_cached_values(self): - res = parse_response("200") - res_id = id(res) - assert res_id == id(res.resolve(default_settings())) - assert res.values(default_settings()) == res.values(default_settings()) - - def test_nonascii(self): - tutils.raises("ascii", parse_response, "200:\xf0") - - def test_err(self): - tutils.raises(language.ParseException, parse_response, 'GET:/') - - def test_raw_content_length(self): - r = parse_response('200:r') - assert len(r.headers) == 0 - - r = parse_response('200') - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("content-length", "0") - - def test_content_type(self): - r = parse_response('200:r:c"foobar"') - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("content-type", "foobar") - - def test_simple(self): - r = parse_response('200:r:h"foo"="bar"') - assert r.status_code.string() == "200" - assert len(r.headers) == 1 - assert r.headers[0].values(default_settings()) == ("foo", "bar") - assert r.body is None - - r = parse_response('200:r:h"foo"="bar":bfoobar:h"bla"="fasel"') - assert r.status_code.string() == "200" - assert len(r.headers) == 2 - assert r.headers[0].values(default_settings()) == ("foo", "bar") - assert r.headers[1].values(default_settings()) == ("bla", "fasel") - assert r.body.string() == "foobar" - - def test_render_simple(self): - s = cStringIO.StringIO() - r = parse_response('200') - assert language.serve( - r, - s, - default_settings(), - ) - - def test_render_with_headers(self): - s = cStringIO.StringIO() - r = parse_response('200:h"foo"="bar"') - assert language.serve( - r, - s, - default_settings(), - ) - - def test_render_with_body(self): - s = cStringIO.StringIO() - r = parse_response('200:bfoobar') - assert language.serve( - r, - s, - default_settings(), - ) - - def test_spec(self): - def rt(s): - s = parse_response(s).spec() - assert parse_response(s).spec() == s - rt("200:bfoobar") diff --git a/pathod/test/test_language_websocket.py b/pathod/test/test_language_websocket.py deleted file mode 100644 index d98fd33e..00000000 --- a/pathod/test/test_language_websocket.py +++ /dev/null @@ -1,142 +0,0 @@ - -from libpathod import language -from libpathod.language import websockets -import netlib.websockets -import tutils - - -def parse_request(s): - return language.parse_pathoc(s).next() - - -class TestWebsocketFrame: - - def _test_messages(self, specs, message_klass): - for i in specs: - wf = parse_request(i) - assert isinstance(wf, message_klass) - assert wf - assert wf.values(language.Settings()) - assert wf.resolve(language.Settings()) - - spec = wf.spec() - wf2 = parse_request(spec) - assert wf2.spec() == spec - - def test_server_values(self): - specs = [ - "wf", - "wf:dr", - "wf:b'foo'", - "wf:mask:r'foo'", - "wf:l1024:b'foo'", - "wf:cbinary", - "wf:c1", - "wf:mask:knone", - "wf:fin", - "wf:fin:rsv1:rsv2:rsv3:mask", - "wf:-fin:-rsv1:-rsv2:-rsv3:-mask", - "wf:k@4", - "wf:x10", - ] - self._test_messages(specs, websockets.WebsocketFrame) - - def test_parse_websocket_frames(self): - wf = language.parse_websocket_frame("wf:x10") - assert len(list(wf)) == 10 - tutils.raises( - language.ParseException, - language.parse_websocket_frame, - "wf:x" - ) - - def test_client_values(self): - specs = [ - "wf:f'wf'", - ] - self._test_messages(specs, websockets.WebsocketClientFrame) - - def test_nested_frame(self): - wf = parse_request("wf:f'wf'") - assert wf.nested_frame - - def test_flags(self): - wf = parse_request("wf:fin:mask:rsv1:rsv2:rsv3") - frm = netlib.websockets.Frame.from_bytes(tutils.render(wf)) - assert frm.header.fin - assert frm.header.mask - assert frm.header.rsv1 - assert frm.header.rsv2 - assert frm.header.rsv3 - - wf = parse_request("wf:-fin:-mask:-rsv1:-rsv2:-rsv3") - frm = netlib.websockets.Frame.from_bytes(tutils.render(wf)) - assert not frm.header.fin - assert not frm.header.mask - assert not frm.header.rsv1 - assert not frm.header.rsv2 - assert not frm.header.rsv3 - - def fr(self, spec, **kwargs): - settings = language.base.Settings(**kwargs) - wf = parse_request(spec) - return netlib.websockets.Frame.from_bytes(tutils.render(wf, settings)) - - def test_construction(self): - assert self.fr("wf:c1").header.opcode == 1 - assert self.fr("wf:c0").header.opcode == 0 - assert self.fr("wf:cbinary").header.opcode ==\ - netlib.websockets.OPCODE.BINARY - assert self.fr("wf:ctext").header.opcode ==\ - netlib.websockets.OPCODE.TEXT - - def test_rawbody(self): - frm = self.fr("wf:mask:r'foo'") - assert len(frm.payload) == 3 - assert frm.payload != "foo" - - assert self.fr("wf:r'foo'").payload == "foo" - - def test_construction(self): - # Simple server frame - frm = self.fr("wf:b'foo'") - assert not frm.header.mask - assert not frm.header.masking_key - - # Simple client frame - frm = self.fr("wf:b'foo'", is_client=True) - assert frm.header.mask - assert frm.header.masking_key - frm = self.fr("wf:b'foo':k'abcd'", is_client=True) - assert frm.header.mask - assert frm.header.masking_key == 'abcd' - - # Server frame, mask explicitly set - frm = self.fr("wf:b'foo':mask") - assert frm.header.mask - assert frm.header.masking_key - frm = self.fr("wf:b'foo':k'abcd'") - assert frm.header.mask - assert frm.header.masking_key == 'abcd' - - # Client frame, mask explicitly unset - frm = self.fr("wf:b'foo':-mask", is_client=True) - assert not frm.header.mask - assert not frm.header.masking_key - - frm = self.fr("wf:b'foo':-mask:k'abcd'", is_client=True) - assert not frm.header.mask - # We're reading back a corrupted frame - the first 3 characters of the - # mask is mis-interpreted as the payload - assert frm.payload == "abc" - - def test_knone(self): - with tutils.raises("expected 4 bytes"): - self.fr("wf:b'foo':mask:knone") - - def test_length(self): - assert self.fr("wf:l3:b'foo'").header.payload_length == 3 - frm = self.fr("wf:l2:b'foo'") - assert frm.header.payload_length == 2 - assert frm.payload == "fo" - tutils.raises("expected 1024 bytes", self.fr, "wf:l1024:b'foo'") diff --git a/pathod/test/test_language_writer.py b/pathod/test/test_language_writer.py deleted file mode 100644 index 1a532903..00000000 --- a/pathod/test/test_language_writer.py +++ /dev/null @@ -1,91 +0,0 @@ -import cStringIO - -from libpathod import language -from libpathod.language import writer - - -def test_send_chunk(): - v = "foobarfoobar" - for bs in range(1, len(v) + 2): - s = cStringIO.StringIO() - writer.send_chunk(s, v, bs, 0, len(v)) - assert s.getvalue() == v - for start in range(len(v)): - for end in range(len(v)): - s = cStringIO.StringIO() - writer.send_chunk(s, v, bs, start, end) - assert s.getvalue() == v[start:end] - - -def test_write_values_inject(): - tst = "foo" - - s = cStringIO.StringIO() - writer.write_values(s, [tst], [(0, "inject", "aaa")], blocksize=5) - assert s.getvalue() == "aaafoo" - - s = cStringIO.StringIO() - writer.write_values(s, [tst], [(1, "inject", "aaa")], blocksize=5) - assert s.getvalue() == "faaaoo" - - s = cStringIO.StringIO() - writer.write_values(s, [tst], [(1, "inject", "aaa")], blocksize=5) - assert s.getvalue() == "faaaoo" - - -def test_write_values_disconnects(): - s = cStringIO.StringIO() - tst = "foo" * 100 - writer.write_values(s, [tst], [(0, "disconnect")], blocksize=5) - assert not s.getvalue() - - -def test_write_values(): - tst = "foobarvoing" - s = cStringIO.StringIO() - writer.write_values(s, [tst], []) - assert s.getvalue() == tst - - for bs in range(1, len(tst) + 2): - for off in range(len(tst)): - s = cStringIO.StringIO() - writer.write_values( - s, [tst], [(off, "disconnect")], blocksize=bs - ) - assert s.getvalue() == tst[:off] - - -def test_write_values_pauses(): - tst = "".join(str(i) for i in range(10)) - for i in range(2, 10): - s = cStringIO.StringIO() - writer.write_values( - s, [tst], [(2, "pause", 0), (1, "pause", 0)], blocksize=i - ) - assert s.getvalue() == tst - - for i in range(2, 10): - s = cStringIO.StringIO() - writer.write_values(s, [tst], [(1, "pause", 0)], blocksize=i) - assert s.getvalue() == tst - - tst = ["".join(str(i) for i in range(10))] * 5 - for i in range(2, 10): - s = cStringIO.StringIO() - writer.write_values(s, tst[:], [(1, "pause", 0)], blocksize=i) - assert s.getvalue() == "".join(tst) - - -def test_write_values_after(): - s = cStringIO.StringIO() - r = language.parse_pathod("400:da").next() - language.serve(r, s, {}) - - s = cStringIO.StringIO() - r = language.parse_pathod("400:pa,0").next() - language.serve(r, s, {}) - - s = cStringIO.StringIO() - r = language.parse_pathod("400:ia,'xx'").next() - language.serve(r, s, {}) - assert s.getvalue().endswith('xx') diff --git a/pathod/test/test_log.py b/pathod/test/test_log.py deleted file mode 100644 index 8f38c040..00000000 --- a/pathod/test/test_log.py +++ /dev/null @@ -1,25 +0,0 @@ -import StringIO -from libpathod import log -from netlib.exceptions import TcpDisconnect -import netlib.tcp - - -class DummyIO(StringIO.StringIO): - - def start_log(self, *args, **kwargs): - pass - - def get_log(self, *args, **kwargs): - return "" - - -def test_disconnect(): - outf = DummyIO() - rw = DummyIO() - l = log.ConnectionLogger(outf, False, rw, rw) - try: - with l.ctx() as lg: - lg("Test") - except TcpDisconnect: - pass - assert "Test" in outf.getvalue() diff --git a/pathod/test/test_pathoc.py b/pathod/test/test_pathoc.py deleted file mode 100644 index 62696a64..00000000 --- a/pathod/test/test_pathoc.py +++ /dev/null @@ -1,308 +0,0 @@ -import json -import cStringIO -import re -import OpenSSL -from mock import Mock - -from netlib import tcp, http, socks -from netlib.exceptions import HttpException, TcpException, NetlibException -from netlib.http import http1, http2 - -from libpathod import pathoc, test, version, pathod, language -from netlib.tutils import raises -import tutils - - -def test_response(): - r = http.Response("HTTP/1.1", 200, "Message", {}, None, None) - assert repr(r) - - -class _TestDaemon: - ssloptions = pathod.SSLOptions() - - @classmethod - def setup_class(cls): - cls.d = test.Daemon( - ssl=cls.ssl, - ssloptions=cls.ssloptions, - staticdir=tutils.test_data.path("data"), - anchors=[ - (re.compile("/anchor/.*"), "202") - ] - ) - - @classmethod - def teardown_class(cls): - cls.d.shutdown() - - def setUp(self): - self.d.clear_log() - - def test_info(self): - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - ssl=self.ssl, - fp=None - ) - c.connect() - resp = c.request("get:/api/info") - assert tuple(json.loads(resp.content)["version"]) == version.IVERSION - - def tval( - self, - requests, - showreq=False, - showresp=False, - explain=False, - showssl=False, - hexdump=False, - timeout=None, - ignorecodes=(), - ignoretimeout=None, - showsummary=True - ): - s = cStringIO.StringIO() - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - ssl=self.ssl, - showreq=showreq, - showresp=showresp, - explain=explain, - hexdump=hexdump, - ignorecodes=ignorecodes, - ignoretimeout=ignoretimeout, - showsummary=showsummary, - fp=s - ) - c.connect(showssl=showssl, fp=s) - if timeout: - c.settimeout(timeout) - for i in requests: - r = language.parse_pathoc(i).next() - if explain: - r = r.freeze(language.Settings()) - try: - c.request(r) - except NetlibException: - pass - return s.getvalue() - - -class TestDaemonSSL(_TestDaemon): - ssl = True - ssloptions = pathod.SSLOptions( - request_client_cert=True, - sans=["test1.com", "test2.com"], - alpn_select=b'h2', - ) - - def test_sni(self): - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - ssl=True, - sni="foobar.com", - fp=None - ) - c.connect() - c.request("get:/p/200") - r = c.request("get:/api/log") - d = json.loads(r.content) - assert d["log"][0]["request"]["sni"] == "foobar.com" - - def test_showssl(self): - assert "certificate chain" in self.tval(["get:/p/200"], showssl=True) - - def test_clientcert(self): - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - ssl=True, - clientcert=tutils.test_data.path("data/clientcert/client.pem"), - fp=None - ) - c.connect() - c.request("get:/p/200") - r = c.request("get:/api/log") - d = json.loads(r.content) - assert d["log"][0]["request"]["clientcert"]["keyinfo"] - - def test_http2_without_ssl(self): - fp = cStringIO.StringIO() - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - use_http2=True, - ssl=False, - fp = fp - ) - tutils.raises(NotImplementedError, c.connect) - - -class TestDaemon(_TestDaemon): - ssl = False - - def test_ssl_error(self): - c = pathoc.Pathoc(("127.0.0.1", self.d.port), ssl=True, fp=None) - tutils.raises("ssl handshake", c.connect) - - def test_showssl(self): - assert not "certificate chain" in self.tval( - ["get:/p/200"], - showssl=True) - - def test_ignorecodes(self): - assert "200" in self.tval(["get:'/p/200:b@1'"]) - assert "200" in self.tval(["get:'/p/200:b@1'"]) - 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,100'"], timeout=0.01) - assert "HTTP" in self.tval( - ["get:'/p/200:p5,100'"], - showresp=True, - timeout=1 - ) - assert not "HTTP" in self.tval( - ["get:'/p/200:p3,100'"], - showresp=True, - timeout=1, - ignoretimeout=True - ) - - def test_showresp(self): - reqs = ["get:/api/info:p0,0", "get:/api/info:p0,0"] - assert self.tval(reqs).count("200") == 2 - assert self.tval(reqs, showresp=True).count("HTTP/1.1 200 OK") == 2 - assert self.tval( - reqs, showresp=True, hexdump=True - ).count("0000000000") == 2 - - def test_showresp_httperr(self): - v = self.tval(["get:'/p/200:d20'"], showresp=True, showsummary=True) - assert "Invalid headers" in v - assert "HTTP/" in v - - def test_explain(self): - reqs = ["get:/p/200:b@100"] - assert "b@100" not in self.tval(reqs, explain=True) - - def test_showreq(self): - reqs = ["get:/api/info:p0,0", "get:/api/info:p0,0"] - assert self.tval(reqs, showreq=True).count("GET /api") == 2 - assert self.tval( - reqs, showreq=True, hexdump=True - ).count("0000000000") == 2 - - def test_conn_err(self): - assert "Invalid server response" in self.tval(["get:'/p/200:d2'"]) - - def test_websocket_shutdown(self): - c = pathoc.Pathoc(("127.0.0.1", self.d.port), fp=None) - c.connect() - c.request("ws:/") - c.stop() - - def test_wait_finish(self): - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - fp=None, - ws_read_limit=1 - ) - c.connect() - c.request("ws:/") - c.request("wf:f'wf:x100'") - [i for i in c.wait(timeout=0, finish=False)] - [i for i in c.wait(timeout=0)] - - def test_connect_fail(self): - to = ("foobar", 80) - c = pathoc.Pathoc(("127.0.0.1", self.d.port), fp=None) - c.rfile, c.wfile = cStringIO.StringIO(), cStringIO.StringIO() - with raises("connect failed"): - c.http_connect(to) - c.rfile = cStringIO.StringIO( - "HTTP/1.1 500 OK\r\n" - ) - with raises("connect failed"): - c.http_connect(to) - c.rfile = cStringIO.StringIO( - "HTTP/1.1 200 OK\r\n" - ) - c.http_connect(to) - - def test_socks_connect(self): - to = ("foobar", 80) - c = pathoc.Pathoc(("127.0.0.1", self.d.port), fp=None) - c.rfile, c.wfile = tutils.treader(""), cStringIO.StringIO() - tutils.raises(pathoc.PathocError, c.socks_connect, to) - - c.rfile = tutils.treader( - "\x05\xEE" - ) - tutils.raises("SOCKS without authentication", c.socks_connect, ("example.com", 0xDEAD)) - - c.rfile = tutils.treader( - "\x05\x00" + - "\x05\xEE\x00\x03\x0bexample.com\xDE\xAD" - ) - tutils.raises("SOCKS server error", c.socks_connect, ("example.com", 0xDEAD)) - - c.rfile = tutils.treader( - "\x05\x00" + - "\x05\x00\x00\x03\x0bexample.com\xDE\xAD" - ) - c.socks_connect(("example.com", 0xDEAD)) - - -class TestDaemonHTTP2(_TestDaemon): - ssl = True - - if OpenSSL._util.lib.Cryptography_HAS_ALPN: - - def test_http2(self): - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - fp=None, - ssl=True, - use_http2=True, - ) - assert isinstance(c.protocol, http2.HTTP2Protocol) - - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - ) - assert c.protocol == http1 - - def test_http2_alpn(self): - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - fp=None, - ssl=True, - use_http2=True, - http2_skip_connection_preface=True, - ) - - tmp_convert_to_ssl = c.convert_to_ssl - c.convert_to_ssl = Mock() - c.convert_to_ssl.side_effect = tmp_convert_to_ssl - c.connect() - - _, kwargs = c.convert_to_ssl.call_args - assert set(kwargs['alpn_protos']) == set([b'http/1.1', b'h2']) - - def test_request(self): - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - fp=None, - ssl=True, - use_http2=True, - ) - c.connect() - resp = c.request("get:/p/200") - assert resp.status_code == 200 diff --git a/pathod/test/test_pathoc_cmdline.py b/pathod/test/test_pathoc_cmdline.py deleted file mode 100644 index 74dfef57..00000000 --- a/pathod/test/test_pathoc_cmdline.py +++ /dev/null @@ -1,59 +0,0 @@ -from libpathod import pathoc_cmdline as cmdline -import tutils -import cStringIO -import mock - - -@mock.patch("argparse.ArgumentParser.error") -def test_pathoc(perror): - assert cmdline.args_pathoc(["pathoc", "foo.com", "get:/"]) - s = cStringIO.StringIO() - with tutils.raises(SystemExit): - cmdline.args_pathoc(["pathoc", "--show-uas"], s, s) - - a = cmdline.args_pathoc(["pathoc", "foo.com:8888", "get:/"]) - assert a.port == 8888 - - a = cmdline.args_pathoc(["pathoc", "foo.com:xxx", "get:/"]) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathoc(["pathoc", "-I", "10, 20", "foo.com:8888", "get:/"]) - assert a.ignorecodes == [10, 20] - - a = cmdline.args_pathoc(["pathoc", "-I", "xx, 20", "foo.com:8888", "get:/"]) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathoc(["pathoc", "-c", "foo:10", "foo.com:8888", "get:/"]) - assert a.connect_to == ["foo", 10] - - a = cmdline.args_pathoc(["pathoc", "foo.com", "get:/", "--http2"]) - assert a.use_http2 == True - assert a.ssl == True - - a = cmdline.args_pathoc(["pathoc", "foo.com", "get:/", "--http2-skip-connection-preface"]) - assert a.use_http2 == True - assert a.ssl == True - assert a.http2_skip_connection_preface == True - - a = cmdline.args_pathoc(["pathoc", "-c", "foo", "foo.com:8888", "get:/"]) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathoc( - ["pathoc", "-c", "foo:bar", "foo.com:8888", "get:/"]) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathoc( - [ - "pathoc", - "foo.com:8888", - tutils.test_data.path("data/request") - ] - ) - assert len(list(a.requests)) == 1 - - with tutils.raises(SystemExit): - cmdline.args_pathoc(["pathoc", "foo.com", "invalid"], s, s) diff --git a/pathod/test/test_pathod.py b/pathod/test/test_pathod.py deleted file mode 100644 index 98da7d28..00000000 --- a/pathod/test/test_pathod.py +++ /dev/null @@ -1,289 +0,0 @@ -import sys -import cStringIO -import OpenSSL - -from libpathod import pathod, version -from netlib import tcp, http -from netlib.exceptions import HttpException, TlsException -import tutils - - -class TestPathod(object): - - def test_logging(self): - s = cStringIO.StringIO() - p = pathod.Pathod(("127.0.0.1", 0), logfp=s) - assert len(p.get_log()) == 0 - id = p.add_log(dict(s="foo")) - assert p.log_by_id(id) - assert len(p.get_log()) == 1 - p.clear_log() - assert len(p.get_log()) == 0 - - for _ in range(p.LOGBUF + 1): - p.add_log(dict(s="foo")) - assert len(p.get_log()) <= p.LOGBUF - - -class TestNoWeb(tutils.DaemonTests): - noweb = True - - def test_noweb(self): - assert self.get("200:da").status_code == 200 - assert self.getpath("/").status_code == 800 - - -class TestTimeout(tutils.DaemonTests): - timeout = 0.01 - - def test_noweb(self): - # FIXME: Add float values to spec language, reduce test timeout to - # increase test performance - # This is a bodge - we have some platform difference that causes - # different exceptions to be raised here. - tutils.raises(Exception, self.pathoc, ["get:/:p1,1"]) - assert self.d.last_log()["type"] == "timeout" - - -class TestNoApi(tutils.DaemonTests): - noapi = True - - def test_noapi(self): - assert self.getpath("/log").status_code == 404 - r = self.getpath("/") - assert r.status_code == 200 - assert not "Log" in r.content - - -class TestNotAfterConnect(tutils.DaemonTests): - ssl = False - ssloptions = dict( - not_after_connect=True - ) - - def test_connect(self): - r, _ = self.pathoc( - [r"get:'http://foo.com/p/202':da"], - connect_to=("localhost", self.d.port) - ) - assert r[0].status_code == 202 - - -class TestCustomCert(tutils.DaemonTests): - ssl = True - ssloptions = dict( - certs=[("*", tutils.test_data.path("data/testkey.pem"))], - ) - - def test_connect(self): - r, _ = self.pathoc([r"get:/p/202"]) - r = r[0] - assert r.status_code == 202 - assert r.sslinfo - assert "test.com" in str(r.sslinfo.certchain[0].get_subject()) - - -class TestSSLCN(tutils.DaemonTests): - ssl = True - ssloptions = dict( - cn="foo.com" - ) - - def test_connect(self): - r, _ = self.pathoc([r"get:/p/202"]) - r = r[0] - assert r.status_code == 202 - assert r.sslinfo - assert r.sslinfo.certchain[0].get_subject().CN == "foo.com" - - -class TestNohang(tutils.DaemonTests): - nohang = True - - def test_nohang(self): - r = self.get("200:p0,0") - assert r.status_code == 800 - l = self.d.last_log() - assert "Pauses have been disabled" in l["response"]["msg"] - - -class TestHexdump(tutils.DaemonTests): - hexdump = True - - def test_hexdump(self): - r = self.get(r"200:b'\xf0'") - - -class TestNocraft(tutils.DaemonTests): - nocraft = True - - def test_nocraft(self): - r = self.get(r"200:b'\xf0'") - assert r.status_code == 800 - assert "Crafting disabled" in r.content - - -class CommonTests(tutils.DaemonTests): - - def test_binarydata(self): - r = self.get(r"200:b'\xf0'") - l = self.d.last_log() - # FIXME: Other binary data elements - - def test_sizelimit(self): - r = self.get("200:b@1g") - assert r.status_code == 800 - l = self.d.last_log() - assert "too large" in l["response"]["msg"] - - def test_preline(self): - r, _ = self.pathoc([r"get:'/p/200':i0,'\r\n'"]) - assert r[0].status_code == 200 - - def test_info(self): - assert tuple(self.d.info()["version"]) == version.IVERSION - - def test_logs(self): - assert self.d.clear_log() - assert not self.d.last_log() - rsp = self.get("202:da") - assert len(self.d.log()) == 1 - assert self.d.clear_log() - assert len(self.d.log()) == 0 - - def test_disconnect(self): - rsp = self.get("202:b@100k:d200") - assert len(rsp.content) < 200 - - def test_parserr(self): - rsp = self.get("400:msg,b:") - assert rsp.status_code == 800 - - def test_static(self): - rsp = self.get("200:b 0 - - -class TestHTTP2(tutils.DaemonTests): - ssl = True - noweb = True - noapi = True - nohang = True - - if OpenSSL._util.lib.Cryptography_HAS_ALPN: - - def test_http2(self): - r, _ = self.pathoc(["GET:/"], ssl=True, use_http2=True) - assert r[0].status_code == 800 diff --git a/pathod/test/test_pathod_cmdline.py b/pathod/test/test_pathod_cmdline.py deleted file mode 100644 index 829c4b32..00000000 --- a/pathod/test/test_pathod_cmdline.py +++ /dev/null @@ -1,85 +0,0 @@ -from libpathod import pathod_cmdline as cmdline -import tutils -import cStringIO -import mock - - -@mock.patch("argparse.ArgumentParser.error") -def test_pathod(perror): - assert cmdline.args_pathod(["pathod"]) - - a = cmdline.args_pathod( - [ - "pathod", - "--cert", - tutils.test_data.path("data/testkey.pem") - ] - ) - assert a.ssl_certs - - a = cmdline.args_pathod( - [ - "pathod", - "--cert", - "nonexistent" - ] - ) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathod( - [ - "pathod", - "-a", - "foo=200" - ] - ) - assert a.anchors - - a = cmdline.args_pathod( - [ - "pathod", - "-a", - "foo=" + tutils.test_data.path("data/response") - ] - ) - assert a.anchors - - a = cmdline.args_pathod( - [ - "pathod", - "-a", - "?=200" - ] - ) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathod( - [ - "pathod", - "-a", - "foo" - ] - ) - assert perror.called - perror.reset_mock() - - a = cmdline.args_pathod( - [ - "pathod", - "--limit-size", - "200k" - ] - ) - assert a.sizelimit - - a = cmdline.args_pathod( - [ - "pathod", - "--limit-size", - "q" - ] - ) - assert perror.called - perror.reset_mock() diff --git a/pathod/test/test_test.py b/pathod/test/test_test.py deleted file mode 100644 index bd92d864..00000000 --- a/pathod/test/test_test.py +++ /dev/null @@ -1,45 +0,0 @@ -import logging -import requests -from libpathod import test -import tutils -logging.disable(logging.CRITICAL) - - -class TestDaemonManual: - - def test_simple(self): - with test.Daemon() as d: - rsp = requests.get("http://localhost:%s/p/202:da" % d.port) - assert rsp.ok - assert rsp.status_code == 202 - with tutils.raises(requests.ConnectionError): - requests.get("http://localhost:%s/p/202:da" % d.port) - - def test_startstop_ssl(self): - d = test.Daemon(ssl=True) - rsp = requests.get( - "https://localhost:%s/p/202:da" % - d.port, - verify=False) - assert rsp.ok - assert rsp.status_code == 202 - d.shutdown() - with tutils.raises(requests.ConnectionError): - requests.get("http://localhost:%s/p/202:da" % d.port) - - def test_startstop_ssl_explicit(self): - ssloptions = dict( - certfile=tutils.test_data.path("data/testkey.pem"), - cacert=tutils.test_data.path("data/testkey.pem"), - ssl_after_connect=False - ) - d = test.Daemon(ssl=ssloptions) - rsp = requests.get( - "https://localhost:%s/p/202:da" % - d.port, - verify=False) - assert rsp.ok - assert rsp.status_code == 202 - d.shutdown() - with tutils.raises(requests.ConnectionError): - requests.get("http://localhost:%s/p/202:da" % d.port) diff --git a/pathod/test/test_utils.py b/pathod/test/test_utils.py deleted file mode 100644 index 7d24e9e4..00000000 --- a/pathod/test/test_utils.py +++ /dev/null @@ -1,39 +0,0 @@ -from libpathod import utils -import tutils - - -def test_membool(): - m = utils.MemBool() - assert not m.v - assert m(1) - assert m.v == 1 - assert m(2) - assert m.v == 2 - - -def test_parse_size(): - assert utils.parse_size("100") == 100 - assert utils.parse_size("100k") == 100 * 1024 - tutils.raises("invalid size spec", utils.parse_size, "foo") - tutils.raises("invalid size spec", utils.parse_size, "100kk") - - -def test_parse_anchor_spec(): - assert utils.parse_anchor_spec("foo=200") == ("foo", "200") - assert utils.parse_anchor_spec("foo") is None - - -def test_data_path(): - tutils.raises(ValueError, utils.data.path, "nonexistent") - - -def test_inner_repr(): - assert utils.inner_repr("\x66") == "\x66" - assert utils.inner_repr(u"foo") == "foo" - - -def test_escape_unprintables(): - s = "".join([chr(i) for i in range(255)]) - e = utils.escape_unprintables(s) - assert e.encode('ascii') - assert not "PATHOD_MARKER" in e diff --git a/pathod/test/tutils.py b/pathod/test/tutils.py deleted file mode 100644 index 664cdd52..00000000 --- a/pathod/test/tutils.py +++ /dev/null @@ -1,128 +0,0 @@ -import tempfile -import os -import re -import shutil -import cStringIO -from contextlib import contextmanager - -import netlib -from libpathod import utils, test, pathoc, pathod, language -from netlib import tcp -import requests - -def treader(bytes): - """ - Construct a tcp.Read object from bytes. - """ - fp = cStringIO.StringIO(bytes) - return tcp.Reader(fp) - - -class DaemonTests(object): - noweb = False - noapi = False - nohang = False - ssl = False - timeout = None - hexdump = False - ssloptions = None - nocraft = False - - @classmethod - def setup_class(cls): - opts = cls.ssloptions or {} - cls.confdir = tempfile.mkdtemp() - opts["confdir"] = cls.confdir - so = pathod.SSLOptions(**opts) - cls.d = test.Daemon( - staticdir=test_data.path("data"), - anchors=[ - (re.compile("/anchor/.*"), "202:da") - ], - ssl=cls.ssl, - ssloptions=so, - sizelimit=1 * 1024 * 1024, - noweb=cls.noweb, - noapi=cls.noapi, - nohang=cls.nohang, - timeout=cls.timeout, - hexdump=cls.hexdump, - nocraft=cls.nocraft, - logreq=True, - logresp=True, - explain=True - ) - - @classmethod - def teardown_class(cls): - cls.d.shutdown() - shutil.rmtree(cls.confdir) - - def teardown(self): - if not (self.noweb or self.noapi): - self.d.clear_log() - - def getpath(self, path, params=None): - scheme = "https" if self.ssl else "http" - resp = requests.get( - "%s://localhost:%s/%s" % ( - scheme, - self.d.port, - path - ), - verify=False, - params=params - ) - return resp - - def get(self, spec): - resp = requests.get(self.d.p(spec), verify=False) - return resp - - def pathoc( - self, - specs, - timeout=None, - connect_to=None, - ssl=None, - ws_read_limit=None, - use_http2=False, - ): - """ - Returns a (messages, text log) tuple. - """ - if ssl is None: - ssl = self.ssl - logfp = cStringIO.StringIO() - c = pathoc.Pathoc( - ("localhost", self.d.port), - ssl=ssl, - ws_read_limit=ws_read_limit, - timeout=timeout, - fp=logfp, - use_http2=use_http2, - ) - c.connect(connect_to) - ret = [] - for i in specs: - resp = c.request(i) - if resp: - ret.append(resp) - for frm in c.wait(): - ret.append(frm) - c.stop() - return ret, logfp.getvalue() - - -tmpdir = netlib.tutils.tmpdir - -raises = netlib.tutils.raises - -test_data = utils.Data(__name__) - - -def render(r, settings=language.Settings()): - r = r.resolve(settings) - s = cStringIO.StringIO() - assert language.serve(r, s, settings) - return s.getvalue() -- cgit v1.2.3 From a1190c369648438811daae70c1baff4e32b198fd Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 15 Feb 2016 17:06:32 +0100 Subject: adjust travis --- pathod/.coveragerc | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 pathod/.coveragerc (limited to 'pathod') diff --git a/pathod/.coveragerc b/pathod/.coveragerc deleted file mode 100644 index 7e978294..00000000 --- a/pathod/.coveragerc +++ /dev/null @@ -1,10 +0,0 @@ -[run] -branch = True - -[report] -show_missing = True -include = *libpathod* -exclude_lines = - pragma: nocover - pragma: no cover - raise NotImplementedError() -- cgit v1.2.3 From b7af84552385fa6daf5f594ffa981f8647f7e755 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 15 Feb 2016 18:12:12 +0100 Subject: fix appveyor, re-introduce requirements.txt --- pathod/setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod/setup.py b/pathod/setup.py index ff50bdd0..3972d8ff 100644 --- a/pathod/setup.py +++ b/pathod/setup.py @@ -1,13 +1,16 @@ from setuptools import setup, find_packages from codecs import open import os -from libpathod import version +import sys # Based on https://github.com/pypa/sampleproject/blob/master/setup.py # and https://python-packaging-user-guide.readthedocs.org/ here = os.path.abspath(os.path.dirname(__file__)) +sys.path.append(os.path.join(here, "..", "netlib")) +from libpathod import version + with open(os.path.join(here, 'README.txt'), encoding='utf-8') as f: long_description = f.read() -- cgit v1.2.3 From fc9fa87827d64c770d329b24151f3ef354054d74 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 15 Feb 2016 18:43:06 +0100 Subject: fix ALPN checks --- pathod/libpathod/pathoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pathod') diff --git a/pathod/libpathod/pathoc.py b/pathod/libpathod/pathoc.py index 55c2a6e0..c0a33b62 100644 --- a/pathod/libpathod/pathoc.py +++ b/pathod/libpathod/pathoc.py @@ -207,7 +207,7 @@ class Pathoc(tcp.TCPClient): self.ws_framereader = None if self.use_http2: - if not OpenSSL._util.lib.Cryptography_HAS_ALPN: # pragma: nocover + if not tcp.HAS_ALPN: # pragma: nocover log.write_raw( self.fp, "HTTP/2 requires ALPN support. " -- cgit v1.2.3 From 3d9a5157e77b5a3237dc62994f4e3d4c75c2066e Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 15 Feb 2016 21:13:06 +0100 Subject: use own shields instance, update pathod readme --- pathod/README.mkd | 44 ---------------------------------------- pathod/README.rst | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ pathod/README.txt | 43 --------------------------------------- pathod/setup.py | 2 +- 4 files changed, 61 insertions(+), 88 deletions(-) delete mode 100644 pathod/README.mkd create mode 100644 pathod/README.rst delete mode 100644 pathod/README.txt (limited to 'pathod') diff --git a/pathod/README.mkd b/pathod/README.mkd deleted file mode 100644 index 9f8c487b..00000000 --- a/pathod/README.mkd +++ /dev/null @@ -1,44 +0,0 @@ -[![Build Status](https://img.shields.io/travis/mitmproxy/pathod/master.svg)](https://travis-ci.org/mitmproxy/pathod) -[![Code Health](https://landscape.io/github/mitmproxy/pathod/master/landscape.svg?style=flat)](https://landscape.io/github/mitmproxy/pathod/master) -[![Coverage Status](https://img.shields.io/coveralls/mitmproxy/pathod/master.svg)](https://coveralls.io/r/mitmproxy/pathod) -[![Downloads](https://img.shields.io/pypi/dm/pathod.svg?color=orange)](https://pypi.python.org/pypi/pathod) -[![Latest Version](https://img.shields.io/pypi/v/pathod.svg)](https://pypi.python.org/pypi/pathod) -[![Supported Python versions](https://img.shields.io/pypi/pyversions/pathod.svg)](https://pypi.python.org/pypi/pathod) - -__pathod__ is a collection of pathological tools for testing and torturing HTTP -clients and servers. The project has three components: - -- __pathod__, an pathological HTTP daemon. -- __pathoc__, a perverse HTTP client. -- __libpathod.test__, an API for easily using __pathod__ and __pathoc__ in unit tests. - - -# Documentation - -The pathod documentation is self-hosted. Just fire up pathod, like so: - - ./pathod - -And then browse to: - - http://localhost:9999 - -You can always view the documentation for the latest release at the pathod -website: - - http://pathod.net - -# Installing - -If you already have __pip__ on your system, installing __pathod__ and its -dependencies is dead simple: - - pip install pathod - -The project has the following dependencies: - -* [netlib](https://github.com/mitmproxy/netlib) -* [requests](http://docs.python-requests.org/en/latest/index.html) - -The project's test suite uses the -[nose](http://nose.readthedocs.org/en/latest/) unit testing framework. diff --git a/pathod/README.rst b/pathod/README.rst new file mode 100644 index 00000000..5593e053 --- /dev/null +++ b/pathod/README.rst @@ -0,0 +1,60 @@ +pathod +^^^^^^ + +|travis| |coveralls| |downloads| |latest_release| |python_versions| + +**pathod** is a collection of pathological tools for testing and torturing HTTP +clients and servers. The project has three components: + +- ``pathod``, an pathological HTTP daemon. +- ``pathoc``, a perverse HTTP client. +- ``libpathod.test``, an API for easily using pathod and pathoc in unit tests. + +Installing +---------- + +If you already have **pip** on your system, installing **pathod** and its +dependencies is dead simple: + +.. code-block:: text + + pip install pathod + +Documentation +------------- + +The pathod documentation is self-hosted. Just fire up pathod, like so: + +.. code-block:: text + + ./pathod + +And then browse to: + +``_ + +You can always view the documentation for the latest release at the pathod +website: + +``_ + + +.. |travis| image:: https://shields.mitmproxy.org/travis/mitmproxy/pathod/master.svg + :target: https://travis-ci.org/mitmproxy/pathod + :alt: Build Status + +.. |coveralls| image:: https://shields.mitmproxy.org/coveralls/mitmproxy/pathod/master.svg + :target: https://coveralls.io/r/mitmproxy/pathod + :alt: Coverage Status + +.. |downloads| image:: https://shields.mitmproxy.org/pypi/dm/pathod.svg?color=orange + :target: https://pypi.python.org/pypi/pathod + :alt: Downloads + +.. |latest_release| image:: https://shields.mitmproxy.org/pypi/v/pathod.svg + :target: https://pypi.python.org/pypi/pathod + :alt: Latest Version + +.. |python_versions| image:: https://shields.mitmproxy.org/pypi/pyversions/pathod.svg + :target: https://pypi.python.org/pypi/pathod + :alt: Supported Python versions \ No newline at end of file diff --git a/pathod/README.txt b/pathod/README.txt deleted file mode 100644 index f8fbdac5..00000000 --- a/pathod/README.txt +++ /dev/null @@ -1,43 +0,0 @@ -**pathod** is a collection of pathological tools for testing and torturing HTTP -clients and servers. The project has three components: - -- **pathod**, an pathological HTTP daemon. -- **pathoc**, a perverse HTTP client. -- **libpathod.test**, an API for easily using pathod and pathoc in unit tests. - - -Documentation -------------- - -The pathod documentation is self-hosted. Just fire up pathod, like so: - - ./pathod - -And then browse to: - - http://localhost:9999 - -You can always view the documentation for the latest release at the pathod -website: - - http://pathod.net - - -Installing ----------- - -If you already have **pip** on your system, installing **pathod** and its -dependencies is dead simple: - - pip install pathod - -The project has the following dependencies: - -* netlib_ -* requests_ - -The project's test suite uses the nose_ unit testing framework. - -.. _netlib: https://github.com/mitmproxy/netlib -.. _requests: http://docs.python-requests.org/en/latest/index.html -.. _nose: http://nose.readthedocs.org/en/latest/ diff --git a/pathod/setup.py b/pathod/setup.py index 3972d8ff..ba329eda 100644 --- a/pathod/setup.py +++ b/pathod/setup.py @@ -11,7 +11,7 @@ here = os.path.abspath(os.path.dirname(__file__)) sys.path.append(os.path.join(here, "..", "netlib")) from libpathod import version -with open(os.path.join(here, 'README.txt'), encoding='utf-8') as f: +with open(os.path.join(here, 'README.rst'), encoding='utf-8') as f: long_description = f.read() setup( -- cgit v1.2.3