-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcyhttp11.pyx
More file actions
175 lines (141 loc) · 6.18 KB
/
cyhttp11.pyx
File metadata and controls
175 lines (141 loc) · 6.18 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# -*- coding: utf-8 -*-
cimport cyhttp11
ctypedef Py_ssize_t ssize_t
class CyHTTPException(Exception):
ERROR_STR = {
ERR_OFFSET_PAST_BUFFER : "Offset past end of buffer",
ERR_OVERFLOW_AFTER_PARSE : "Buffer overflow after parsing",
ERR_NREAD_OVERFLOW : "nread longer than length",
ERR_BODY_OVERFLOW : "Body starts after buffer end",
ERR_MARK_OVERFLOW : "Mark is after buffer end",
ERR_FIELD_LEN_OVERFLOW : "Field has length longer than whole buffer",
ERR_FIELD_START_OVERFLOW : "Field starts after buffer end",
}
def __str__(self):
return "CyHTTPException : %i %s" % (self.args[0], self.ERROR_STR[self.args[0]])
cdef class HTTPHeaders(dict):
def __contains__(self, key):
return dict.__contains__(self, key.title())
def __getitem__(self, key):
return dict.__getitem__(self, key.title())
def __setitem__(self, key, value):
dict.__setitem__(self, key.title(), value)
def __delitem__(self, key):
dict.__delitem__(self, key.title())
# The parser's callbacks
cdef void _http_field(void *data, char *field, size_t flen, char *value, size_t vlen):
result = <object>data
result.headers[field[:flen]] = value[:vlen]
cdef void _element_cb(void *data, char *attribute, char *at, size_t length):
result = <object>data
setattr(result, unicode(attribute), at[:length])
cdef void _request_method(void *data, char *at, size_t length):
result = <object>data
result.request_method = at[:length]
cdef void _request_uri(void *data, char *at, size_t length):
result = <object>data
result.request_uri = at[:length]
cdef void _fragment(void *data, char *at, size_t length):
result = <object>data
result.fragment = at[:length]
cdef void _request_path(void *data, char *at, size_t length):
result = <object>data
result.request_path = at[:length]
cdef void _query_string(void *data, char *at, size_t length):
result = <object>data
result.query_string = at[:length]
cdef void _status_code(void *data, char *at, size_t length):
result = <object>data
result.status_code = int(at[:length])
cdef void _reason_phrase(void *data, char *at, size_t length):
result = <object>data
result.reason_phrase = at[:length]
cdef void _http_version(void *data, char *at, size_t length):
result = <object>data
result.http_version = at[:length]
cdef void _header_done(void *data, char *at, size_t length):
result = <object>data
result.body = at[:length]
cdef class HTTPParser:
"""
This is a docstring for this class.
"""
cdef cyhttp11.http_parser _http_parser
cdef public HTTPHeaders headers
cdef public bytes request_method
cdef public bytes request_uri
cdef public bytes fragment
cdef public bytes request_path
cdef public bytes query_string
cdef public bytes http_version
cdef public bytes body
def __cinit__(self):
self._http_parser.data = <void*>self
self._http_parser.http_field = <field_cb>_http_field
self._http_parser.request_method = <element_cb>_request_method
self._http_parser.request_uri = <element_cb>_request_uri
self._http_parser.fragment = <element_cb>_fragment
self._http_parser.request_path = <element_cb>_request_path
self._http_parser.query_string = <element_cb>_query_string
self._http_parser.http_version = <element_cb>_http_version
self._http_parser.header_done = <element_cb>_header_done
self.reset()
def execute(self, bytes):
ret = cyhttp11.http_parser_execute(&self._http_parser,
bytes,
len(bytes),
self._http_parser.nread)
if ret < 0:
raise CyHTTPException(-ret)
return ret
def is_finished(self):
return cyhttp11.http_parser_is_finished(&self._http_parser)
def has_error(self):
return cyhttp11.http_parser_has_error(&self._http_parser)
def reset(self):
cyhttp11.http_parser_init(&self._http_parser)
self.headers = HTTPHeaders()
self.request_method = b''
self.request_uri = b''
self.fragment = b''
self.request_path = b''
self.query_string = b''
self.http_version = b''
self.body = b''
cdef class HTTPClientParser:
"""
This is a docstring for this class.
"""
cdef cyhttp11.httpclient_parser _httpclient_parser
cdef public HTTPHeaders headers
cdef public int status_code
cdef public bytes reason_phrase
cdef public bytes http_version
cdef public bytes body
def __cinit__(self):
self._httpclient_parser.data = <void*>self
self._httpclient_parser.http_field = <field_cb>_http_field
self._httpclient_parser.status_code = <element_cb>_status_code
self._httpclient_parser.reason_phrase = <element_cb>_reason_phrase
self._httpclient_parser.http_version = <element_cb>_http_version
self._httpclient_parser.header_done = <element_cb>_header_done
self.reset()
def execute(self, bytes):
ret = cyhttp11.httpclient_parser_execute(&self._httpclient_parser,
bytes,
len(bytes),
self._httpclient_parser.nread)
if ret < 0:
raise CyHTTPException(-ret)
return ret
def is_finished(self):
return cyhttp11.httpclient_parser_is_finished(&self._httpclient_parser)
def has_error(self):
return cyhttp11.httpclient_parser_has_error(&self._httpclient_parser)
def reset(self):
cyhttp11.httpclient_parser_init(&self._httpclient_parser)
self.headers = HTTPHeaders()
self.status_code = -1
self.reason_phrase = b''
self.http_version = b''
self.body = b''