Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/protocol/http1/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module HTTP1
OWS = /[ \t]*/
# A field value is any string of characters that does not contain a null character, CR, or LF. After reflecting on the RFCs and surveying real implementations, I came to the conclusion that the RFCs are too restrictive. Most servers only check for the presence of null bytes, and obviously CR/LF characters have semantic meaning in the parser. So, I decided to follow this defacto standard, even if I'm not entirely happy with it.
FIELD_VALUE = /[^\0\r\n]+/.freeze
HEADER = /\A(#{FIELD_NAME}):#{OWS}(?:(#{FIELD_VALUE})#{OWS})?\z/.freeze
HEADER = /\A(#{FIELD_NAME}):#{OWS}(?:([^\0\r\n]*[^\0\r\n \t])#{OWS})?\z/.freeze

VALID_FIELD_NAME = /\A#{FIELD_NAME}\z/.freeze
VALID_FIELD_VALUE = /\A#{FIELD_VALUE}?\z/.freeze
Expand Down
4 changes: 4 additions & 0 deletions releases.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Releases

## Unreleased

- Strip trailing whitespace from parsed header and trailer values.

## v0.41.0

- Map remote socket failures to `Protocol::HTTP::RemoteError` and prevent connection reuse.
Expand Down
13 changes: 13 additions & 0 deletions test/protocol/http1/body/chunked.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,19 @@
end
end

with "trailer with trailing whitespace" do
let(:postfix) {"ETag: abcd \t\r\n"}

it "strips trailing whitespace from the value" do
headers.add("trailer", "etag")

expect(body.read).to be == "Hello World"
expect(body.read).to be == nil

expect(headers["etag"]).to be == "abcd"
end
end

with "incomplete trailer" do
let(:buffer) {StringIO.new("0\r\n")}

Expand Down
18 changes: 18 additions & 0 deletions test/protocol/http1/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@
end
end

with "#read_headers" do
it "strips optional whitespace around values" do
client.stream.write "X-A: a b \t\r\nX-B:\t\r\nX-C: c\v\r\n\r\n"
client.stream.close

expect(server.read_headers).to be == [["X-A", "a b"], ["X-B", ""], ["X-C", "c\v"]]
end
end

with "#read_request" do
it "reads request without body" do
client.stream.write "GET / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n\r\n"
Expand Down Expand Up @@ -156,6 +165,15 @@
expect(server).to be(:persistent)
end

it "reads request with chunked body when transfer-encoding has trailing whitespace" do
client.stream.write "GET / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked \r\n\r\nb\r\nHello World\r\n0\r\n\r\n"
client.stream.close

authority, method, target, version, headers, body = server.read_request

expect(body.join).to be == "Hello World"
end

it "reads request with CONNECT method" do
client.stream.write "CONNECT localhost:443 HTTP/1.1\r\nHost: localhost\r\n\r\n"
client.stream.close
Expand Down