async-http 0.68.0 → 0.69.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: 232e7394f119e448ebf2e16f2064d660ba164c852a23dc6d15c7cd7d3984d4de
4
- data.tar.gz: 27bf2b400b9b4bab65cb2fee22ec75ed0ff74210fb61d53a1932ab3d8c6e9615
3
+ metadata.gz: 9f4a2ceef3a210332512cbe39f7bcac65cecaf23308f151534cfeb955fccb3e1
4
+ data.tar.gz: a44a6b0f61b2bdbf81b868e1e05bfe7e45855bc92a3efdc266534688d9f84fd8
5
5
  SHA512:
6
- metadata.gz: ab4cf960886ec3f8efdd0587fef2214213d09aabd8501d8c2fb212da706c78c2df73fe9dff7ce0d882945727fd7dc6635650658a5b84421b07257d94c5a2d435
7
- data.tar.gz: 70aea8682c576a672afc7b0f009f03a2ed8fadfe33c5e39e668754d9c6dd3d0e875d40734447d3983d8b11f0b5e92ce275d282766844e2552431476a74837b0f
6
+ metadata.gz: 22f65ce662e632e0d7836f13c12db69f86305ecae5e88ccf97ace1e0dc3c861e5af4fce7877dd489fec2be48031dfef99b1b697c1c0153df9670f095061465e4
7
+ data.tar.gz: 9cfb68209dcff74007c239d94176e7a3b9ac76a6667066e55e1d230b54e77663389cb5f81743ca2ac0f40b5f832e2f4720d65fa55c69962f808a9860a1018bd8
checksums.yaml.gz.sig CHANGED
Binary file
@@ -4,6 +4,8 @@
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2021-2022, by Adam Daniels.
6
6
  # Copyright, 2024, by Thomas Morgan.
7
+ # Copyright, 2024, by Igor Sidorov.
8
+ # Copyright, 2024, by Hal Brodigan.
7
9
 
8
10
  require 'io/endpoint'
9
11
  require 'io/endpoint/host_endpoint'
@@ -39,7 +41,7 @@ module Async
39
41
  if url.is_a?(Endpoint)
40
42
  return url
41
43
  else
42
- Endpoint.parse(url.to_str)
44
+ Endpoint.parse(url.to_s)
43
45
  end
44
46
  end
45
47
 
@@ -4,13 +4,24 @@
4
4
  # Copyright, 2021-2023, by Samuel Williams.
5
5
 
6
6
  require_relative '../internet'
7
- require 'thread/local'
7
+
8
+ ::Thread.attr_accessor :async_http_internet_instance
8
9
 
9
10
  module Async
10
11
  module HTTP
11
12
  class Internet
12
- # Provide access to a shared thread-local instance.
13
- extend ::Thread::Local
13
+ # The global instance of the internet.
14
+ def self.instance
15
+ ::Thread.current.async_http_internet_instance ||= self.new
16
+ end
17
+
18
+ class << self
19
+ ::Protocol::HTTP::Methods.each do |name, verb|
20
+ define_method(verb.downcase) do |url, headers = nil, body = nil, &block|
21
+ self.instance.call(verb, url, headers, body, &block)
22
+ end
23
+ end
24
+ end
14
25
  end
15
26
  end
16
27
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2023, by Samuel Williams.
4
+ # Copyright, 2018-2024, by Samuel Williams.
5
+ # Copyright, 2024, by Igor Sidorov.
5
6
 
6
7
  require_relative 'client'
7
8
  require_relative 'endpoint'
@@ -38,7 +39,7 @@ module Async
38
39
  # @parameter url [String] The URL to request, e.g. `https://www.codeotaku.com`.
39
40
  # @parameter headers [Hash | Protocol::HTTP::Headers] The headers to send with the request.
40
41
  # @parameter body [String | Protocol::HTTP::Body] The body to send with the request.
41
- def call(method, url, headers = nil, body = nil)
42
+ def call(method, url, headers = nil, body = nil, &block)
42
43
  endpoint = Endpoint[url]
43
44
  client = self.client_for(endpoint)
44
45
 
@@ -47,7 +48,15 @@ module Async
47
48
 
48
49
  request = ::Protocol::HTTP::Request.new(endpoint.scheme, endpoint.authority, method, endpoint.path, nil, headers, body)
49
50
 
50
- return client.call(request)
51
+ response = client.call(request)
52
+
53
+ return response unless block_given?
54
+
55
+ begin
56
+ yield response
57
+ ensure
58
+ response.close
59
+ end
51
60
  end
52
61
 
53
62
  def close
@@ -59,8 +68,8 @@ module Async
59
68
  end
60
69
 
61
70
  ::Protocol::HTTP::Methods.each do |name, verb|
62
- define_method(verb.downcase) do |url, headers = nil, body = nil|
63
- self.call(verb, url, headers, body)
71
+ define_method(verb.downcase) do |url, headers = nil, body = nil, &block|
72
+ self.call(verb, url, headers, body, &block)
64
73
  end
65
74
  end
66
75
 
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative '../protocol'
24
+
25
+ require 'async/queue'
26
+
27
+ module Async
28
+ module HTTP
29
+ module Mock
30
+ # This is an endpoint which bridges a client with a local server.
31
+ class Endpoint
32
+ def initialize(protocol = Protocol::HTTP2, scheme = "http", authority = "localhost", queue: Queue.new)
33
+ @protocol = protocol
34
+ @scheme = scheme
35
+ @authority = authority
36
+
37
+ @queue = queue
38
+ end
39
+
40
+ attr :protocol
41
+ attr :scheme
42
+ attr :authority
43
+
44
+ # Processing incoming connections
45
+ # @yield [::HTTP::Protocol::Request] the requests as they come in.
46
+ def run(parent: Task.current, &block)
47
+ while peer = @queue.dequeue
48
+ server = @protocol.server(peer)
49
+
50
+ parent.async do
51
+ server.each(&block)
52
+ end
53
+ end
54
+ end
55
+
56
+ def connect
57
+ local, remote = ::Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM)
58
+
59
+ @queue.enqueue(remote)
60
+
61
+ return local
62
+ end
63
+
64
+ def wrap(endpoint)
65
+ self.class.new(@protocol, endpoint.scheme, endpoint.authority, queue: @queue)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative 'mock/endpoint'
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2024, by Thomas Morgan.
5
+ # Copyright, 2024, by Samuel Williams.
5
6
 
6
7
  require_relative 'http1'
7
8
  require_relative 'http2'
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Async
7
7
  module HTTP
8
- VERSION = "0.68.0"
8
+ VERSION = "0.69.0"
9
9
  end
10
10
  end
data/lib/async/http.rb CHANGED
@@ -8,4 +8,6 @@ require_relative 'http/version'
8
8
  require_relative 'http/client'
9
9
  require_relative 'http/server'
10
10
 
11
+ require_relative 'http/internet'
12
+
11
13
  require_relative 'http/endpoint'
data/license.md CHANGED
@@ -7,7 +7,7 @@ Copyright, 2019, by Denis Talakevich.
7
7
  Copyright, 2019-2020, by Brian Morearty.
8
8
  Copyright, 2019, by Cyril Roelandt.
9
9
  Copyright, 2020, by Stefan Wrobel.
10
- Copyright, 2020, by Igor Sidorov.
10
+ Copyright, 2020-2024, by Igor Sidorov.
11
11
  Copyright, 2020, by Bruno Sutic.
12
12
  Copyright, 2020, by Sam Shadwell.
13
13
  Copyright, 2020, by Orgad Shaneh.
@@ -21,6 +21,7 @@ Copyright, 2023-2024, by Thomas Morgan.
21
21
  Copyright, 2023, by dependabot[bot].
22
22
  Copyright, 2023, by Josh Huber.
23
23
  Copyright, 2024, by Anton Zhuravsky.
24
+ Copyright, 2024, by Hal Brodigan.
24
25
 
25
26
  Permission is hereby granted, free of charge, to any person obtaining a copy
26
27
  of this software and associated documentation files (the "Software"), to deal
data/readme.md CHANGED
@@ -4,358 +4,13 @@ An asynchronous client and server implementation of HTTP/1.0, HTTP/1.1 and HTTP/
4
4
 
5
5
  [![Development Status](https://github.com/socketry/async-http/workflows/Test/badge.svg)](https://github.com/socketry/async-http/actions?workflow=Test)
6
6
 
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
10
-
11
- ``` ruby
12
- gem 'async-http'
13
- ```
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install async-http
22
-
23
7
  ## Usage
24
8
 
25
- Please see the [project documentation](https://socketry.github.io/async-http/) or serve it locally using `bake utopia:project:serve`.
26
-
27
- ### Post JSON data
28
-
29
- Here is an example showing how to post a data structure as JSON to a remote resource:
30
-
31
- ``` ruby
32
- #!/usr/bin/env ruby
33
-
34
- require 'json'
35
- require 'async'
36
- require 'async/http/internet'
37
-
38
- data = {'life' => 42}
39
-
40
- Async do
41
- # Make a new internet:
42
- internet = Async::HTTP::Internet.new
43
-
44
- # Prepare the request:
45
- headers = [['accept', 'application/json']]
46
- body = [JSON.dump(data)]
47
-
48
- # Issues a POST request:
49
- response = internet.post("https://httpbin.org/anything", headers, body)
50
-
51
- # Save the response body to a local file:
52
- pp JSON.parse(response.read)
53
- ensure
54
- # The internet is closed for business:
55
- internet.close
56
- end
57
- ```
58
-
59
- Consider using [async-rest](https://github.com/socketry/async-rest) instead.
60
-
61
- ### Multiple Requests
62
-
63
- To issue multiple requests concurrently, you should use a barrier, e.g.
64
-
65
- ``` ruby
66
- #!/usr/bin/env ruby
67
-
68
- require 'async'
69
- require 'async/barrier'
70
- require 'async/http/internet'
71
-
72
- TOPICS = ["ruby", "python", "rust"]
73
-
74
- Async do
75
- internet = Async::HTTP::Internet.new
76
- barrier = Async::Barrier.new
77
-
78
- # Spawn an asynchronous task for each topic:
79
- TOPICS.each do |topic|
80
- barrier.async do
81
- response = internet.get "https://www.google.com/search?q=#{topic}"
82
- puts "Found #{topic}: #{response.read.scan(topic).size} times."
83
- end
84
- end
85
-
86
- # Ensure we wait for all requests to complete before continuing:
87
- barrier.wait
88
- ensure
89
- internet&.close
90
- end
91
- ```
92
-
93
- #### Limiting Requests
94
-
95
- If you need to limit the number of simultaneous requests, use a semaphore.
96
-
97
- ``` ruby
98
- #!/usr/bin/env ruby
99
-
100
- require 'async'
101
- require 'async/barrier'
102
- require 'async/semaphore'
103
- require 'async/http/internet'
104
-
105
- TOPICS = ["ruby", "python", "rust"]
106
-
107
- Async do
108
- internet = Async::HTTP::Internet.new
109
- barrier = Async::Barrier.new
110
- semaphore = Async::Semaphore.new(2, parent: barrier)
111
-
112
- # Spawn an asynchronous task for each topic:
113
- TOPICS.each do |topic|
114
- semaphore.async do
115
- response = internet.get "https://www.google.com/search?q=#{topic}"
116
- puts "Found #{topic}: #{response.read.scan(topic).size} times."
117
- end
118
- end
119
-
120
- # Ensure we wait for all requests to complete before continuing:
121
- barrier.wait
122
- ensure
123
- internet&.close
124
- end
125
- ```
126
-
127
- ### Persistent Connections
128
-
129
- To keep connections alive, install the `thread-local` gem,
130
- require `async/http/internet/instance`, and use the `instance`, e.g.
131
-
132
- ``` ruby
133
- #!/usr/bin/env ruby
134
-
135
- require 'async'
136
- require 'async/http/internet/instance'
137
-
138
- Async do
139
- internet = Async::HTTP::Internet.instance
140
- response = internet.get "https://www.google.com/search?q=test"
141
- puts "Found #{response.read.size} results."
142
- end
143
- ```
144
-
145
- ### Downloading a File
146
-
147
- Here is an example showing how to download a file and save it to a local path:
148
-
149
- ``` ruby
150
- #!/usr/bin/env ruby
151
-
152
- require 'async'
153
- require 'async/http/internet'
154
-
155
- Async do
156
- # Make a new internet:
157
- internet = Async::HTTP::Internet.new
158
-
159
- # Issues a GET request to Google:
160
- response = internet.get("https://www.google.com/search?q=kittens")
161
-
162
- # Save the response body to a local file:
163
- response.save("/tmp/search.html")
164
- ensure
165
- # The internet is closed for business:
166
- internet.close
167
- end
168
- ```
169
-
170
- ### Basic Client/Server
171
-
172
- Here is a basic example of a client/server running in the same reactor:
173
-
174
- ``` ruby
175
- #!/usr/bin/env ruby
176
-
177
- require 'async'
178
- require 'async/http/server'
179
- require 'async/http/client'
180
- require 'async/http/endpoint'
181
- require 'async/http/protocol/response'
182
-
183
- endpoint = Async::HTTP::Endpoint.parse('http://127.0.0.1:9294')
184
-
185
- app = lambda do |request|
186
- Protocol::HTTP::Response[200, {}, ["Hello World"]]
187
- end
188
-
189
- server = Async::HTTP::Server.new(app, endpoint)
190
- client = Async::HTTP::Client.new(endpoint)
191
-
192
- Async do |task|
193
- server_task = task.async do
194
- server.run
195
- end
196
-
197
- response = client.get("/")
198
-
199
- puts response.status
200
- puts response.read
201
-
202
- server_task.stop
203
- end
204
- ```
205
-
206
- ### Advanced Verification
207
-
208
- You can hook into SSL certificate verification to improve server verification.
209
-
210
- ``` ruby
211
- require 'async'
212
- require 'async/http'
213
-
214
- # These are generated from the certificate chain that the server presented.
215
- trusted_fingerprints = {
216
- "dac9024f54d8f6df94935fb1732638ca6ad77c13" => true,
217
- "e6a3b45b062d509b3382282d196efe97d5956ccb" => true,
218
- "07d63f4c05a03f1c306f9941b8ebf57598719ea2" => true,
219
- "e8d994f44ff20dc78dbff4e59d7da93900572bbf" => true,
220
- }
221
-
222
- Async do
223
- endpoint = Async::HTTP::Endpoint.parse("https://www.codeotaku.com/index")
224
-
225
- # This is a quick hack/POC:
226
- ssl_context = endpoint.ssl_context
227
-
228
- ssl_context.verify_callback = proc do |verified, store_context|
229
- certificate = store_context.current_cert
230
- fingerprint = OpenSSL::Digest::SHA1.new(certificate.to_der).to_s
231
-
232
- if trusted_fingerprints.include? fingerprint
233
- true
234
- else
235
- Console.logger.warn("Untrusted Certificate Fingerprint"){fingerprint}
236
- false
237
- end
238
- end
239
-
240
- endpoint = endpoint.with(ssl_context: ssl_context)
241
-
242
- client = Async::HTTP::Client.new(endpoint)
243
-
244
- response = client.get(endpoint.path)
245
-
246
- pp response.status, response.headers.fields, response.read
247
- end
248
- ```
249
-
250
- ### Timeouts
251
-
252
- Here's a basic example with a timeout:
253
-
254
- ``` ruby
255
- #!/usr/bin/env ruby
256
-
257
- require 'async/http/internet'
258
-
259
- Async do |task|
260
- internet = Async::HTTP::Internet.new
261
-
262
- # Request will timeout after 2 seconds
263
- task.with_timeout(2) do
264
- response = internet.get "https://httpbin.org/delay/10"
265
- end
266
- rescue Async::TimeoutError
267
- puts "The request timed out"
268
- ensure
269
- internet&.close
270
- end
271
- ```
272
-
273
- ## Performance
274
-
275
- On a 4-core 8-thread i7, running `ab` which uses discrete (non-keep-alive) connections:
276
-
277
- $ ab -c 8 -t 10 http://127.0.0.1:9294/
278
- This is ApacheBench, Version 2.3 <$Revision: 1757674 $>
279
- Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
280
- Licensed to The Apache Software Foundation, http://www.apache.org/
281
-
282
- Benchmarking 127.0.0.1 (be patient)
283
- Completed 5000 requests
284
- Completed 10000 requests
285
- Completed 15000 requests
286
- Completed 20000 requests
287
- Completed 25000 requests
288
- Completed 30000 requests
289
- Completed 35000 requests
290
- Completed 40000 requests
291
- Completed 45000 requests
292
- Completed 50000 requests
293
- Finished 50000 requests
294
-
295
-
296
- Server Software:
297
- Server Hostname: 127.0.0.1
298
- Server Port: 9294
299
-
300
- Document Path: /
301
- Document Length: 13 bytes
302
-
303
- Concurrency Level: 8
304
- Time taken for tests: 1.869 seconds
305
- Complete requests: 50000
306
- Failed requests: 0
307
- Total transferred: 2450000 bytes
308
- HTML transferred: 650000 bytes
309
- Requests per second: 26755.55 [#/sec] (mean)
310
- Time per request: 0.299 [ms] (mean)
311
- Time per request: 0.037 [ms] (mean, across all concurrent requests)
312
- Transfer rate: 1280.29 [Kbytes/sec] received
313
-
314
- Connection Times (ms)
315
- min mean[+/-sd] median max
316
- Connect: 0 0 0.0 0 0
317
- Processing: 0 0 0.2 0 6
318
- Waiting: 0 0 0.2 0 6
319
- Total: 0 0 0.2 0 6
320
-
321
- Percentage of the requests served within a certain time (ms)
322
- 50% 0
323
- 66% 0
324
- 75% 0
325
- 80% 0
326
- 90% 0
327
- 95% 1
328
- 98% 1
329
- 99% 1
330
- 100% 6 (longest request)
331
-
332
- On a 4-core 8-thread i7, running `wrk`, which uses 8 keep-alive connections:
333
-
334
- $ wrk -c 8 -d 10 -t 8 http://127.0.0.1:9294/
335
- Running 10s test @ http://127.0.0.1:9294/
336
- 8 threads and 8 connections
337
- Thread Stats Avg Stdev Max +/- Stdev
338
- Latency 217.69us 0.99ms 23.21ms 97.39%
339
- Req/Sec 12.18k 1.58k 17.67k 83.21%
340
- 974480 requests in 10.10s, 60.41MB read
341
- Requests/sec: 96485.00
342
- Transfer/sec: 5.98MB
343
-
344
- According to these results, the cost of handling connections is quite high, while general throughput seems pretty decent.
345
-
346
- ## Semantic Model
347
-
348
- ### Scheme
349
-
350
- HTTP/1 has an implicit scheme determined by the kind of connection made to the server (either `http` or `https`), while HTTP/2 models this explicitly and the client indicates this in the request using the `:scheme` pseudo-header (typically `https`). To normalize this, `Async::HTTP::Client` and `Async::HTTP::Server` have a default scheme which is used if none is supplied.
351
-
352
- ### Version
353
-
354
- HTTP/1 has an explicit version while HTTP/2 does not expose the version in any way.
9
+ Please see the [project documentation](https://socketry.github.io/async-http/) for more details.
355
10
 
356
- ### Reason
11
+ - [Getting Started](https://socketry.github.io/async-http/guides/getting-started/index) - This guide explains how to get started with `Async::HTTP`.
357
12
 
358
- HTTP/1 responses contain a reason field which is largely irrelevant. HTTP/2 does not support this field.
13
+ - [Testing](https://socketry.github.io/async-http/guides/testing/index) - This guide explains how to use `Async::HTTP` clients and servers in your tests.
359
14
 
360
15
  ## Contributing
361
16
 
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.68.0
4
+ version: 0.69.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -10,11 +10,12 @@ authors:
10
10
  - Janko Marohnić
11
11
  - Thomas Morgan
12
12
  - Adam Daniels
13
+ - Igor Sidorov
13
14
  - Anton Zhuravsky
14
15
  - Cyril Roelandt
15
16
  - Denis Talakevich
17
+ - Hal Brodigan
16
18
  - Ian Ker-Seymer
17
- - Igor Sidorov
18
19
  - Josh Huber
19
20
  - Marco Concetto Rudilosso
20
21
  - Olle Jonsson
@@ -57,7 +58,7 @@ cert_chain:
57
58
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
58
59
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
59
60
  -----END CERTIFICATE-----
60
- date: 2024-06-23 00:00:00.000000000 Z
61
+ date: 2024-06-24 00:00:00.000000000 Z
61
62
  dependencies:
62
63
  - !ruby/object:Gem::Dependency
63
64
  name: async
@@ -190,6 +191,8 @@ files:
190
191
  - lib/async/http/endpoint.rb
191
192
  - lib/async/http/internet.rb
192
193
  - lib/async/http/internet/instance.rb
194
+ - lib/async/http/mock.rb
195
+ - lib/async/http/mock/endpoint.rb
193
196
  - lib/async/http/protocol.rb
194
197
  - lib/async/http/protocol/http.rb
195
198
  - lib/async/http/protocol/http1.rb
metadata.gz.sig CHANGED
Binary file