1010from collections import namedtuple
1111
1212
13- Request = namedtuple (
14- 'Request' , ['method' , 'path' , 'minor_version' , 'headers' , 'consumed' ]
15- )
1613Response = namedtuple (
1714 'Response' , ['status' , 'msg' , 'minor_version' , 'headers' , 'consumed' ]
1815)
@@ -27,25 +24,14 @@ class ParseError(Exception):
2724
2825class Parser (object ):
2926 """
30- A single HTTP parser object. This object can parse HTTP requests and
31- responses using picohttpparser.
27+ A single HTTP parser object.
3228 This object is not thread-safe, and it does maintain state that is shared
3329 across parsing requests. For this reason, make sure that access to this
3430 object is synchronized if you use it across multiple threads.
3531 """
3632 def __init__ (self ):
3733 pass
3834
39- def parse_request (self , buffer ):
40- """
41- Parses a single HTTP request from a buffer.
42- :param buffer: A ``memoryview`` object wrapping a buffer containing a
43- HTTP request.
44- :returns: A :class:`Request <hyper.http11.parser.Request>` object, or
45- ``None`` if there is not enough data in the buffer.
46- """
47- pass
48-
4935 def parse_response (self , buffer ):
5036 """
5137 Parses a single HTTP response from a buffer.
@@ -54,4 +40,43 @@ def parse_response(self, buffer):
5440 :returns: A :class:`Response <hyper.http11.parser.Response>` object, or
5541 ``None`` if there is not enough data in the buffer.
5642 """
57- pass
43+ # Begin by copying the data out of the buffer. This is necessary
44+ # because as much as possible we want to use the built-in bytestring
45+ # methods, rather than looping over the data in Python.
46+ temp_buffer = buffer .tobytes ()
47+
48+ index = temp_buffer .find (b'\n ' )
49+ if index == - 1 :
50+ return None
51+
52+ version , status , reason = temp_buffer [0 :index ].split (None , 2 )
53+ if not version .startswith (b'HTTP/1.' ):
54+ raise ParseError ("Not HTTP/1.X!" )
55+
56+ minor_version = int (version [7 :])
57+ status = int (status )
58+ reason = memoryview (reason .strip ())
59+
60+ # Chomp the newline.
61+ index += 1
62+
63+ # Now, parse the headers out.
64+ end_index = index
65+ headers = []
66+
67+ while True :
68+ end_index = temp_buffer .find (b'\n ' , index )
69+ if end_index == - 1 :
70+ return None
71+ elif (end_index - index ) <= 1 :
72+ # Chomp the newline
73+ end_index += 1
74+ break
75+
76+ name , value = temp_buffer [index :end_index ].split (b':' , 1 )
77+ value = value .strip ()
78+ headers .append ((memoryview (name ), memoryview (value )))
79+ index = end_index + 1
80+
81+ resp = Response (status , reason , minor_version , headers , end_index )
82+ return resp
0 commit comments