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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
from ..odict import ODict
from .. import utils, encoding
from ..utils import always_bytes, native
from . import cookies
from .headers import Headers
from six.moves import urllib
# TODO: Move somewhere else?
ALPN_PROTO_HTTP1 = b'http/1.1'
ALPN_PROTO_H2 = b'h2'
HDR_FORM_URLENCODED = "application/x-www-form-urlencoded"
HDR_FORM_MULTIPART = "multipart/form-data"
CONTENT_MISSING = 0
class Message(object):
def __init__(self, http_version, headers, body, timestamp_start, timestamp_end):
self.http_version = http_version
if not headers:
headers = Headers()
assert isinstance(headers, Headers)
self.headers = headers
self._body = body
self.timestamp_start = timestamp_start
self.timestamp_end = timestamp_end
@property
def body(self):
return self._body
@body.setter
def body(self, body):
self._body = body
if isinstance(body, bytes):
self.headers["content-length"] = str(len(body)).encode()
content = body
def __eq__(self, other):
if isinstance(other, Message):
return self.__dict__ == other.__dict__
return False
class Response(Message):
def __init__(
self,
http_version,
status_code,
msg=None,
headers=None,
body=None,
timestamp_start=None,
timestamp_end=None,
):
super(Response, self).__init__(http_version, headers, body, timestamp_start, timestamp_end)
self.status_code = status_code
self.msg = msg
def __repr__(self):
# return "Response(%s - %s)" % (self.status_code, self.msg)
if self.body:
size = utils.pretty_size(len(self.body))
else:
size = "content missing"
# TODO: Remove "(unknown content type, content missing)" edge-case
return "<Response: {status_code} {msg} ({contenttype}, {size})>".format(
status_code=self.status_code,
msg=self.msg,
contenttype=self.headers.get("content-type", "unknown content type"),
size=size)
def get_cookies(self):
"""
Get the contents of all Set-Cookie headers.
Returns a possibly empty ODict, where keys are cookie name strings,
and values are [value, attr] lists. Value is a string, and attr is
an ODictCaseless containing cookie attributes. Within attrs, unary
attributes (e.g. HTTPOnly) are indicated by a Null value.
"""
ret = []
for header in self.headers.get_all("set-cookie"):
v = cookies.parse_set_cookie_header(header)
if v:
name, value, attrs = v
ret.append([name, [value, attrs]])
return ODict(ret)
def set_cookies(self, odict):
"""
Set the Set-Cookie headers on this response, over-writing existing
headers.
Accepts an ODict of the same format as that returned by get_cookies.
"""
values = []
for i in odict.lst:
values.append(
cookies.format_set_cookie_header(
i[0],
i[1][0],
i[1][1]
)
)
self.headers.set_all("set-cookie", values)
|