async-http 0.78.0 → 0.79.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76e78af8d20808d557b1c13c850af0a268de5535726ba07708b2012eb8752029
4
- data.tar.gz: 53bdf9b950394a03ca8c1fd47befe51e8ba51a5cce82aa47c01111df7efd21b4
3
+ metadata.gz: 93d3d9d22a84537ba522b417586a7bc02d243d56defe26fb9a3937470675b244
4
+ data.tar.gz: 8c16add5b2c301948235c739d076f92c400cdd745cc36881fac49125a41c5bc4
5
5
  SHA512:
6
- metadata.gz: 43c49b50bb88955088b74926e3fe33310f38f4b09d9b9ecdc538a9835c9be5b8be0e172e09794324a53db99e09b0102ae96fc179af13578a758f42644d6f4011
7
- data.tar.gz: fa1a0d97f326bdd72010f07cfe21004b0da8f75fe4556778bd3b918f42e2e85f22bc41cd07e2a64b4395540e531a879480e634a8fe401ee0d0d7c146af8b61d7
6
+ metadata.gz: cf362c7394967d2746e6d37984f25f5fc02e8e1fa89b7d5f6afcf31d87e665d75877cd5a9cd920f1ae87b6ecbc73e7d9b7cedc72467a69d95b5d24a04b897a8e
7
+ data.tar.gz: e922cf9cfd745423d9350f633d1a152dd8f6e06ae23abd3c8b1e403f49abb7089181aa68a1ded1a329cf2017b7bf98feb6a60fed45e1f8582eb3b01ca401ce4d
checksums.yaml.gz.sig CHANGED
Binary file
@@ -18,11 +18,12 @@ module Async
18
18
 
19
19
  attr_accessor :pool
20
20
 
21
- def closed!
21
+ def closed(error = nil)
22
22
  super
23
23
 
24
24
  if pool = @pool
25
25
  @pool = nil
26
+ # If the connection is not reusable, this will retire it from the connection pool and invoke `#close`.
26
27
  pool.release(self)
27
28
  end
28
29
  end
@@ -50,30 +51,32 @@ module Async
50
51
  task.async(annotation: "Upgrading request...") do
51
52
  # If this fails, this connection will be closed.
52
53
  write_upgrade_body(protocol, body)
54
+ rescue => error
55
+ self.close(error)
53
56
  end
54
57
  elsif request.connect?
55
58
  task.async(annotation: "Tunnneling request...") do
56
59
  write_tunnel_body(@version, body)
60
+ rescue => error
61
+ self.close(error)
57
62
  end
58
63
  else
59
64
  task.async(annotation: "Streaming request...") do
60
65
  # Once we start writing the body, we can't recover if the request fails. That's because the body might be generated dynamically, streaming, etc.
61
66
  write_body(@version, body, false, trailer)
67
+ rescue => error
68
+ self.close(error)
62
69
  end
63
70
  end
64
71
  elsif protocol = request.protocol
65
72
  write_upgrade_body(protocol)
66
73
  else
67
- write_body(@version, body, false, trailer)
74
+ write_body(@version, request.body, false, trailer)
68
75
  end
69
76
 
70
- response = Response.read(self, request)
71
-
72
- return response
73
- rescue
74
- # This will ensure that #reusable? returns false.
75
- self.close
76
-
77
+ return Response.read(self, request)
78
+ rescue => error
79
+ self.close(error)
77
80
  raise
78
81
  end
79
82
  end
@@ -43,6 +43,8 @@ module Async
43
43
 
44
44
  def read_line?
45
45
  @stream.read_until(CRLF)
46
+ rescue Errno::ECONNRESET
47
+ return nil
46
48
  end
47
49
 
48
50
  def read_line
@@ -32,19 +32,23 @@ module Async
32
32
  end
33
33
 
34
34
  def close(error = nil)
35
+ super
36
+
35
37
  unless @closed.resolved?
36
38
  @error = error
37
39
  @closed.value = true
38
40
  end
39
-
40
- super
41
41
  end
42
42
 
43
- def wait
43
+ def wait(persistent = true)
44
44
  if @reading
45
45
  @closed.wait
46
- else
46
+ elsif persistent
47
+ # If the connection can be reused, let's gracefully discard the body:
47
48
  self.discard
49
+ else
50
+ # Else, we don't care about the body, so we can close it immediately:
51
+ self.close
48
52
  end
49
53
  end
50
54
 
@@ -22,7 +22,7 @@ module Async
22
22
  @ready = Async::Notification.new
23
23
  end
24
24
 
25
- def closed!
25
+ def closed(error = nil)
26
26
  super
27
27
 
28
28
  @ready.signal
@@ -38,14 +38,12 @@ module Async
38
38
  end
39
39
 
40
40
  def next_request
41
- # Wait for the connection to become idle before reading the next request:
42
- unless idle?
41
+ if closed?
42
+ return nil
43
+ elsif !idle?
43
44
  @ready.wait
44
45
  end
45
46
 
46
- # The default is true.
47
- return unless @persistent
48
-
49
47
  # Read an incoming request:
50
48
  return unless request = Request.read(self)
51
49
 
@@ -90,38 +88,41 @@ module Async
90
88
  # We force a 101 response if the protocol is upgraded - HTTP/2 CONNECT will return 200 for success, but this won't be understood by HTTP/1 clients:
91
89
  write_response(@version, 101, response.headers)
92
90
 
93
- stream = write_upgrade_body(protocol)
94
-
95
91
  # At this point, the request body is hijacked, so we don't want to call #finish below.
96
92
  request = nil
97
93
  response = nil
98
94
 
99
- # We must return here as no further request processing can be done:
100
- return body.call(stream)
95
+ if body.stream?
96
+ return body.call(write_upgrade_body(protocol))
97
+ else
98
+ write_upgrade_body(protocol, body)
99
+ end
101
100
  elsif response.status == 101
102
101
  # This code path is to support legacy behavior where the response status is set to 101, but the protocol is not upgraded. This may not be a valid use case, but it is supported for compatibility. We expect the response headers to contain the `upgrade` header.
103
102
  write_response(@version, response.status, response.headers)
104
103
 
105
- stream = write_tunnel_body(version)
106
-
107
104
  # Same as above:
108
105
  request = nil
109
106
  response = nil
110
107
 
111
- # We must return here as no further request processing can be done:
112
- return body&.call(stream)
108
+ if body.stream?
109
+ return body.call(write_tunnel_body(version))
110
+ else
111
+ write_tunnel_body(version, body)
112
+ end
113
113
  else
114
114
  write_response(@version, response.status, response.headers)
115
115
 
116
116
  if request.connect? and response.success?
117
- stream = write_tunnel_body(version)
118
-
119
117
  # Same as above:
120
118
  request = nil
121
119
  response = nil
122
120
 
123
- # We must return here as no further request processing can be done:
124
- return body.call(stream)
121
+ if body.stream?
122
+ return body.call(write_tunnel_body(version))
123
+ else
124
+ write_tunnel_body(version, body)
125
+ end
125
126
  else
126
127
  head = request.head?
127
128
 
@@ -143,8 +144,12 @@ module Async
143
144
  request&.finish
144
145
  end
145
146
 
146
- # Discard or wait for the input body to be consumed:
147
- finishable&.wait
147
+ if finishable
148
+ finishable.wait(@persistent)
149
+ else
150
+ # Do not remove this line or you will unleash the gods of concurrency hell.
151
+ task.yield
152
+ end
148
153
  rescue => error
149
154
  raise
150
155
  ensure
@@ -62,9 +62,9 @@ module Async
62
62
  end
63
63
 
64
64
  # TODO this might need to be in an ensure block:
65
- if @input and frame.end_stream?
66
- @input.close_write
65
+ if input = @input and frame.end_stream?
67
66
  @input = nil
67
+ input.close_write
68
68
  end
69
69
  rescue ::Protocol::HTTP2::HeaderError => error
70
70
  Console.logger.debug(self, error)
@@ -123,6 +123,8 @@ module Async
123
123
 
124
124
  # Called when the output terminates normally.
125
125
  def finish_output(error = nil)
126
+ return if self.closed?
127
+
126
128
  trailer = @output&.trailer
127
129
 
128
130
  @output = nil
@@ -152,14 +154,14 @@ module Async
152
154
  def closed(error)
153
155
  super
154
156
 
155
- if @input
156
- @input.close_write(error)
157
+ if input = @input
157
158
  @input = nil
159
+ input.close_write(error)
158
160
  end
159
161
 
160
- if @output
161
- @output.stop(error)
162
+ if output = @output
162
163
  @output = nil
164
+ output.stop(error)
163
165
  end
164
166
 
165
167
  if pool = @pool and @connection
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Async
7
7
  module HTTP
8
- VERSION = "0.78.0"
8
+ VERSION = "0.79.0"
9
9
  end
10
10
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.78.0
4
+ version: 0.79.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -58,7 +58,7 @@ cert_chain:
58
58
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
59
59
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
60
60
  -----END CERTIFICATE-----
61
- date: 2024-09-22 00:00:00.000000000 Z
61
+ date: 2024-09-24 00:00:00.000000000 Z
62
62
  dependencies:
63
63
  - !ruby/object:Gem::Dependency
64
64
  name: async
@@ -136,28 +136,28 @@ dependencies:
136
136
  requirements:
137
137
  - - "~>"
138
138
  - !ruby/object:Gem::Version
139
- version: '0.25'
139
+ version: '0.27'
140
140
  type: :runtime
141
141
  prerelease: false
142
142
  version_requirements: !ruby/object:Gem::Requirement
143
143
  requirements:
144
144
  - - "~>"
145
145
  - !ruby/object:Gem::Version
146
- version: '0.25'
146
+ version: '0.27'
147
147
  - !ruby/object:Gem::Dependency
148
148
  name: protocol-http2
149
149
  requirement: !ruby/object:Gem::Requirement
150
150
  requirements:
151
151
  - - "~>"
152
152
  - !ruby/object:Gem::Version
153
- version: '0.18'
153
+ version: '0.19'
154
154
  type: :runtime
155
155
  prerelease: false
156
156
  version_requirements: !ruby/object:Gem::Requirement
157
157
  requirements:
158
158
  - - "~>"
159
159
  - !ruby/object:Gem::Version
160
- version: '0.18'
160
+ version: '0.19'
161
161
  - !ruby/object:Gem::Dependency
162
162
  name: traces
163
163
  requirement: !ruby/object:Gem::Requirement
metadata.gz.sig CHANGED
Binary file