httpdisk 0.1.0 → 0.5.1
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/.rubocop.yml +28 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +36 -4
- data/README.md +36 -4
- data/Rakefile +21 -10
- data/bin/httpdisk +10 -8
- data/bin/httpdisk-grep +46 -0
- data/examples.rb +1 -2
- data/httpdisk.gemspec +3 -2
- data/lib/httpdisk.rb +10 -5
- data/lib/httpdisk/cache.rb +33 -22
- data/lib/httpdisk/cache_key.rb +17 -9
- data/lib/httpdisk/cli/args.rb +57 -0
- data/lib/httpdisk/cli/main.rb +169 -0
- data/lib/httpdisk/client.rb +94 -18
- data/lib/httpdisk/error.rb +4 -0
- data/lib/httpdisk/grep/args.rb +35 -0
- data/lib/httpdisk/grep/main.rb +112 -0
- data/lib/httpdisk/grep/printer.rb +99 -0
- data/lib/httpdisk/payload.rb +11 -9
- data/lib/httpdisk/slop_duration.rb +24 -0
- data/lib/httpdisk/sloptions.rb +105 -0
- data/lib/httpdisk/version.rb +1 -1
- metadata +26 -4
- data/lib/httpdisk/cli.rb +0 -218
- data/lib/httpdisk/cli_slop.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 994e5e02b7c4cdbfbfcef40099558c8fa86a97538da74065a76321c8ee25e129
|
4
|
+
data.tar.gz: 97ae05c7a08e2c9b3bdccc01a9679d63ab35ce4fabc6307087fbfa7946fbecef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09d938bd3b32d743aab858883c94a760a27c40762a98d792b4135df29625995582aac5571aca0b510d0e85adc8b99436f2ede87196581544ae5759de35df9cfb'
|
7
|
+
data.tar.gz: 18c4f281814896c8d8a9e8d513416538770263b4b17dea5fbc5a5e5612af9f3b0f39d86b5e54919df6466a2e18e73f52e125ad9d167b1912c4f3acc2cb8b8a27
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
SuggestExtensions: false
|
4
|
+
|
5
|
+
# this is buggy in 2.7.0
|
6
|
+
Style/HashTransformValues: { Enabled: false }
|
7
|
+
|
8
|
+
# minimal personal preference
|
9
|
+
Layout/CaseIndentation: { Enabled: false }
|
10
|
+
Layout/EndAlignment: { EnforcedStyleAlignWith: variable }
|
11
|
+
Lint/AssignmentInCondition: { Enabled: false }
|
12
|
+
Lint/NonLocalExitFromIterator: { Enabled: false }
|
13
|
+
Metrics: { Enabled: false }
|
14
|
+
Naming/MethodParameterName: { Enabled: false }
|
15
|
+
Naming/VariableNumber: { Enabled: false }
|
16
|
+
Style/Documentation: { Enabled: false }
|
17
|
+
Style/DoubleNegation: { Enabled: false }
|
18
|
+
Style/EmptyCaseCondition: { Enabled: false }
|
19
|
+
Style/FrozenStringLiteralComment: { Enabled: false }
|
20
|
+
Style/GuardClause: { Enabled: false }
|
21
|
+
Style/IfUnlessModifier: { Enabled: false }
|
22
|
+
Style/NegatedIf: { Enabled: false }
|
23
|
+
Style/NumericPredicate: { Enabled: false }
|
24
|
+
Style/ParallelAssignment: { Enabled: false }
|
25
|
+
Style/SoleNestedConditional: { Enabled: false }
|
26
|
+
Style/StderrPuts: { Enabled: false }
|
27
|
+
Style/TrailingCommaInArrayLiteral: { EnforcedStyleForMultiline: consistent_comma }
|
28
|
+
Style/TrailingCommaInHashLiteral: { EnforcedStyleForMultiline: consistent_comma }
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
httpdisk (0.1
|
4
|
+
httpdisk (0.5.1)
|
5
|
+
content-type (~> 0.0)
|
5
6
|
faraday (~> 1.4)
|
6
7
|
faraday-cookie_jar (~> 0.0)
|
7
8
|
faraday_middleware (~> 1.0)
|
@@ -12,43 +13,73 @@ GEM
|
|
12
13
|
specs:
|
13
14
|
addressable (2.7.0)
|
14
15
|
public_suffix (>= 2.0.2, < 5.0)
|
16
|
+
ast (2.4.2)
|
15
17
|
coderay (1.1.3)
|
18
|
+
content-type (0.0.1)
|
19
|
+
parslet (~> 1.5)
|
16
20
|
crack (0.4.5)
|
17
21
|
rexml
|
18
22
|
domain_name (0.5.20190701)
|
19
23
|
unf (>= 0.0.5, < 1.0.0)
|
20
|
-
faraday (1.
|
24
|
+
faraday (1.5.0)
|
25
|
+
faraday-em_http (~> 1.0)
|
26
|
+
faraday-em_synchrony (~> 1.0)
|
21
27
|
faraday-excon (~> 1.1)
|
28
|
+
faraday-httpclient (~> 1.0.1)
|
22
29
|
faraday-net_http (~> 1.0)
|
23
30
|
faraday-net_http_persistent (~> 1.1)
|
31
|
+
faraday-patron (~> 1.0)
|
24
32
|
multipart-post (>= 1.2, < 3)
|
25
33
|
ruby2_keywords (>= 0.0.4)
|
26
34
|
faraday-cookie_jar (0.0.7)
|
27
35
|
faraday (>= 0.8.0)
|
28
36
|
http-cookie (~> 1.0.0)
|
37
|
+
faraday-em_http (1.0.0)
|
38
|
+
faraday-em_synchrony (1.0.0)
|
29
39
|
faraday-excon (1.1.0)
|
40
|
+
faraday-httpclient (1.0.1)
|
30
41
|
faraday-net_http (1.0.1)
|
31
42
|
faraday-net_http_persistent (1.1.0)
|
43
|
+
faraday-patron (1.0.0)
|
32
44
|
faraday_middleware (1.0.0)
|
33
45
|
faraday (~> 1.0)
|
34
46
|
hashdiff (1.0.1)
|
35
|
-
http-cookie (1.0.
|
47
|
+
http-cookie (1.0.4)
|
36
48
|
domain_name (~> 0.5)
|
37
49
|
method_source (1.0.0)
|
38
50
|
minitest (5.14.4)
|
39
51
|
mocha (1.11.2)
|
40
52
|
multipart-post (2.1.1)
|
53
|
+
parallel (1.20.1)
|
54
|
+
parser (3.0.1.1)
|
55
|
+
ast (~> 2.4.1)
|
56
|
+
parslet (1.8.2)
|
41
57
|
pry (0.13.1)
|
42
58
|
coderay (~> 1.1)
|
43
59
|
method_source (~> 1.0)
|
44
60
|
public_suffix (4.0.6)
|
61
|
+
rainbow (3.0.0)
|
45
62
|
rake (13.0.3)
|
63
|
+
regexp_parser (2.1.1)
|
46
64
|
rexml (3.2.5)
|
65
|
+
rubocop (1.13.0)
|
66
|
+
parallel (~> 1.10)
|
67
|
+
parser (>= 3.0.0.0)
|
68
|
+
rainbow (>= 2.2.2, < 4.0)
|
69
|
+
regexp_parser (>= 1.8, < 3.0)
|
70
|
+
rexml
|
71
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
72
|
+
ruby-progressbar (~> 1.7)
|
73
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
74
|
+
rubocop-ast (1.5.0)
|
75
|
+
parser (>= 3.0.1.1)
|
76
|
+
ruby-progressbar (1.11.0)
|
47
77
|
ruby2_keywords (0.0.4)
|
48
|
-
slop (4.
|
78
|
+
slop (4.9.1)
|
49
79
|
unf (0.1.4)
|
50
80
|
unf_ext
|
51
81
|
unf_ext (0.0.7.7)
|
82
|
+
unicode-display_width (2.0.0)
|
52
83
|
webmock (3.12.2)
|
53
84
|
addressable (>= 2.3.6)
|
54
85
|
crack (>= 0.3.2)
|
@@ -63,6 +94,7 @@ DEPENDENCIES
|
|
63
94
|
mocha
|
64
95
|
pry
|
65
96
|
rake
|
97
|
+
rubocop (~> 1.13.0)
|
66
98
|
webmock
|
67
99
|
|
68
100
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -119,20 +119,27 @@ httpdisk caches all responses. POST responses are cached, along with 500 respons
|
|
119
119
|
|
120
120
|
In general, if you make a request it will be cached regardless of the outcome.
|
121
121
|
|
122
|
+
## String Encoding
|
123
|
+
|
124
|
+
httpdisk will honor the `Content-Type` from responses. Unfortunately, it is entirely possible to get invalid bodies if the `Content-Type` doesn't match the bytes. This is a major bummer, so httpdisk provides a `utf8:` option that forces text response bodies to UTF-8.
|
125
|
+
|
122
126
|
## Configuration
|
123
127
|
|
124
128
|
httpdisk supports a few options:
|
125
129
|
|
126
130
|
- `dir:` location for disk cache, defaults to `~/httpdisk`
|
127
|
-
- `
|
131
|
+
- `expires:` when to expire cached requests, default is nil (never expire)
|
128
132
|
- `force:` don't read anything from cache (but still write)
|
129
133
|
- `force_errors:` don't read errors from cache (but still write)
|
134
|
+
- `ignore_params:` array of query params to ignore when calculating cache_key
|
135
|
+
- `logger`: log requests to stderr, or pass your own logger
|
136
|
+
- `utf8`: if true, force text response bodies to valid UTF-8
|
130
137
|
|
131
138
|
Pass these in when setting up Faraday:
|
132
139
|
|
133
140
|
```ruby
|
134
141
|
faraday = Faraday.new do
|
135
|
-
_1.use :httpdisk,
|
142
|
+
_1.use :httpdisk, expires: 7*24*60*60, force: true
|
136
143
|
end
|
137
144
|
```
|
138
145
|
|
@@ -160,10 +167,13 @@ Specific to httpdisk:
|
|
160
167
|
--force don't read anything from cache (but still write)
|
161
168
|
--force-errors don't read errors from cache (but still write)
|
162
169
|
--status show status for a url in the cache
|
163
|
-
--version show version
|
164
|
-
--help show this help
|
165
170
|
```
|
166
171
|
|
172
|
+
## Goodies: httpdisk-grep
|
173
|
+
|
174
|
+
The `httpdisk-grep` command makes it easy to search your cache directory.
|
175
|
+
It can be challenging to use grep/ripgrep because cache files are compressed and JSON bodies often lack newlines. httpdisk-grep is the right tool for the job. See `httpdisk-grep --help`.
|
176
|
+
|
167
177
|
## Limitations & Gotchas
|
168
178
|
|
169
179
|
- Transient errors are cached. This is appropriate for many uses cases (like crawling) but can be confusing. Use `httpdisk --status` to debug.
|
@@ -174,6 +184,28 @@ Specific to httpdisk:
|
|
174
184
|
|
175
185
|
## Changelog
|
176
186
|
|
187
|
+
#### 0.5
|
188
|
+
|
189
|
+
- honor Content-Type
|
190
|
+
- added `:utf8` option to force text-like response bodies to UTF-8
|
191
|
+
|
192
|
+
#### 0.4
|
193
|
+
|
194
|
+
- added httpdisk-grep for searching cache files
|
195
|
+
- added HTTPDisk::Cache#delete
|
196
|
+
- rename `:expires_in` to `:expires`
|
197
|
+
|
198
|
+
#### 0.3
|
199
|
+
|
200
|
+
- added :ignore_params, for ignoring query params when generating cache keys
|
201
|
+
- HTTP 40x & 50x responses return :error status (and respond to `force_error`)
|
202
|
+
|
203
|
+
#### 0.2 - May 2020
|
204
|
+
|
205
|
+
- added `response.env[:httpdisk]`, which will be true if the response came from the cache
|
206
|
+
- added `:logger` option
|
207
|
+
- rake rubocop
|
208
|
+
|
177
209
|
#### 0.1 - April 2020
|
178
210
|
|
179
211
|
- Original release
|
data/Rakefile
CHANGED
@@ -10,12 +10,15 @@ spec = Gem::Specification.load('httpdisk.gemspec')
|
|
10
10
|
#
|
11
11
|
|
12
12
|
# test (default)
|
13
|
-
Rake::TestTask.new
|
13
|
+
Rake::TestTask.new do
|
14
|
+
_1.libs << 'test'
|
15
|
+
_1.warning = false # https://github.com/lostisland/faraday/issues/1285
|
16
|
+
end
|
14
17
|
task default: :test
|
15
18
|
|
16
|
-
# Watch files, run tests whenever something changes
|
19
|
+
# Watch rb files, run tests whenever something changes
|
17
20
|
task :watch do
|
18
|
-
|
21
|
+
sh "find . -name '*.rb' | entr -c rake"
|
19
22
|
end
|
20
23
|
|
21
24
|
#
|
@@ -23,7 +26,15 @@ end
|
|
23
26
|
#
|
24
27
|
|
25
28
|
task :pry do
|
26
|
-
|
29
|
+
sh 'pry -I lib -r httpdisk.rb'
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# rubocop
|
34
|
+
#
|
35
|
+
|
36
|
+
task :rubocop do
|
37
|
+
sh 'bundle exec rubocop -A .'
|
27
38
|
end
|
28
39
|
|
29
40
|
#
|
@@ -31,17 +42,17 @@ end
|
|
31
42
|
#
|
32
43
|
|
33
44
|
task :build do
|
34
|
-
|
45
|
+
sh 'gem build --quiet httpdisk.gemspec'
|
35
46
|
end
|
36
47
|
|
37
48
|
task install: :build do
|
38
|
-
|
49
|
+
sh "gem install --quiet httpdisk-#{spec.version}.gem"
|
39
50
|
end
|
40
51
|
|
41
|
-
task release:
|
52
|
+
task release: %i[rubocop test build] do
|
42
53
|
raise "looks like git isn't clean" unless `git status --porcelain`.empty?
|
43
54
|
|
44
|
-
|
45
|
-
|
46
|
-
|
55
|
+
sh "git tag -a #{spec.version} -m 'Tagging #{spec.version}'"
|
56
|
+
sh 'git push --tags'
|
57
|
+
sh "gem push httpdisk-#{spec.version}.gem"
|
47
58
|
end
|
data/bin/httpdisk
CHANGED
@@ -6,20 +6,22 @@
|
|
6
6
|
|
7
7
|
$LOAD_PATH.unshift(File.join(__dir__, '../lib'))
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
BIN = File.basename($PROGRAM_NAME)
|
10
|
+
|
11
|
+
def puts_error(s)
|
12
|
+
$stderr.puts "#{BIN}: #{s}"
|
11
13
|
end
|
12
14
|
|
13
15
|
#
|
14
16
|
# Load the bare minimum and parse args with slop. We do this separately for speed.
|
15
17
|
#
|
16
18
|
|
17
|
-
require 'httpdisk/
|
19
|
+
require 'httpdisk/cli/args'
|
18
20
|
begin
|
19
|
-
slop = HTTPDisk::
|
21
|
+
slop = HTTPDisk::Cli::Args.slop(ARGV)
|
20
22
|
rescue Slop::Error => e
|
21
23
|
puts_error(e) if e.message != ''
|
22
|
-
puts_error("try '
|
24
|
+
puts_error("try '#{BIN} --help' for more information")
|
23
25
|
exit 1
|
24
26
|
end
|
25
27
|
|
@@ -28,11 +30,11 @@ end
|
|
28
30
|
#
|
29
31
|
|
30
32
|
require 'httpdisk'
|
31
|
-
|
33
|
+
main = HTTPDisk::Cli::Main.new(slop)
|
32
34
|
begin
|
33
|
-
|
35
|
+
main.run
|
34
36
|
rescue StandardError => e
|
35
|
-
puts_error(e) if !
|
37
|
+
puts_error(e) if !main.options[:silent]
|
36
38
|
if ENV['HTTPDISK_DEBUG']
|
37
39
|
$stderr.puts
|
38
40
|
$stderr.puts e.backtrace.join("\n")
|
data/bin/httpdisk-grep
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#
|
4
|
+
# Search an HTTPDisk cache, similar to grep.
|
5
|
+
#
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(__dir__, '../lib'))
|
8
|
+
|
9
|
+
BIN = File.basename($PROGRAM_NAME)
|
10
|
+
|
11
|
+
def puts_error(s)
|
12
|
+
$stderr.puts "#{BIN}: #{s}"
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Load the bare minimum and parse args with slop. We do this separately for speed.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'httpdisk/grep/args'
|
20
|
+
begin
|
21
|
+
slop = HTTPDisk::Grep::Args.slop(ARGV)
|
22
|
+
rescue Slop::Error => e
|
23
|
+
puts_error(e) if e.message != ''
|
24
|
+
puts_error("try '#{BIN} --help' for more information")
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# now load everything and run
|
30
|
+
#
|
31
|
+
|
32
|
+
require 'httpdisk'
|
33
|
+
|
34
|
+
main = HTTPDisk::Grep::Main.new(slop)
|
35
|
+
begin
|
36
|
+
success = main.run
|
37
|
+
exit 1 if !success
|
38
|
+
rescue StandardError => e
|
39
|
+
puts_error(e)
|
40
|
+
if ENV['HTTPDISK_DEBUG']
|
41
|
+
$stderr.puts
|
42
|
+
$stderr.puts e.class
|
43
|
+
$stderr.puts e.backtrace.join("\n")
|
44
|
+
end
|
45
|
+
exit 2
|
46
|
+
end
|
data/examples.rb
CHANGED
@@ -18,7 +18,6 @@ class Examples
|
|
18
18
|
faraday.get('http://www.google.com', nil, { "User-Agent": 'test-agent' })
|
19
19
|
faraday.get('http://www.google.com', { q: 'ruby' })
|
20
20
|
faraday.post('http://httpbin.org/post', 'name=hello')
|
21
|
-
exit
|
22
21
|
|
23
22
|
3.times { puts }
|
24
23
|
response = faraday.get('http://httpbingo.org/get')
|
@@ -106,7 +105,7 @@ class Examples
|
|
106
105
|
end
|
107
106
|
|
108
107
|
3.times { puts }
|
109
|
-
response = faraday.post('http://httpbingo.org/post', { this_is: [
|
108
|
+
response = faraday.post('http://httpbingo.org/post', { this_is: ['json'] })
|
110
109
|
puts response.env.url
|
111
110
|
puts JSON.pretty_generate(response.body)
|
112
111
|
end
|
data/httpdisk.gemspec
CHANGED
@@ -3,7 +3,7 @@ require_relative 'lib/httpdisk/version'
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'httpdisk'
|
5
5
|
s.version = HTTPDisk::VERSION
|
6
|
-
s.authors = [
|
6
|
+
s.authors = ['Adam Doppelt']
|
7
7
|
s.email = 'amd@gurge.com'
|
8
8
|
|
9
9
|
s.summary = 'httpdisk - disk cache for faraday'
|
@@ -18,9 +18,10 @@ Gem::Specification.new do |s|
|
|
18
18
|
end
|
19
19
|
s.bindir = 'bin'
|
20
20
|
s.executables = s.files.grep(%r{^#{s.bindir}/}) { File.basename(_1) }
|
21
|
-
s.require_paths = [
|
21
|
+
s.require_paths = ['lib']
|
22
22
|
|
23
23
|
# gem dependencies
|
24
|
+
s.add_dependency 'content-type', '~> 0.0'
|
24
25
|
s.add_dependency 'faraday', '~> 1.4'
|
25
26
|
s.add_dependency 'faraday-cookie_jar', '~> 0.0'
|
26
27
|
s.add_dependency 'faraday_middleware', '~> 1.0'
|
data/lib/httpdisk.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
require 'httpdisk/cache_key'
|
2
2
|
require 'httpdisk/cache'
|
3
|
-
require 'httpdisk/cli_slop'
|
4
|
-
require 'httpdisk/cli'
|
5
3
|
require 'httpdisk/client'
|
6
4
|
require 'httpdisk/error'
|
7
5
|
require 'httpdisk/payload'
|
6
|
+
require 'httpdisk/slop_duration'
|
7
|
+
require 'httpdisk/sloptions'
|
8
8
|
require 'httpdisk/version'
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
# cli
|
11
|
+
require 'httpdisk/cli/args'
|
12
|
+
require 'httpdisk/cli/main'
|
13
|
+
|
14
|
+
# grep
|
15
|
+
require 'httpdisk/grep/args'
|
16
|
+
require 'httpdisk/grep/main'
|
17
|
+
require 'httpdisk/grep/printer'
|
data/lib/httpdisk/cache.rb
CHANGED
@@ -7,23 +7,9 @@ module HTTPDisk
|
|
7
7
|
|
8
8
|
def initialize(options)
|
9
9
|
@options = options
|
10
|
-
|
11
|
-
# heavy sanity checking on arguments here
|
12
|
-
if !dir.is_a?(String)
|
13
|
-
raise ArgumentError, "expected :dir to be a string, not #{dir.inspect}"
|
14
|
-
end
|
15
|
-
if expires_in && !expires_in.is_a?(Integer)
|
16
|
-
raise ArgumentError, "expected :expires_in to be an integer, not #{expires_in.inspect}"
|
17
|
-
end
|
18
|
-
%i[force force_errors].each do
|
19
|
-
value = send(_1)
|
20
|
-
if ![ nil, true, false ].include?(value)
|
21
|
-
raise ArgumentError, "expected #{_1} to be a boolean, not #{value.inspect}"
|
22
|
-
end
|
23
|
-
end
|
24
10
|
end
|
25
11
|
|
26
|
-
%i[dir
|
12
|
+
%i[dir expires force force_errors].each do |method|
|
27
13
|
define_method(method) do
|
28
14
|
options[method]
|
29
15
|
end
|
@@ -39,16 +25,35 @@ module HTTPDisk
|
|
39
25
|
|
40
26
|
# Cache status for a cache_key, %i[error force hit miss stale]
|
41
27
|
def status(cache_key)
|
42
|
-
payload_or_status = read0(cache_key)
|
28
|
+
payload_or_status = read0(cache_key, peek: true)
|
43
29
|
return payload_or_status if payload_or_status.is_a?(Symbol)
|
44
|
-
|
30
|
+
|
31
|
+
payload_or_status.error? ? :error : :hit
|
45
32
|
end
|
46
33
|
|
47
34
|
# Write response to the disk cache
|
48
35
|
def write(cache_key, payload)
|
49
36
|
path = diskpath(cache_key)
|
50
37
|
FileUtils.mkdir_p(File.dirname(path))
|
51
|
-
|
38
|
+
|
39
|
+
# Atomically write gzipped payload. Put our underlying Tempfile into
|
40
|
+
# binmode to avoid accidental newline conversion or string encoding. Not
|
41
|
+
# required for *nix systems, but I've heard rumors it's helpful for
|
42
|
+
# Windows.
|
43
|
+
Tempfile.new(binmode: true).tap do |tmp|
|
44
|
+
Zlib::GzipWriter.new(tmp).tap do |gzip|
|
45
|
+
payload.write(gzip)
|
46
|
+
gzip.close
|
47
|
+
end
|
48
|
+
tmp.close
|
49
|
+
FileUtils.mv(tmp.path, path)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Delete existing response, if any
|
54
|
+
def delete(cache_key)
|
55
|
+
path = diskpath(cache_key)
|
56
|
+
FileUtils.rm(path) if File.exist?(path)
|
52
57
|
end
|
53
58
|
|
54
59
|
# Relative path for this cache_key based on the cache key
|
@@ -59,22 +64,28 @@ module HTTPDisk
|
|
59
64
|
protected
|
60
65
|
|
61
66
|
# low level read, returns payload or status
|
62
|
-
def read0(cache_key)
|
67
|
+
def read0(cache_key, peek: false)
|
63
68
|
path = diskpath(cache_key)
|
64
69
|
|
65
70
|
return :miss if !File.exist?(path)
|
66
71
|
return :stale if expired?(path)
|
67
72
|
return :force if force?
|
68
73
|
|
69
|
-
|
70
|
-
|
74
|
+
begin
|
75
|
+
payload = Zlib::GzipReader.open(path, encoding: 'ASCII-8BIT') do
|
76
|
+
Payload.read(_1, peek: peek)
|
77
|
+
end
|
78
|
+
rescue StandardError => e
|
79
|
+
raise "#{path}: #{e}"
|
80
|
+
end
|
81
|
+
return :force if force_errors? && payload.error?
|
71
82
|
|
72
83
|
payload
|
73
84
|
end
|
74
85
|
|
75
86
|
# Is this path expired?
|
76
87
|
def expired?(path)
|
77
|
-
|
88
|
+
expires && File.stat(path).mtime < Time.now - expires
|
78
89
|
end
|
79
90
|
end
|
80
91
|
end
|