Restore client argument parsing. Add thread-safe logging subsystem.

This commit is contained in:
Aldo Cortesi 2012-06-21 14:29:49 +12:00
parent 1089a52f3d
commit 12c140b951
4 changed files with 99 additions and 63 deletions

View File

@ -1,4 +1,4 @@
import urllib
import urllib, threading
from netlib import tcp, protocol, odict, wsgi
import version, app, rparse
@ -22,6 +22,7 @@ class PathodHandler(tcp.BaseHandler):
content = protocol.read_http_body_request(
self.rfile, self.wfile, headers, httpversion, None
)
if path.startswith(self.server.prefix):
spec = urllib.unquote(path)[len(self.server.prefix):]
try:
@ -34,6 +35,7 @@ class PathodHandler(tcp.BaseHandler):
ret = presp.serve(self.wfile)
if ret["disconnect"]:
self.close()
self.server.add_log(ret)
else:
cc = wsgi.ClientConn(self.client_address)
req = wsgi.Request(cc, "http", method, path, headers, content)
@ -48,12 +50,38 @@ class PathodHandler(tcp.BaseHandler):
class Pathod(tcp.TCPServer):
def __init__(self, addr, ssloptions=None, prefix="/p/"):
LOGBUF = 500
def __init__(self, addr, ssloptions=None, prefix="/p/", staticdir=None, anchors=None):
tcp.TCPServer.__init__(self, addr)
self.ssloptions = ssloptions
self.prefix = prefix
self.app = app.app
self.app.config["pathod"] = self
self.log = []
self.logid = 0
def handle_connection(self, request, client_address):
PathodHandler(request, client_address, self)
def add_log(self, d):
lock = threading.Lock()
with lock:
d["id"] = self.logid
self.log.insert(0, d)
if len(self.log) > self.LOGBUF:
self.log.pop()
self.logid += 1
return d["id"]
def clear_log(self):
lock = threading.Lock()
with lock:
self.log = []
def log_by_id(self, id):
for i in self.log:
if i["id"] == id:
return i
def get_log(self):
return self.log

56
opathod
View File

@ -1,56 +0,0 @@
#!/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.')
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

58
pathod
View File

@ -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

View File

@ -31,5 +31,17 @@ class _TestApplication:
class TestPathod:
def test_instantiation(self):
pathod.Pathod(("127.0.0.1", 0))
p = pathod.Pathod(("127.0.0.1", 0))
def test_logging(self):
p = pathod.Pathod(("127.0.0.1", 0))
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 i in range(p.LOGBUF + 1):
p.add_log(dict(s="foo"))
assert len(p.get_log()) <= p.LOGBUF