Parses RFC 5322 headers from a stream. Line continuations are supported. Returns list of header name and value pairs. Header name is in upper case.
(self, lines)
| 61 | self.max_field_size = max_field_size |
| 62 | |
| 63 | def parse_headers(self, lines): |
| 64 | """Parses RFC 5322 headers from a stream. |
| 65 | |
| 66 | Line continuations are supported. Returns list of header name |
| 67 | and value pairs. Header name is in upper case. |
| 68 | """ |
| 69 | close_conn = None |
| 70 | encoding = None |
| 71 | headers = CIMultiDict() |
| 72 | raw_headers = [] |
| 73 | |
| 74 | lines_idx = 1 |
| 75 | line = lines[1] |
| 76 | |
| 77 | while line: |
| 78 | header_length = len(line) |
| 79 | |
| 80 | # Parse initial header name : value pair. |
| 81 | try: |
| 82 | bname, bvalue = line.split(b':', 1) |
| 83 | except ValueError: |
| 84 | raise errors.InvalidHeader(line) from None |
| 85 | |
| 86 | bname = bname.strip(b' \t').upper() |
| 87 | if HDRRE.search(bname): |
| 88 | raise errors.InvalidHeader(bname) |
| 89 | |
| 90 | # next line |
| 91 | lines_idx += 1 |
| 92 | line = lines[lines_idx] |
| 93 | |
| 94 | # consume continuation lines |
| 95 | continuation = line and line[0] in (32, 9) # (' ', '\t') |
| 96 | |
| 97 | if continuation: |
| 98 | bvalue = [bvalue] |
| 99 | while continuation: |
| 100 | header_length += len(line) |
| 101 | if header_length > self.max_field_size: |
| 102 | raise errors.LineTooLong( |
| 103 | 'limit request headers fields size') |
| 104 | bvalue.append(line) |
| 105 | |
| 106 | # next line |
| 107 | lines_idx += 1 |
| 108 | line = lines[lines_idx] |
| 109 | continuation = line[0] in (32, 9) # (' ', '\t') |
| 110 | bvalue = b'\r\n'.join(bvalue) |
| 111 | else: |
| 112 | if header_length > self.max_field_size: |
| 113 | raise errors.LineTooLong( |
| 114 | 'limit request headers fields size') |
| 115 | |
| 116 | bvalue = bvalue.strip() |
| 117 | |
| 118 | name = bname.decode('utf-8', 'surrogateescape') |
| 119 | value = bvalue.decode('utf-8', 'surrogateescape') |
| 120 |