aboutsummaryrefslogtreecommitdiffstats
path: root/libpathod/pathod.py
blob: edf6e03a63b6411d7ef3adb3ec6804e7e5c576ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import urllib, threading
from netlib import tcp, protocol, odict, wsgi
import version, app, rparse


class PathodHandler(tcp.BaseHandler):
    def handle(self):
        if self.server.ssloptions:
            self.convert_to_ssl(
                self.server.ssloptions["certfile"],
                self.server.ssloptions["keyfile"],
            )

        line = self.rfile.readline()
        if line == "\r\n" or line == "\n": # Possible leftover from previous message
            line = self.rfile.readline()
        if line == "":
            return None

        method, path, httpversion = protocol.parse_init_http(line)
        headers = odict.ODictCaseless(protocol.read_headers(self.rfile))
        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:
                presp = rparse.parse({}, spec)
            except rparse.ParseException, v:
                presp = rparse.InternalResponse(
                    800,
                    "Error parsing response spec: %s\n"%v.msg + v.marked()
                )
            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)
            sn = self.connection.getsockname()
            app = wsgi.WSGIAdaptor(
                self.server.app,
                sn[0],
                self.server.port,
                version.NAMEVERSION
            )
            app.serve(req, self.wfile)


class Pathod(tcp.TCPServer):
    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