File tree Expand file tree Collapse file tree 2 files changed +41
-3
lines changed
lib/async/http/protocol/http1 Expand file tree Collapse file tree 2 files changed +41
-3
lines changed Original file line number Diff line number Diff line change @@ -83,7 +83,7 @@ def each(task: Task.current)
83
83
version = request . version
84
84
85
85
# Same as above:
86
- request = nil unless body
86
+ request = nil unless request . body
87
87
response = nil
88
88
89
89
write_body ( version , body , head , trailer )
@@ -97,8 +97,13 @@ def each(task: Task.current)
97
97
write_body ( request . version , nil )
98
98
end
99
99
100
- # Gracefully finish reading the request body if it was not already done so.
101
- request &.finish
100
+ if request &.body
101
+ # Read one chunk to allow small or 0-length bodies to identify the body as complete.
102
+ request . body . read unless request . body . empty?
103
+ # If request body has outstanding data, will close the stream. This avoids wasting cycles if remaining
104
+ # body size is large or unknown. If body was already read, leaves stream open for potential keep-alive.
105
+ request . close
106
+ end
102
107
103
108
# This ensures we yield at least once every iteration of the loop and allow other fibers to execute.
104
109
task . yield
@@ -109,6 +114,7 @@ def each(task: Task.current)
109
114
end
110
115
end
111
116
end
117
+
112
118
end
113
119
end
114
120
end
Original file line number Diff line number Diff line change 7
7
8
8
require 'async/http/protocol/http11'
9
9
require 'async/http/a_protocol'
10
+ require 'protocol/http/body/readable'
10
11
11
12
describe Async ::HTTP ::Protocol ::HTTP11 do
12
13
it_behaves_like Async ::HTTP ::AProtocol
@@ -32,6 +33,37 @@ def around
32
33
end
33
34
end
34
35
36
+ with 'bad request body' do
37
+ let ( :app ) do
38
+ Protocol ::HTTP ::Middleware . for do |request |
39
+ Protocol ::HTTP ::Response [ 400 , { } , [ "Bad request" ] ]
40
+ end
41
+ end
42
+
43
+ class EndlessBody < Protocol ::HTTP ::Body ::Readable
44
+ attr :chunks_read
45
+ def initialize
46
+ @chunks_read = 0
47
+ end
48
+ def read
49
+ @chunks_read += 1
50
+ Async ::Task . current . yield
51
+ 'endless'
52
+ end
53
+ end
54
+
55
+ it "should close the connection when request unread" do
56
+ body = EndlessBody . new
57
+ response = client . post ( '/' , { } , body )
58
+
59
+ expect ( response ) . to be ( :bad_request? )
60
+
61
+ response . read
62
+ sleep 0.01 # brief window for multiple chunks to be read and avoid Async::Stop
63
+ expect ( body . chunks_read ) . to be :< , 5
64
+ end
65
+ end
66
+
35
67
with 'head request' do
36
68
let ( :app ) do
37
69
Protocol ::HTTP ::Middleware . for do |request |
You can’t perform that action at this time.
0 commit comments