mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Merge pull request #2287 from eugeneius/chunked_content_length
Set CONTENT_LENGTH for chunked requests
This commit is contained in:
commit
f9ddd58845
3 changed files with 60 additions and 7 deletions
|
@ -46,6 +46,7 @@
|
|||
* Improvements to `out_of_band` hook (#2234)
|
||||
* Prefer the rackup file specified by the CLI (#2225)
|
||||
* Fix for spawning subprocesses with fork_worker option (#2267)
|
||||
* Set `CONTENT_LENGTH` for chunked requests (#2287)
|
||||
|
||||
* Refactor
|
||||
* Remove unused loader argument from Plugin initializer (#2095)
|
||||
|
|
|
@ -420,7 +420,10 @@ module Puma
|
|||
raise EOFError
|
||||
end
|
||||
|
||||
return true if decode_chunk(chunk)
|
||||
if decode_chunk(chunk)
|
||||
@env[CONTENT_LENGTH] = @chunked_content_length
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -432,20 +435,28 @@ module Puma
|
|||
@body = Tempfile.new(Const::PUMA_TMP_BASE)
|
||||
@body.binmode
|
||||
@tempfile = @body
|
||||
@chunked_content_length = 0
|
||||
|
||||
return decode_chunk(body)
|
||||
if decode_chunk(body)
|
||||
@env[CONTENT_LENGTH] = @chunked_content_length
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
def write_chunk(str)
|
||||
@chunked_content_length += @body.write(str)
|
||||
end
|
||||
|
||||
def decode_chunk(chunk)
|
||||
if @partial_part_left > 0
|
||||
if @partial_part_left <= chunk.size
|
||||
if @partial_part_left > 2
|
||||
@body << chunk[0..(@partial_part_left-3)] # skip the \r\n
|
||||
write_chunk(chunk[0..(@partial_part_left-3)]) # skip the \r\n
|
||||
end
|
||||
chunk = chunk[@partial_part_left..-1]
|
||||
@partial_part_left = 0
|
||||
else
|
||||
@body << chunk if @partial_part_left > 2 # don't include the last \r\n
|
||||
write_chunk(chunk) if @partial_part_left > 2 # don't include the last \r\n
|
||||
@partial_part_left -= chunk.size
|
||||
return false
|
||||
end
|
||||
|
@ -492,12 +503,12 @@ module Puma
|
|||
|
||||
case
|
||||
when got == len
|
||||
@body << part[0..-3] # to skip the ending \r\n
|
||||
write_chunk(part[0..-3]) # to skip the ending \r\n
|
||||
when got <= len - 2
|
||||
@body << part
|
||||
write_chunk(part)
|
||||
@partial_part_left = len - part.size
|
||||
when got == len - 1 # edge where we get just \r but not \n
|
||||
@body << part[0..-2]
|
||||
write_chunk(part[0..-2])
|
||||
@partial_part_left = len - part.size
|
||||
end
|
||||
else
|
||||
|
|
|
@ -498,8 +498,10 @@ EOF
|
|||
|
||||
def test_chunked_request
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -507,12 +509,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_pause_before_value
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -525,12 +530,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_pause_between_chunks
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -543,12 +551,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_pause_mid_count
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -561,12 +572,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_pause_before_count_newline
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -579,12 +593,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_pause_mid_value
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -597,12 +614,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_pause_between_cr_lf_after_size_of_second_chunk
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -624,12 +644,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal (part1 + 'b'), body
|
||||
assert_equal 4201, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_pause_between_closing_cr_lf
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -643,12 +666,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal 'hello', body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_pause_before_closing_cr_lf
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -662,12 +688,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal 'hello', body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_request_header_case
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -675,12 +704,15 @@ EOF
|
|||
|
||||
assert_equal "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
end
|
||||
|
||||
def test_chunked_keep_alive
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -690,14 +722,17 @@ EOF
|
|||
|
||||
assert_equal ["HTTP/1.1 200 OK", "Content-Length: 0"], h
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
|
||||
sock.close
|
||||
end
|
||||
|
||||
def test_chunked_keep_alive_two_back_to_back
|
||||
body = nil
|
||||
content_length = nil
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
||||
|
@ -715,6 +750,7 @@ EOF
|
|||
h = header(sock)
|
||||
assert_equal ["HTTP/1.1 200 OK", "Content-Length: 0"], h
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
assert_equal true, last_crlf_written
|
||||
|
||||
last_crlf_writer.join
|
||||
|
@ -726,16 +762,19 @@ EOF
|
|||
|
||||
assert_equal ["HTTP/1.1 200 OK", "Content-Length: 0"], h
|
||||
assert_equal "goodbye", body
|
||||
assert_equal 7, content_length
|
||||
|
||||
sock.close
|
||||
end
|
||||
|
||||
def test_chunked_keep_alive_two_back_to_back_with_set_remote_address
|
||||
body = nil
|
||||
content_length = nil
|
||||
remote_addr =nil
|
||||
@server = Puma::Server.new @app, @events, { remote_address: :header, remote_address_header: 'HTTP_X_FORWARDED_FOR'}
|
||||
server_run app: ->(env) {
|
||||
body = env['rack.input'].read
|
||||
content_length = env['CONTENT_LENGTH']
|
||||
remote_addr = env['REMOTE_ADDR']
|
||||
[200, {}, [""]]
|
||||
}
|
||||
|
@ -745,6 +784,7 @@ EOF
|
|||
h = header sock
|
||||
assert_equal ["HTTP/1.1 200 OK", "Content-Length: 0"], h
|
||||
assert_equal "hello", body
|
||||
assert_equal 5, content_length
|
||||
assert_equal "127.0.0.1", remote_addr
|
||||
|
||||
sock << "GET / HTTP/1.1\r\nX-Forwarded-For: 127.0.0.2\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\n\r\n4\r\ngood\r\n3\r\nbye\r\n0\r\n\r\n"
|
||||
|
@ -754,6 +794,7 @@ EOF
|
|||
|
||||
assert_equal ["HTTP/1.1 200 OK", "Content-Length: 0"], h
|
||||
assert_equal "goodbye", body
|
||||
assert_equal 7, content_length
|
||||
assert_equal "127.0.0.2", remote_addr
|
||||
|
||||
sock.close
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue