PageRenderTime 16ms CodeModel.GetById 9ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/circuits/net/protocols/http.py

https://bitbucket.org/prologic/circuits/
Python | 78 lines | 54 code | 22 blank | 2 comment | 6 complexity | b02d75f5286292e494eed7dc158a791a MD5 | raw file
 1
 2from io import BytesIO
 3
 4from circuits.web.headers import parse_headers
 5from circuits.core import handler, BaseComponent, Event
 6
 7class Request(Event):
 8    """Request Event"""
 9
10    success = "request_success",
11    failure = "request_failure",
12
13class Response(Event):
14    """Response Event"""
15
16class ResponseObject(object):
17
18    def __init__(self, status, message, protocol=None):
19        self.status = status
20        self.message = message
21        self.protocol = protocol
22
23        self._headers = None
24        self._body = BytesIO()
25
26    @property
27    def headers(self):
28        return self._headers
29
30    def read(self):
31        return self._body.read()
32
33class HTTP(BaseComponent):
34
35    channel = "web"
36
37    def __init__(self, encoding="utf-8", channel=channel):
38        super(HTTP, self).__init__(channel=channel)
39
40        self._encoding = encoding
41
42        self._response = None
43        self._buffer = BytesIO()
44
45    @handler("read", target="client")
46    def _on_client_read(self, data):
47        if self._response is not None:
48            self._response._body.write(data)
49            cLen = int(self._response.headers.get("Content-Length", "0"))
50            if cLen and self._response._body.tell() == cLen:
51                self._response._body.seek(0)
52                self.fire(Response(self._response))
53                self._response = None
54        else:
55            statusline, data = data.split(b"\r\n", 1)
56            statusline = statusline.strip().decode(
57                    self._encoding, "replace")
58            protocol, status, message = statusline.split(" ", 2)
59
60            status = int(status)
61            protocol = tuple(map(int, protocol[5:].split(".")))
62
63            response = ResponseObject(status, message, protocol)
64
65            end_of_headers = data.find(b"\r\n\r\n")
66            header_data = data[:end_of_headers].decode(
67                    self._encoding, "replace")
68            headers = response._headers = parse_headers(header_data)
69
70            response._body.write(data[(end_of_headers + 4):])
71
72            cLen = int(headers.get("Content-Length", "0"))
73            if cLen and response._body.tell() < cLen:
74                self._response = response
75                return
76
77            response._body.seek(0)
78            self.fire(Response(response))