Skip to content

Commit e8d9019

Browse files
Brandon McGinty-CarrollRX14
Brandon McGinty-Carroll
authored andcommittedOct 14, 2017
ensure propper handling of multiple Content-Length headers (#4705)
When multiple Content-Length headers are received, error out if all received values do not match. Return a single Content-Length header value.
1 parent 1d02669 commit e8d9019

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed
 

Diff for: ‎spec/std/http/request_spec.cr

+28
Original file line numberDiff line numberDiff line change
@@ -347,5 +347,33 @@ module HTTP
347347
request.host_with_port.should eq("host.example.org:3000")
348348
end
349349
end
350+
351+
it "doesn't raise on request with multiple Content_length headers" do
352+
io = IO::Memory.new <<-REQ
353+
GET / HTTP/1.1
354+
Host: host
355+
Content-Length: 5
356+
Content-Length: 5
357+
Content-Type: text/plain
358+
359+
abcde
360+
REQ
361+
HTTP::Request.from_io(io)
362+
end
363+
364+
it "raises if request has multiple and differing content-length headers" do
365+
io = IO::Memory.new <<-REQ
366+
GET / HTTP/1.1
367+
Host: host
368+
Content-Length: 5
369+
Content-Length: 6
370+
Content-Type: text/plain
371+
372+
abcde
373+
REQ
374+
expect_raises(ArgumentError) do
375+
HTTP::Request.from_io(io)
376+
end
377+
end
350378
end
351379
end

Diff for: ‎src/http/common.cr

+8-3
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ module HTTP
2626
body = nil
2727
if body_type.prohibited?
2828
body = nil
29-
elsif content_length = headers["Content-Length"]?
30-
content_length = content_length.to_u64
29+
elsif content_length = content_length(headers)
3130
if content_length != 0
3231
# Don't create IO for Content-Length == 0
3332
body = FixedLengthContent.new(io, content_length)
@@ -166,7 +165,13 @@ module HTTP
166165

167166
# :nodoc:
168167
def self.content_length(headers)
169-
headers["Content-Length"]?.try &.to_u64?
168+
length_headers = headers.get? "Content-Length"
169+
return nil unless length_headers
170+
first_header = length_headers[0]
171+
if length_headers.size > 1 && length_headers.any? { |header| header != first_header }
172+
raise ArgumentError.new("Multiple Content-Length headers received did not match: #{length_headers}")
173+
end
174+
first_header.to_u64
170175
end
171176

172177
# :nodoc:

0 commit comments

Comments
 (0)
Please sign in to comment.