async-http 0.68.0 → 0.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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