fetch-api 0.4.1 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -7
- data/lib/fetch/client.rb +5 -2
- data/lib/fetch/config.rb +1 -1
- data/lib/fetch/connection_pool.rb +31 -38
- data/lib/fetch/version.rb +1 -1
- data/lib/fetch.rb +2 -2
- data/sig/fetch/config.rbs +1 -1
- data/sig/fetch/connection_pool.rbs +2 -10
- data/sig/fetch/version.rbs +3 -0
- data/sig/fetch.rbs +0 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb43f07388e02a5f1ec3ccf700a634962896b68e8de60c402aacfe078499dc06
|
4
|
+
data.tar.gz: 228e63fa8ba87bdb73f4ed82dd92af70724bb5e3c0a10c2be1849bba3752b846
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99785c3983dbf1e311e3e845ad92a41791af9089b1ecf349973e5a3a14159b1ec855b07c16f46980248b1f8375d3761fd6696cebde999763053a178117257510
|
7
|
+
data.tar.gz: 6c969cd4edfc77256e960cab56d7fe9db4a345f754e811e278b18d27900c393625ead267a566abb4334e743270b181ac9921fdfdc51f45f715da8f8701ed28cb
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# Fetch
|
1
|
+
# Fetch::API
|
2
2
|
|
3
3
|
Ruby's Net::HTTP is very powerful, but has a complicated API. OpenURI is easy to use, but has limited functionality. Third-party HTTP clients each have different APIs, and it can sometimes be difficult to learn how to use them.
|
4
4
|
|
5
|
-
There is one HTTP client that we can all use. It is the browser's Fetch API.
|
5
|
+
There is one HTTP client that we can all use. It is the browser's Fetch API. Fetch::API is an HTTP client for Ruby that can be used in a way that is similar to the Fetch API.
|
6
6
|
|
7
7
|
This is not intended to be a complete copy of the Fetch API. For example, responses are returned synchronously rather than asynchronously, as that is more familiar behavior for Ruby programmers. It is only "like" the Fetch API.
|
8
8
|
|
@@ -102,16 +102,16 @@ res = fetch('http://example.com', **{
|
|
102
102
|
})
|
103
103
|
```
|
104
104
|
|
105
|
-
|
105
|
+
### Connection pooling
|
106
106
|
|
107
|
-
Fetch
|
107
|
+
Fetch::API automatically pools and reuses connections to the same origin. Connections are closed after a certain amount of time has passed since the last use, and a new connection is used the next time. Different connections are returned for different threads (in other words, Fetch::API is thread-safe).
|
108
108
|
|
109
|
-
These values
|
109
|
+
These values can be configured as follows (in seconds):
|
110
110
|
|
111
111
|
``` ruby
|
112
112
|
Fetch.configure do |config|
|
113
|
-
config.
|
114
|
-
config.keep_alive_timeout
|
113
|
+
config.max_idle_time = 30 # default
|
114
|
+
config.keep_alive_timeout = 15 # default
|
115
115
|
end
|
116
116
|
```
|
117
117
|
|
data/lib/fetch/client.rb
CHANGED
@@ -48,7 +48,10 @@ module Fetch
|
|
48
48
|
when Net::HTTPRedirection
|
49
49
|
case redirect.to_s
|
50
50
|
when 'follow'
|
51
|
-
|
51
|
+
# @type var location: String
|
52
|
+
location = res['Location']
|
53
|
+
|
54
|
+
fetch(location, method:, headers:, body:, redirect:, _redirected: true)
|
52
55
|
when 'error'
|
53
56
|
raise RedirectError, "redirected to #{res['Location']}"
|
54
57
|
when 'manual'
|
@@ -67,7 +70,7 @@ module Fetch
|
|
67
70
|
if pool = Thread.current.thread_variable_get(:fetch_connection_pool)
|
68
71
|
pool
|
69
72
|
else
|
70
|
-
Thread.current.thread_variable_set
|
73
|
+
Thread.current.thread_variable_set(:fetch_connection_pool, ConnectionPool.new)
|
71
74
|
end
|
72
75
|
end
|
73
76
|
|
data/lib/fetch/config.rb
CHANGED
@@ -4,74 +4,67 @@ require 'thread'
|
|
4
4
|
|
5
5
|
module Fetch
|
6
6
|
class ConnectionPool
|
7
|
-
Entry = Struct.new(:connection, :in_use, :last_used, keyword_init: true)
|
8
|
-
|
9
7
|
def initialize
|
10
8
|
@connections = {}
|
11
9
|
@mutex = Mutex.new
|
12
10
|
|
13
11
|
@sweeper = Thread.new {
|
14
12
|
loop do
|
15
|
-
sleep 1
|
16
|
-
|
17
13
|
sweep
|
18
14
|
|
19
|
-
|
15
|
+
if @connections.empty?
|
16
|
+
Thread.stop
|
17
|
+
else
|
18
|
+
sleep 1
|
19
|
+
end
|
20
20
|
end
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
24
24
|
def with_connection(uri, &block)
|
25
|
-
conn =
|
25
|
+
conn = checkout(uri)
|
26
26
|
|
27
27
|
begin
|
28
28
|
block.call(conn)
|
29
29
|
ensure
|
30
|
-
|
30
|
+
checkin uri, conn
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
-
def
|
37
|
-
@mutex.synchronize {
|
38
|
-
entry
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@connections[uri.origin] = Entry.new(connection: http, in_use: true)
|
50
|
-
|
51
|
-
http.start
|
52
|
-
}
|
53
|
-
end
|
54
|
-
}.tap {
|
55
|
-
@sweeper.wakeup
|
56
|
-
}
|
36
|
+
def checkout(uri)
|
37
|
+
if entry = @mutex.synchronize { @connections.delete(uri.origin) }
|
38
|
+
entry.first
|
39
|
+
else
|
40
|
+
# @type var host: String
|
41
|
+
host = uri.host
|
42
|
+
|
43
|
+
Net::HTTP.new(host, uri.port).tap {|http|
|
44
|
+
http.use_ssl = uri.scheme == 'https'
|
45
|
+
http.keep_alive_timeout = Fetch.config.keep_alive_timeout
|
46
|
+
http.start
|
47
|
+
}
|
48
|
+
end
|
57
49
|
end
|
58
50
|
|
59
|
-
def
|
51
|
+
def checkin(uri, conn)
|
60
52
|
@mutex.synchronize do
|
61
|
-
|
62
|
-
entry.in_use = false
|
63
|
-
entry.last_used = Time.now
|
64
|
-
end
|
53
|
+
@connections[uri.origin] = [conn, Time.now]
|
65
54
|
end
|
55
|
+
|
56
|
+
@sweeper.wakeup
|
66
57
|
end
|
67
58
|
|
68
59
|
def sweep
|
69
60
|
@mutex.synchronize do
|
70
|
-
@connections.each do |origin,
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
61
|
+
@connections.each do |origin, (conn, last_used)|
|
62
|
+
if last_used + Fetch.config.max_idle_time < Time.now
|
63
|
+
begin
|
64
|
+
conn.finish
|
65
|
+
rescue IOError
|
66
|
+
# do nothing
|
67
|
+
end
|
75
68
|
|
76
69
|
@connections.delete origin
|
77
70
|
end
|
data/lib/fetch/version.rb
CHANGED
data/lib/fetch.rb
CHANGED
data/sig/fetch/config.rbs
CHANGED
@@ -1,20 +1,12 @@
|
|
1
1
|
module Fetch
|
2
2
|
class ConnectionPool
|
3
|
-
class Entry
|
4
|
-
attr_accessor connection: Net::HTTP
|
5
|
-
attr_accessor in_use: bool
|
6
|
-
attr_accessor last_used: Time
|
7
|
-
|
8
|
-
def initialize: (connection: Net::HTTP, in_use: bool, ?last_used: Time) -> void
|
9
|
-
end
|
10
|
-
|
11
3
|
def initialize: () -> void
|
12
4
|
def with_connection: [T] (URI::HTTP) { (Net::HTTP) -> T } -> T
|
13
5
|
|
14
6
|
private
|
15
7
|
|
16
|
-
def
|
17
|
-
def
|
8
|
+
def checkout: (URI::HTTP) -> Net::HTTP
|
9
|
+
def checkin: (URI::HTTP, Net::HTTP) -> void
|
18
10
|
def sweep: () -> void
|
19
11
|
end
|
20
12
|
end
|
data/sig/fetch.rbs
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fetch-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keita Urashima
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: forwardable
|
@@ -139,6 +139,7 @@ files:
|
|
139
139
|
- sig/fetch/headers.rbs
|
140
140
|
- sig/fetch/response.rbs
|
141
141
|
- sig/fetch/url_search_params.rbs
|
142
|
+
- sig/fetch/version.rbs
|
142
143
|
homepage: https://github.com/ursm/fetch-api
|
143
144
|
licenses:
|
144
145
|
- MIT
|
@@ -160,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
161
|
- !ruby/object:Gem::Version
|
161
162
|
version: '0'
|
162
163
|
requirements: []
|
163
|
-
rubygems_version: 3.5.
|
164
|
+
rubygems_version: 3.5.11
|
164
165
|
signing_key:
|
165
166
|
specification_version: 4
|
166
167
|
summary: Something like the Fetch API for Ruby
|