async-http 0.78.0 → 0.80.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: 5a73103da274cc4cac5838409d95a05f1c8a746e0b58dcee062031886061ffb7
4
+ data.tar.gz: da1d5991f78d71c2ab1a3c8ace1d0d8c53831b545bdcfe2f3e93d095bd6389bd
5
5
  SHA512:
6
- metadata.gz: 43c49b50bb88955088b74926e3fe33310f38f4b09d9b9ecdc538a9835c9be5b8be0e172e09794324a53db99e09b0102ae96fc179af13578a758f42644d6f4011
7
- data.tar.gz: fa1a0d97f326bdd72010f07cfe21004b0da8f75fe4556778bd3b918f42e2e85f22bc41cd07e2a64b4395540e531a879480e634a8fe401ee0d0d7c146af8b61d7
6
+ metadata.gz: 4169f9f110a07db5f27b6e083b09b1c6d3f0940269b1d423150993a491c4f3d46dfa4ae227712502b07d4cf949b0186e1e838fa3b77cead2809ee73c30e4500c
7
+ data.tar.gz: a85d33bd88881433c1c33b369027d6ff4f1c095b26ecac5b583b865fe2f8011c6ee7bba6c6f9857c5b1cf1697c4298a5e4c6506da3584d0215682bd4beea9858
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
@@ -17,7 +17,8 @@ module Async
17
17
 
18
18
  @task = nil
19
19
 
20
- @window_updated = Async::Condition.new
20
+ @guard = ::Mutex.new
21
+ @window_updated = ::ConditionVariable.new
21
22
  end
22
23
 
23
24
  attr :trailer
@@ -33,17 +34,26 @@ module Async
33
34
  end
34
35
 
35
36
  def window_updated(size)
36
- @window_updated.signal
37
+ @guard.synchronize do
38
+ @window_updated.signal
39
+ end
37
40
  end
38
41
 
39
42
  def write(chunk)
40
43
  until chunk.empty?
41
44
  maximum_size = @stream.available_frame_size
42
45
 
43
- while maximum_size <= 0
44
- @window_updated.wait
45
-
46
- maximum_size = @stream.available_frame_size
46
+ # We try to avoid synchronization if possible:
47
+ if maximum_size <= 0
48
+ @guard.synchronize do
49
+ maximum_size = @stream.available_frame_size
50
+
51
+ while maximum_size <= 0
52
+ @window_updated.wait(@guard)
53
+
54
+ maximum_size = @stream.available_frame_size
55
+ end
56
+ end
47
57
  end
48
58
 
49
59
  break unless chunk = send_data(chunk, maximum_size)
@@ -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.80.0"
9
9
  end
10
10
  end
data.tar.gz.sig CHANGED
@@ -1,4 +1 @@
1
- M7>d[܌c��a���0 d}bB�զ�UƐ��(�)��e���
2
- ^�Ƶ=U���Z��'�cOt3JlLO�K6�4�1:$�t��6�ݚ���)�[y��q��^�a7��.x쥃��U�ɀ�N�*5�T�Y������
3
- h%!5��c;Z[j�sX�L�����}>m}7e��p|9"̕$�4������k'Me_�{s1�?8/Li�Na���-ZI�4���1��G�$a]��ŋ��*���~-N�D8��&�����"��pr:���P;2��:a[��UB�� )|�}4[��ق�`����lq
4
- ��8=�5���Si/�ﻲH���^ �fO
1
+ ug;oFa�l��C�7vt}}�5�X�n��l�Q�6�^h��:tQ[���3d9%���@:B�/�1�����0�KJ�� �LU����o'y O{��.醠K\/���|�k<{p*P��)X��"k���1�c��`~!�V�7=��m�){3BT>���0��6+B�B�Q�w�q3��'ˇ%�.nYZ8�7��q�����u�]���`C4<C��ѿߨ!_���=YE�!�w��DŽ��ǒ�:X8�SL+�59����b��Ձ���,����2D?F���|\;�S����?����q��\������Ӝ2n���rP�7YVUԠ,z���xs��
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.80.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-10-02 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