Commit | Line | Data |
---|---|---|
c270f222 FT |
1 | import os, socket |
2 | import htlib | |
3 | ||
4 | class protoerr(Exception): | |
5 | pass | |
6 | ||
7 | class req(object): | |
8 | def __init__(self, method, url, ver, rest, headers, fd): | |
9 | self.method = method | |
10 | self.url = url | |
11 | self.ver = ver | |
12 | self.rest = rest | |
13 | self.headers = headers | |
14 | self.sk = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM).makefile('r+') | |
15 | os.close(fd) | |
16 | ||
17 | def close(self): | |
18 | self.sk.close() | |
19 | ||
20 | def __getitem__(self, header): | |
21 | header = header.lower() | |
22 | for key, val in self.headers: | |
23 | if key.lower() == header: | |
24 | return val | |
25 | raise KeyError(header) | |
26 | ||
27 | def __contains__(self, header): | |
28 | header = header.lower() | |
29 | for key, val in self.headers: | |
30 | if key.lower() == header: | |
31 | return True | |
32 | return False | |
33 | ||
34 | def dup(self): | |
35 | return req(self.method, self.url, self.ver, self.rest, self.headers, os.dup(self.sk.fileno())) | |
36 | ||
37 | def match(self, match): | |
38 | if self.rest[:len(match)] == match: | |
39 | self.rest = self.rest[len(match):] | |
40 | return True | |
41 | return False | |
42 | ||
43 | def __str__(self): | |
44 | return "\"%s %s %s\"" % (self.method, self.url, self.ver) | |
45 | ||
46 | def __enter__(self): | |
47 | return self | |
48 | ||
49 | def __exit__(self, *excinfo): | |
50 | self.sk.close() | |
51 | return False | |
52 | ||
53 | def recvreq(sock = 0): | |
54 | data, fd = htlib.recvfd(sock) | |
55 | if fd is None: | |
56 | return None | |
57 | try: | |
c270f222 FT |
58 | parts = data.split('\0')[:-1] |
59 | if len(parts) < 5: | |
60 | raise protoerr("Truncated request") | |
61 | method, url, ver, rest = parts[:4] | |
62 | headers = [] | |
63 | i = 4 | |
64 | while True: | |
65 | if parts[i] == "": break | |
66 | if len(parts) - i < 3: | |
67 | raise protoerr("Truncated request") | |
68 | headers.append((parts[i], parts[i + 1])) | |
69 | i += 2 | |
70 | return req(method, url, ver, rest, headers, os.dup(fd)) | |
71 | finally: | |
72 | os.close(fd) | |
73 | ||
74 | def sendreq(sock, req): | |
75 | data = "" | |
76 | data += req.method + '\0' | |
77 | data += req.url + '\0' | |
78 | data += req.ver + '\0' | |
79 | data += req.rest + '\0' | |
80 | for key, val in req.headers: | |
81 | data += key + '\0' | |
82 | data += val + '\0' | |
83 | data += '\0' | |
84 | htlib.sendfd(sock, req.sk.fileno(), data) |