async-http-cache 0.1.3 → 0.4.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 +4 -4
- data/.github/workflows/development.yml +0 -1
- data/Gemfile +4 -0
- data/async-http-cache.gemspec +2 -3
- data/lib/async/http/cache/body.rb +33 -17
- data/lib/async/http/cache/general.rb +12 -3
- data/lib/async/http/cache/response.rb +11 -1
- data/lib/async/http/cache/store/memory.rb +11 -1
- data/lib/async/http/cache/version.rb +1 -1
- metadata +9 -24
- data/Rakefile +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17173f66af03c869ff56b8dd197565e230d10899eee2d3da2f18685ca670e892
|
4
|
+
data.tar.gz: 1d6b1a438c596bdca021820f69dd86f02bcca593ffd771ab7912feb8f2f530a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43ab1d479efa3d86814c73241ba78281ea3ce7fa125fde7393556ba1529192608da09979dc6e895e81621531beaf132195fb993d72638a35c38489e4f6436f37
|
7
|
+
data.tar.gz: 79e4aaf2b574eab58253a92e5dc55b0f526733ad3335f035f3b07b91a3f1e54bc4e039e047d1c31da4484e41c132607888edc4c44ef8734bdb31c4ee87a86d8a
|
data/Gemfile
CHANGED
data/async-http-cache.gemspec
CHANGED
@@ -21,13 +21,12 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
-
spec.add_dependency "async-http"
|
25
|
-
spec.add_dependency "protocol-http", "~> 0.14"
|
24
|
+
spec.add_dependency "async-http", "~> 0.56"
|
26
25
|
|
27
26
|
spec.add_development_dependency "async-rspec", "~> 1.10"
|
28
27
|
|
29
28
|
spec.add_development_dependency "covered"
|
30
29
|
spec.add_development_dependency "bundler"
|
31
30
|
spec.add_development_dependency "rspec"
|
32
|
-
spec.add_development_dependency "
|
31
|
+
spec.add_development_dependency "bake-bundler"
|
33
32
|
end
|
@@ -21,33 +21,49 @@
|
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
23
|
require 'protocol/http/body/rewindable'
|
24
|
-
require 'protocol/http/body/
|
24
|
+
require 'protocol/http/body/completable'
|
25
|
+
require 'protocol/http/body/digestable'
|
25
26
|
|
26
27
|
module Async
|
27
28
|
module HTTP
|
28
29
|
module Cache
|
29
30
|
module Body
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
TRAILER = 'trailer'
|
32
|
+
ETAG = 'etag'
|
33
|
+
|
34
|
+
def self.wrap(response, &block)
|
35
|
+
if body = response.body
|
36
|
+
if body.empty?
|
37
|
+
# A body that is empty? at the outset, is immutable. This generally only applies to HEAD requests.
|
38
|
+
yield response, body
|
39
|
+
else
|
40
|
+
# Insert a rewindable body so that we can cache the response body:
|
41
|
+
rewindable = ::Protocol::HTTP::Body::Rewindable.wrap(response)
|
42
|
+
|
43
|
+
unless response.headers.include?(ETAG)
|
44
|
+
# Compute a digest and add it to the response headers:
|
45
|
+
::Protocol::HTTP::Body::Digestable.wrap(response) do |wrapper|
|
46
|
+
response.headers.add(ETAG, wrapper.etag)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Ensure the etag is listed as a trailer:
|
50
|
+
response.headers.add(TRAILER, ETAG)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Wrap the response with the callback:
|
54
|
+
::Protocol::HTTP::Body::Completable.wrap(response) do |error|
|
55
|
+
if error
|
56
|
+
Async.logger.error(self) {error}
|
57
|
+
else
|
58
|
+
yield response, rewindable.buffered
|
59
|
+
end
|
44
60
|
end
|
45
61
|
end
|
46
62
|
else
|
47
|
-
yield
|
63
|
+
yield response, nil
|
48
64
|
end
|
49
65
|
|
50
|
-
return
|
66
|
+
return response
|
51
67
|
end
|
52
68
|
end
|
53
69
|
end
|
@@ -31,6 +31,7 @@ module Async
|
|
31
31
|
module Cache
|
32
32
|
class General < ::Protocol::HTTP::Middleware
|
33
33
|
CACHE_CONTROL = 'cache-control'
|
34
|
+
|
34
35
|
CONTENT_TYPE = 'content-type'
|
35
36
|
AUTHORIZATION = 'authorization'
|
36
37
|
COOKIE = 'cookie'
|
@@ -91,9 +92,17 @@ module Async
|
|
91
92
|
return response
|
92
93
|
end
|
93
94
|
|
94
|
-
|
95
|
+
if request.head? and body = response.body
|
96
|
+
unless body.empty?
|
97
|
+
Async.logger.warn(self) {"HEAD request resulted in non-empty body!"}
|
98
|
+
|
99
|
+
return response
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
return Body.wrap(response) do |response, body|
|
95
104
|
Async.logger.debug(self) {"Updating cache for #{key}..."}
|
96
|
-
@store.insert(key, request, Response.new(
|
105
|
+
@store.insert(key, request, Response.new(response, body))
|
97
106
|
end
|
98
107
|
end
|
99
108
|
|
@@ -107,7 +116,7 @@ module Async
|
|
107
116
|
Async.logger.debug(self) {"Cache hit for #{key}..."}
|
108
117
|
@count += 1
|
109
118
|
|
110
|
-
#
|
119
|
+
# Return the cached response:
|
111
120
|
return response
|
112
121
|
end
|
113
122
|
end
|
@@ -29,6 +29,9 @@ module Async
|
|
29
29
|
class Response < ::Protocol::HTTP::Response
|
30
30
|
CACHE_CONTROL = 'cache-control'
|
31
31
|
SET_COOKIE = 'set-cookie'
|
32
|
+
ETAG = 'etag'
|
33
|
+
|
34
|
+
X_CACHE = 'x-cache'
|
32
35
|
|
33
36
|
def initialize(response, body)
|
34
37
|
@generated_at = Async::Clock.now
|
@@ -36,16 +39,23 @@ module Async
|
|
36
39
|
super(
|
37
40
|
response.version,
|
38
41
|
response.status,
|
39
|
-
response.headers.
|
42
|
+
response.headers.flatten,
|
40
43
|
body,
|
41
44
|
response.protocol
|
42
45
|
)
|
43
46
|
|
44
47
|
@max_age = @headers[CACHE_CONTROL]&.max_age
|
48
|
+
@etag = nil
|
49
|
+
|
50
|
+
@headers.set(X_CACHE, 'hit')
|
45
51
|
end
|
46
52
|
|
47
53
|
attr :generated_at
|
48
54
|
|
55
|
+
def etag
|
56
|
+
@etag ||= @headers[ETAG]
|
57
|
+
end
|
58
|
+
|
49
59
|
def cachable?
|
50
60
|
if cache_control = @headers[CACHE_CONTROL]
|
51
61
|
if cache_control.private? || !cache_control.public?
|
@@ -64,6 +64,9 @@ module Async
|
|
64
64
|
|
65
65
|
attr :index
|
66
66
|
|
67
|
+
IF_NONE_MATCH = 'if-none-match'
|
68
|
+
NOT_MODIFIED = ::Protocol::HTTP::Response[304]
|
69
|
+
|
67
70
|
def lookup(key, request)
|
68
71
|
if response = @index[key]
|
69
72
|
if response.expired?
|
@@ -74,6 +77,12 @@ module Async
|
|
74
77
|
return nil
|
75
78
|
end
|
76
79
|
|
80
|
+
if etags = request.headers[IF_NONE_MATCH]
|
81
|
+
if etags.include?(response.etag)
|
82
|
+
return NOT_MODIFIED
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
77
86
|
@hit += 1
|
78
87
|
|
79
88
|
return response.dup
|
@@ -86,7 +95,8 @@ module Async
|
|
86
95
|
|
87
96
|
def insert(key, request, response)
|
88
97
|
if @index.size < @limit
|
89
|
-
|
98
|
+
length = response.body&.length
|
99
|
+
if length.nil? or length < 1024*64
|
90
100
|
@index[key] = response
|
91
101
|
end
|
92
102
|
end
|
metadata
CHANGED
@@ -1,43 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async-http-cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-http
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: protocol-http
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
17
|
- - "~>"
|
32
18
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
19
|
+
version: '0.56'
|
34
20
|
type: :runtime
|
35
21
|
prerelease: false
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
37
23
|
requirements:
|
38
24
|
- - "~>"
|
39
25
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0.
|
26
|
+
version: '0.56'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: async-rspec
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,7 +81,7 @@ dependencies:
|
|
95
81
|
- !ruby/object:Gem::Version
|
96
82
|
version: '0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
84
|
+
name: bake-bundler
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
87
|
- - ">="
|
@@ -108,7 +94,7 @@ dependencies:
|
|
108
94
|
- - ">="
|
109
95
|
- !ruby/object:Gem::Version
|
110
96
|
version: '0'
|
111
|
-
description:
|
97
|
+
description:
|
112
98
|
email:
|
113
99
|
- samuel.williams@oriontransfer.co.nz
|
114
100
|
executables: []
|
@@ -120,7 +106,6 @@ files:
|
|
120
106
|
- ".rspec"
|
121
107
|
- Gemfile
|
122
108
|
- README.md
|
123
|
-
- Rakefile
|
124
109
|
- async-http-cache.gemspec
|
125
110
|
- lib/async/http/cache.rb
|
126
111
|
- lib/async/http/cache/body.rb
|
@@ -134,7 +119,7 @@ homepage: https://github.com/socketry/async-http-cache
|
|
134
119
|
licenses:
|
135
120
|
- MIT
|
136
121
|
metadata: {}
|
137
|
-
post_install_message:
|
122
|
+
post_install_message:
|
138
123
|
rdoc_options: []
|
139
124
|
require_paths:
|
140
125
|
- lib
|
@@ -150,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
135
|
version: '0'
|
151
136
|
requirements: []
|
152
137
|
rubygems_version: 3.1.2
|
153
|
-
signing_key:
|
138
|
+
signing_key:
|
154
139
|
specification_version: 4
|
155
140
|
summary: Standard-compliant cache for async-http.
|
156
141
|
test_files: []
|