@@ -118,7 +118,7 @@ def raw_items(self):
118
118
119
119
def normalize_and_validate (headers , _parsed = False ):
120
120
new_headers = []
121
- saw_content_length = False
121
+ seen_content_length = None
122
122
saw_transfer_encoding = False
123
123
for name , value in headers :
124
124
# For headers coming out of the parser, we can safely skip some steps,
@@ -132,11 +132,17 @@ def normalize_and_validate(headers, _parsed=False):
132
132
raw_name = name
133
133
name = name .lower ()
134
134
if name == b"content-length" :
135
- if saw_content_length :
136
- raise LocalProtocolError ("multiple Content-Length headers" )
135
+ lengths = set (length .strip () for length in value .split (b"," ))
136
+ if len (lengths ) != 1 :
137
+ raise LocalProtocolError ("conflicting Content-Length headers" )
138
+ value = lengths .pop ()
137
139
validate (_content_length_re , value , "bad Content-Length" )
138
- saw_content_length = True
139
- if name == b"transfer-encoding" :
140
+ if seen_content_length is None :
141
+ seen_content_length = value
142
+ new_headers .append ((raw_name , name , value ))
143
+ elif seen_content_length != value :
144
+ raise LocalProtocolError ("conflicting Content-Length headers" )
145
+ elif name == b"transfer-encoding" :
140
146
# "A server that receives a request message with a transfer coding
141
147
# it does not understand SHOULD respond with 501 (Not
142
148
# Implemented)."
@@ -154,7 +160,9 @@ def normalize_and_validate(headers, _parsed=False):
154
160
error_status_hint = 501 ,
155
161
)
156
162
saw_transfer_encoding = True
157
- new_headers .append ((raw_name , name , value ))
163
+ new_headers .append ((raw_name , name , value ))
164
+ else :
165
+ new_headers .append ((raw_name , name , value ))
158
166
return Headers (new_headers )
159
167
160
168
0 commit comments