1
- # cython: language_level=3, freethreading_compatible = True
1
+ # cython: language_level=3
2
2
#
3
3
# Based on https://github.com/MagicStack/httptools
4
4
#
@@ -12,20 +12,10 @@ from cpython cimport (
12
12
PyObject_GetBuffer,
13
13
)
14
14
from cpython.mem cimport PyMem_Free, PyMem_Malloc
15
- from cpython.object cimport PyObject
16
15
from libc.limits cimport ULLONG_MAX
17
16
from libc.string cimport memcpy
18
- from multidict cimport (
19
- CIMultiDict,
20
- CIMultiDict_Add,
21
- CIMultiDict_Contains,
22
- CIMultiDict_New,
23
- CIMultiDictProxy,
24
- CIMultiDictProxy_GetOne,
25
- CIMultiDictProxy_New,
26
- multidict_import,
27
- )
28
17
18
+ from multidict import CIMultiDict as _CIMultiDict, CIMultiDictProxy as _CIMultiDictProxy
29
19
from yarl import URL as _URL
30
20
31
21
from aiohttp import hdrs
@@ -58,9 +48,6 @@ include "_headers.pxi"
58
48
59
49
from aiohttp cimport _find_header
60
50
61
- # import multidict capsule...
62
- multidict_import()
63
-
64
51
ALLOWED_UPGRADES = frozenset ({" websocket" })
65
52
DEF DEFAULT_FREELIST_SIZE = 250
66
53
@@ -74,6 +61,8 @@ __all__ = ('HttpRequestParser', 'HttpResponseParser',
74
61
75
62
cdef object URL = _URL
76
63
cdef object URL_build = URL.build
64
+ cdef object CIMultiDict = _CIMultiDict
65
+ cdef object CIMultiDictProxy = _CIMultiDictProxy
77
66
cdef object HttpVersion = _HttpVersion
78
67
cdef object HttpVersion10 = _HttpVersion10
79
68
cdef object HttpVersion11 = _HttpVersion11
@@ -124,8 +113,8 @@ cdef class RawRequestMessage:
124
113
cdef readonly str method
125
114
cdef readonly str path
126
115
cdef readonly object version # HttpVersion
127
- cdef readonly CIMultiDictProxy headers # CIMultiDictProxy
128
- cdef readonly CIMultiDict raw_headers # CIMultiDict
116
+ cdef readonly object headers # CIMultiDict
117
+ cdef readonly object raw_headers # tuple
129
118
cdef readonly object should_close
130
119
cdef readonly object compression
131
120
cdef readonly object upgrade
@@ -197,8 +186,8 @@ cdef class RawRequestMessage:
197
186
cdef _new_request_message(str method,
198
187
str path,
199
188
object version,
200
- CIMultiDictProxy headers,
201
- CIMultiDict raw_headers,
189
+ object headers,
190
+ object raw_headers,
202
191
bint should_close,
203
192
object compression,
204
193
bint upgrade,
@@ -224,9 +213,8 @@ cdef class RawResponseMessage:
224
213
cdef readonly object version # HttpVersion
225
214
cdef readonly int code
226
215
cdef readonly str reason
227
- # Temporary Note: We can now expose the real types thanks to the new cython-api
228
- cdef readonly CIMultiDictProxy headers
229
- cdef readonly CIMultiDict raw_headers
216
+ cdef readonly object headers # CIMultiDict
217
+ cdef readonly object raw_headers # tuple
230
218
cdef readonly object should_close
231
219
cdef readonly object compression
232
220
cdef readonly object upgrade
@@ -262,8 +250,8 @@ cdef class RawResponseMessage:
262
250
cdef _new_response_message(object version,
263
251
int code,
264
252
str reason,
265
- CIMultiDictProxy headers,
266
- CIMultiDict raw_headers,
253
+ object headers,
254
+ object raw_headers,
267
255
bint should_close,
268
256
object compression,
269
257
bint upgrade,
@@ -309,8 +297,8 @@ cdef class HttpParser:
309
297
bytearray _buf
310
298
str _path
311
299
str _reason
312
- CIMultiDict _headers
313
- CIMultiDict _raw_headers
300
+ list _headers
301
+ list _raw_headers
314
302
bint _upgraded
315
303
list _messages
316
304
object _payload
@@ -396,13 +384,13 @@ cdef class HttpParser:
396
384
name = find_header(self ._raw_name)
397
385
value = self ._raw_value.decode(' utf-8' , ' surrogateescape' )
398
386
399
- CIMultiDict_Add( self ._headers, name, value)
387
+ self ._headers.append(( name, value) )
400
388
401
389
if name is CONTENT_ENCODING:
402
390
self ._content_encoding = value
403
391
404
392
self ._has_value = False
405
- CIMultiDict_Add( self ._raw_headers, self ._raw_name, self ._raw_value)
393
+ self ._raw_headers.append(( self ._raw_name, self ._raw_value) )
406
394
self ._raw_name = EMPTY_BYTES
407
395
self ._raw_value = EMPTY_BYTES
408
396
@@ -423,34 +411,25 @@ cdef class HttpParser:
423
411
self ._has_value = True
424
412
425
413
cdef _on_headers_complete(self ):
426
- cdef CIMultiDictProxy headers
427
- cdef CIMultiDict raw_headers
428
- cdef PyObject* upgrade_value
429
- cdef bint allowed = 0
430
-
431
414
self ._process_header()
432
415
433
416
should_close = not cparser.llhttp_should_keep_alive(self ._cparser)
434
417
upgrade = self ._cparser.upgrade
435
418
chunked = self ._cparser.flags & cparser.F_CHUNKED
436
419
437
- raw_headers = self ._raw_headers
438
- headers = CIMultiDictProxy_New( self ._headers)
420
+ raw_headers = tuple ( self ._raw_headers)
421
+ headers = CIMultiDictProxy(CIMultiDict( self ._headers) )
439
422
440
423
if self ._cparser.type == cparser.HTTP_REQUEST:
441
- if upgrade and CIMultiDictProxy_GetOne(headers, " upgrade" , & upgrade_value):
442
- self ._upgraded = (
443
- (< str > upgrade_value).lower() in ALLOWED_UPGRADES
444
- or self ._cparser.method == cparser.HTTP_CONNECT
445
- )
446
- elif self ._cparser.method == cparser.HTTP_CONNECT:
424
+ allowed = upgrade and headers.get(" upgrade" , " " ).lower() in ALLOWED_UPGRADES
425
+ if allowed or self ._cparser.method == cparser.HTTP_CONNECT:
447
426
self ._upgraded = True
448
427
else :
449
428
if upgrade and self ._cparser.status_code == 101 :
450
429
self ._upgraded = True
451
430
452
431
# do not support old websocket spec
453
- if CIMultiDict_Contains(headers, SEC_WEBSOCKET_KEY1) :
432
+ if SEC_WEBSOCKET_KEY1 in headers :
454
433
raise InvalidHeader(SEC_WEBSOCKET_KEY1)
455
434
456
435
encoding = None
@@ -617,7 +596,7 @@ cdef class HttpRequestParser(HttpParser):
617
596
if self ._cparser.method == cparser.HTTP_CONNECT:
618
597
# authority-form,
619
598
# https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3
620
- self ._url = URL_build (authority = self ._path, encoded = True )
599
+ self ._url = URL.build (authority = self ._path, encoded = True )
621
600
elif idx3 > 1 and self ._path[0 ] == ' /' :
622
601
# origin-form,
623
602
# https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1
@@ -643,7 +622,7 @@ cdef class HttpRequestParser(HttpParser):
643
622
query = self ._path[idx1: idx2]
644
623
fragment = self ._path[idx2+ 1 :]
645
624
646
- self ._url = URL_build (
625
+ self ._url = URL.build (
647
626
path = path,
648
627
query_string = query,
649
628
fragment = fragment,
@@ -687,9 +666,8 @@ cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1:
687
666
cdef HttpParser pyparser = < HttpParser> parser.data
688
667
689
668
pyparser._started = True
690
- # Not Certain yet if 5 is a good solid number of headers to preallocate yet...
691
- pyparser._headers = CIMultiDict_New(5 )
692
- pyparser._raw_headers = CIMultiDict_New(5 )
669
+ pyparser._headers = []
670
+ pyparser._raw_headers = []
693
671
PyByteArray_Resize(pyparser._buf, 0 )
694
672
pyparser._path = None
695
673
pyparser._reason = None
0 commit comments