| 166 | """ |
| 167 | |
| 168 | def __call__(self, out, buf): |
| 169 | # read HTTP message (request line + headers) |
| 170 | try: |
| 171 | raw_data = yield from buf.readuntil( |
| 172 | b'\r\n\r\n', self.max_headers) |
| 173 | except errors.LineLimitExceededParserError as exc: |
| 174 | raise errors.LineTooLong(exc.limit) from None |
| 175 | |
| 176 | lines = raw_data.split(b'\r\n') |
| 177 | |
| 178 | # request line |
| 179 | line = lines[0].decode('utf-8', 'surrogateescape') |
| 180 | try: |
| 181 | method, path, version = line.split(None, 2) |
| 182 | except ValueError: |
| 183 | raise errors.BadStatusLine(line) from None |
| 184 | |
| 185 | # method |
| 186 | method = method.upper() |
| 187 | if not METHRE.match(method): |
| 188 | raise errors.BadStatusLine(method) |
| 189 | |
| 190 | # version |
| 191 | try: |
| 192 | if version.startswith('HTTP/'): |
| 193 | n1, n2 = version[5:].split('.', 1) |
| 194 | version = HttpVersion(int(n1), int(n2)) |
| 195 | else: |
| 196 | raise errors.BadStatusLine(version) |
| 197 | except: |
| 198 | raise errors.BadStatusLine(version) |
| 199 | |
| 200 | # read headers |
| 201 | headers, raw_headers, close, compression = self.parse_headers(lines) |
| 202 | if close is None: # then the headers weren't set in the request |
| 203 | if version <= HttpVersion10: # HTTP 1.0 must asks to not close |
| 204 | close = True |
| 205 | else: # HTTP 1.1 must ask to close. |
| 206 | close = False |
| 207 | |
| 208 | out.feed_data( |
| 209 | RawRequestMessage( |
| 210 | method, path, version, headers, raw_headers, |
| 211 | close, compression), |
| 212 | len(raw_data)) |
| 213 | out.feed_eof() |
| 214 | |
| 215 | |
| 216 | class HttpResponseParser(HttpParser): |