httparty-cache 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ff16750de74919a4428091908be24f05775deded7885af69960c38265ee1679b
4
+ data.tar.gz: 12ccabffc3f4d24dfeef6327a3ac5649560b275051840826f31c3482e2075b2d
5
+ SHA512:
6
+ metadata.gz: f2d9b8a53ed1ef26b0ab22dc64108ea69cecfc76c13505b4d184e2df0823ddb78857ccf815152bc1adf202a94a0b1a3010af4c7714012842f675ee3428c6109e
7
+ data.tar.gz: 5b33148ca9f3d650218f66ca59964c04c91e87dfa730f8cd997aaad87fe36d19decdf1833463512ecc3f457cbe1bb8b5fbe7c5f4527325fe686cde1718b335e7
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # HTTParty cache
2
+
3
+ Implements [HTTP caching][] support to [HTTParty][] requests by following
4
+ servers' headers such as [Cache-Control][], specifically the `max-age`,
5
+ `must-revalidate` and`no-cache` directives, [Vary][], [ETag][],
6
+ [Last-Modified][] to perform response [validation][].
7
+
8
+ [HTTP caching]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
9
+ [Cache-Control]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/cache-control
10
+ [Vary]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/vary
11
+ [ETag]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/etag
12
+ [Last-Modified]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/last-modified
13
+ [validation]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#validation
14
+ [HTTParty]: https://github.com/jnunemaker/httparty
15
+
16
+ ## Use
17
+
18
+ Add this gem to your `Gemfile` and install dependencies.
19
+
20
+ Configure your `HTTParty` client to use a cache store and perform
21
+ caching:
22
+
23
+ ```ruby
24
+ require 'httparty'
25
+ require 'httparty/cache'
26
+
27
+ class Client
28
+ include HTTParty
29
+ include HTTParty::Cache
30
+
31
+ caching true
32
+ cache_store :memory
33
+ end
34
+ ```
35
+
36
+ ### Cache stores
37
+
38
+ #### Redis
39
+
40
+ If you want to use Redis as a cache store:
41
+
42
+ 1. Add `redis-client` and optionally `hiredis-client` gems to your
43
+ `Gemfile`.
44
+
45
+ 2. Set the environment variable `REDIS_URL` with the server URL, or
46
+ initialize the cache store with a custom URL.
47
+
48
+ ```ruby
49
+ require 'httparty'
50
+ require 'httparty/cache'
51
+ require 'httparty/cache/store/redis'
52
+
53
+ class Client
54
+ include HTTParty
55
+ include HTTParty::Cache
56
+
57
+ caching true
58
+ cache_store :redis
59
+ # or
60
+ cache_store HTTParty::Cache::Store::Redis.new(redis_url: 'redis://redis.provider:6379')
61
+ end
62
+ ```
63
+
64
+ #### Jekyll
65
+
66
+ If you want to use Jekyll as a cache store, for instance while writing
67
+ a plugin using HTTParty:
68
+
69
+ ```ruby
70
+ require 'httparty'
71
+ require 'httparty/cache'
72
+ require 'httparty/cache/store/jekyll'
73
+
74
+ class Client
75
+ include HTTParty
76
+ include HTTParty::Cache
77
+
78
+ caching true
79
+ cache_store :jekyll
80
+ # or
81
+ cache_store HTTParty::Cache::Store::Jekyll.new(name: 'My::Jekyll::Cache')
82
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTParty
4
+ module Cache
5
+ # Extends HTTParty::Request with caching methods
6
+ #
7
+ # @see {https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching}
8
+ module Request
9
+ CACHE_REVALIDATION_HEADERS = {
10
+ 'ETag' => 'If-None-Match',
11
+ 'Last-Modified' => 'If-Modified-Since'
12
+ }.freeze
13
+
14
+ # Calculates a cache key from URI + query string + headers
15
+ #
16
+ # @return [String]
17
+ def cache_key
18
+ @cache_key ||= "request:#{uri}##{URI.encode_www_form(options[:headers] || {})}"
19
+ end
20
+
21
+ def validate
22
+ super
23
+
24
+ raise ArgumentError, 'Caching is enabled but store was not provided' if caching? && cache_store.nil?
25
+ end
26
+
27
+ # Patch HTTParty::Request#perform to provide caching for GET
28
+ # requests
29
+ #
30
+ # @return [HTTParty::Response]
31
+ def perform(&block)
32
+ return super(&block) unless caching? && http_method == Net::HTTP::Get
33
+
34
+ if cached?
35
+ handle_revalidation
36
+ else
37
+ super(&block).tap do |response|
38
+ # Point current request to cached response
39
+ cache_store.set(response.cache_key, response)
40
+ cache_store.set(cache_key, response.cache_key)
41
+ end
42
+ end
43
+ end
44
+
45
+ # When the request is performed for the first time or has been
46
+ # evicted from cache or is corrupted
47
+ #
48
+ # @return [Bool]
49
+ def cached?
50
+ cache_store.key?(cache_key) &&
51
+ cache_store.key?(cache_store.get(cache_key)) &&
52
+ cache_store.get(cache_store.get(cache_key)).is_a?(HTTParty::Response)
53
+ end
54
+
55
+ def caching?
56
+ !!options[:caching]
57
+ end
58
+
59
+ private
60
+
61
+ # Revalidates request
62
+ #
63
+ # @return [HTTParty::Response]
64
+ def handle_revalidation
65
+ cached_response = cache_store.get(cache_store.get(cache_key))
66
+
67
+ if cached_response.revalidate? || cached_response.stale?
68
+ self.http_method = Net::HTTP::Head
69
+ options[:cached_response] = cached_response
70
+
71
+ add_cache_revalidation_headers
72
+
73
+ response = perform
74
+
75
+ if response.not_modified?
76
+ cached_response.headers['date'] = response.headers['date']
77
+ response = cached_response
78
+ else
79
+ self.http_method = Net::HTTP::Get
80
+ # Remove from cache so we can perform the request, otherwise
81
+ # we produce an infinite loop
82
+ cache_store.delete(cache_key)
83
+ response = perform
84
+ end
85
+
86
+ cache_store.set(response.cache_key, response)
87
+ response
88
+ else
89
+ cached_response
90
+ end
91
+ end
92
+
93
+ # Just a shortcut
94
+ def cache_store
95
+ options[:cache_store]
96
+ end
97
+
98
+ # Adds revalidation headers unless they're already present
99
+ #
100
+ # @return [nil]
101
+ def add_cache_revalidation_headers
102
+ options[:headers] ||= {}
103
+
104
+ CACHE_REVALIDATION_HEADERS.each_pair do |original_header, revalidation_header|
105
+ next if (value = options[:cached_response].headers[original_header]).nil?
106
+
107
+ options[:headers][revalidation_header] ||= value
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ # Patch HTTParty::Request
115
+ HTTParty::Request.class_eval do
116
+ prepend HTTParty::Cache::Request
117
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTParty
4
+ module Cache
5
+ # Extends HTTParty::Response with caching methods
6
+ #
7
+ # @see {https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching}
8
+ module Response
9
+ # Detects if response is cached
10
+ def cached?
11
+ code == 304
12
+ end
13
+
14
+ # Parses Cache-Control headers
15
+ #
16
+ # @see {https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/cache-control}
17
+ # @return [Hash]
18
+ def cache_control
19
+ @cache_control ||= headers['Cache-Control'].to_s.downcase.split(',').map(&:strip).map do |c|
20
+ k, v = c.split('=', 2).map(&:strip)
21
+
22
+ [k.tr('-', '_').to_sym, (v ? Integer(v) : true)]
23
+ end.to_h
24
+ end
25
+
26
+ # Returns the request date
27
+ #
28
+ # @return [Time]
29
+ def date
30
+ Time.parse(headers['date'])
31
+ rescue TypeError, ArgumentError
32
+ raise HTTParty::ResponseError, response
33
+ end
34
+
35
+ # Returns the current age of the request in seconds
36
+ #
37
+ # @return [Integer]
38
+ def age
39
+ (Time.now - date).to_i
40
+ rescue HTTParty::ResponseError
41
+ 0
42
+ end
43
+
44
+ # The response is stale when it has been cached for more than the
45
+ # allowed max age
46
+ #
47
+ # @return [Bool]
48
+ def stale?
49
+ !cache_control[:max_age].nil? && age > cache_control[:max_age]
50
+ end
51
+
52
+ # Detects if the response must be revalidated even if still fresh.
53
+ #
54
+ # @see {https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#force_revalidation}
55
+ # @return [Bool]
56
+ def revalidate?
57
+ !!(cache_control[:no_cache] || (cache_control[:max_age]&.zero? && cache_control[:must_revalidate]))
58
+ end
59
+
60
+ # Returns the request headers that vary responses
61
+ #
62
+ # @return [Hash]
63
+ def vary
64
+ @vary ||= request.options[:headers].to_h.slice(*headers['Vary'].to_s.split(',').map(&:strip).sort)
65
+ end
66
+
67
+ # Generates a cache key
68
+ #
69
+ # @return [String]
70
+ def cache_key
71
+ @cache_key ||= "response:#{request.uri}##{URI.encode_www_form vary}"
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ # Patch HTTParty::Response
78
+ HTTParty::Response.include HTTParty::Cache::Response
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTParty
4
+ module Cache
5
+ module Store
6
+ # Cache store
7
+ class Abstract
8
+ # @return [Hash]
9
+ attr_reader :options
10
+
11
+ # @param :key [String]
12
+ # @return [Response,nil]
13
+ def get(key)
14
+ raise NotImplementedError
15
+ end
16
+
17
+ # @param :key [String]
18
+ # @param :response [Response]
19
+ # @return [Response]
20
+ def set(key, response)
21
+ raise NotImplementedError
22
+ end
23
+
24
+ # @param :key [String]
25
+ # @return nil
26
+ def delete(key)
27
+ raise NotImplementedError
28
+ end
29
+
30
+ # @param :key [String]
31
+ # @yield
32
+ def getset(key, &block)
33
+ raise NotImplementedError
34
+ end
35
+
36
+ # @param :key [String]
37
+ # @return [Boolean]
38
+ def key?(key)
39
+ raise NotImplementedError
40
+ end
41
+
42
+ def clear
43
+ raise NotImplementedError
44
+ end
45
+
46
+ def marshal_dump
47
+ [
48
+ self.class.name,
49
+ options || {}
50
+ ]
51
+ end
52
+
53
+ def marshal_load(array)
54
+ Object.const_get(array.first).new(**array.last)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'abstract'
4
+ require 'jekyll/cache'
5
+
6
+ module HTTParty
7
+ module Cache
8
+ module Store
9
+ class Jekyll < Abstract
10
+ extend Forwardable
11
+
12
+ def_delegators :@store, :key?, :delete, :clear, :getset
13
+
14
+ # @return [Hash]
15
+ attr_reader :options
16
+
17
+ # @param :name [String]
18
+ def initialize(name: self.class.name)
19
+ @options = {}
20
+ @options[:name] = name
21
+ @store = ::Jekyll::Cache.new(name)
22
+ end
23
+
24
+ def set(key, response)
25
+ @store[key] = response
26
+ response
27
+ end
28
+
29
+ def get(key)
30
+ @store[key]
31
+ rescue RuntimeError
32
+ nil
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'abstract'
4
+
5
+ module HTTParty
6
+ module Cache
7
+ module Store
8
+ class Memory < Abstract
9
+ extend Forwardable
10
+
11
+ attr_reader :store
12
+
13
+ def_delegator :@store, :[], :get
14
+ def_delegator :@store, :[]=, :set
15
+
16
+ def_delegators :@store, :key?, :delete
17
+
18
+ def initialize(**)
19
+ clear
20
+ end
21
+
22
+ def getset(key)
23
+ store[key] ||= yield
24
+ end
25
+
26
+ def clear
27
+ @store = {}
28
+ nil
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'abstract'
4
+ require 'redis-client'
5
+
6
+ begin
7
+ require 'hiredis-client'
8
+ RedisClient.default_driver = :hiredis
9
+ rescue LoadError
10
+ end
11
+
12
+ module HTTParty
13
+ module Cache
14
+ module Store
15
+ class Redis < Abstract
16
+ # A Marshaled `nil` value
17
+ NIL = "\x04\b0"
18
+
19
+ # @return [Hash]
20
+ attr_reader :options
21
+
22
+ # @param :redis_url [String]
23
+ def initialize(redis_url: nil)
24
+ @options = {}
25
+ @options[:redis_url] = redis_url || ENV['REDIS_URL']
26
+ @config = RedisClient.config(url: @options[:redis_url])
27
+ @redis = @config.new_pool(size: 2)
28
+ @redis.call('PING')
29
+ end
30
+
31
+ # Retrieves a key
32
+ #
33
+ # @param :key [String]
34
+ # @return [Response,nil]
35
+ def get(key)
36
+ Marshal.load(redis('GET', key) || NIL)
37
+ end
38
+
39
+ # Stores a Marshaled value indexed by a key.
40
+ #
41
+ # @param :key [String]
42
+ # @param :response [Response]
43
+ # @return [Response]
44
+ def set(key, response)
45
+ redis('SET', key, Marshal.dump(response))
46
+ response
47
+ end
48
+
49
+ # Returns a key or set its value to a block result
50
+ #
51
+ # @param :key [String]
52
+ # @return [Response,nil]
53
+ def getset(key)
54
+ return get(key) if key?(key)
55
+
56
+ set(key, yield)
57
+ end
58
+
59
+ # Removes a key from Redis
60
+ #
61
+ # @param :key [String]
62
+ # @return [nil]
63
+ def delete(key)
64
+ redis('DEL', key)
65
+ nil
66
+ end
67
+
68
+ # Discovers if a key exists
69
+ #
70
+ # @param :key [String]
71
+ # @return [Boolean]
72
+ def key?(key)
73
+ redis('EXISTS', key).positive?
74
+ end
75
+
76
+ def clear
77
+ redis('FLUSHALL', 'SYNC')
78
+ nil
79
+ end
80
+
81
+ private
82
+
83
+ # Execs Redis commands and collects stats
84
+ def redis(*args)
85
+ @redis.call(*args)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTParty
4
+ module Cache
5
+ module Store
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTParty
4
+ # HTTParty plugin to manage cache
5
+ module Cache
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+
9
+ require_relative 'cache/response'
10
+ require_relative 'cache/request'
11
+ end
12
+
13
+ module ClassMethods
14
+ # This is both a setter and a getter...
15
+ #
16
+ # @param :cache_store [Symbol,HTTParty::Cache::Store::Abstract]
17
+ # @return [HTTParty::Cache::Store::Abstract]
18
+ def cache_store(cache_store = nil)
19
+ case cache_store
20
+ when NilClass
21
+ return default_options[:cache_store]
22
+ when Symbol
23
+ require_relative "cache/store/#{cache_store}"
24
+
25
+ class_name = cache_store.to_s.split('_').map(&:capitalize).join
26
+ cache_store = Object.const_get("HTTParty::Cache::Store::#{class_name}").new
27
+ end
28
+
29
+ default_options[:cache_store] = cache_store
30
+ end
31
+
32
+ # Toggle caching
33
+ #
34
+ # @param :caching [Bool]
35
+ # @return [Bool]
36
+ def caching(caching)
37
+ default_options[:caching] = caching
38
+ end
39
+
40
+ # Sets cache_control
41
+ def cache_control(cache_control)
42
+ default_options[:cache_control] = cache_control
43
+ end
44
+ end
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,259 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: httparty-cache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - f
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.18'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.18'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: factory_bot
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.6'
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 3.6.0
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '3.6'
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 3.6.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec-tap-formatters
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: yard
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: hiredis-client
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: 0.14.0
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 0.14.0
131
+ - !ruby/object:Gem::Dependency
132
+ name: redis-client
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 0.14.0
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: 0.14.0
145
+ - !ruby/object:Gem::Dependency
146
+ name: rubocop
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ - !ruby/object:Gem::Dependency
160
+ name: timecop
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ - !ruby/object:Gem::Dependency
174
+ name: jekyll
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ type: :development
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ - !ruby/object:Gem::Dependency
188
+ name: webmock
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - "~>"
192
+ - !ruby/object:Gem::Version
193
+ version: '1.24'
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: 1.24.3
197
+ type: :development
198
+ prerelease: false
199
+ version_requirements: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - "~>"
202
+ - !ruby/object:Gem::Version
203
+ version: '1.24'
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: 1.24.3
207
+ description: A cache manager for HTTParty
208
+ email:
209
+ - f@sutty.nl
210
+ executables: []
211
+ extensions: []
212
+ extra_rdoc_files:
213
+ - README.md
214
+ files:
215
+ - README.md
216
+ - lib/httparty/cache.rb
217
+ - lib/httparty/cache/request.rb
218
+ - lib/httparty/cache/response.rb
219
+ - lib/httparty/cache/store.rb
220
+ - lib/httparty/cache/store/abstract.rb
221
+ - lib/httparty/cache/store/jekyll.rb
222
+ - lib/httparty/cache/store/memory.rb
223
+ - lib/httparty/cache/store/redis.rb
224
+ homepage: https://0xacab.org/sutty/httparty-cache
225
+ licenses:
226
+ - MIT
227
+ metadata:
228
+ bug_tracker_uri: https://0xacab.org/sutty/httparty-cache/issues
229
+ homepage_uri: https://0xacab.org/sutty/httparty-cache
230
+ source_code_uri: https://0xacab.org/sutty/httparty-cache
231
+ changelog_uri: https://0xacab.org/sutty/httparty-cache/-/blob/master/CHANGELOG.md
232
+ documentation_uri: https://rubydoc.info/gems/httparty-cache
233
+ post_install_message:
234
+ rdoc_options:
235
+ - "--title"
236
+ - httparty-cache - HTTParty cache
237
+ - "--main"
238
+ - README.md
239
+ - "--line-numbers"
240
+ - "--inline-source"
241
+ - "--quiet"
242
+ require_paths:
243
+ - lib
244
+ required_ruby_version: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - ">="
247
+ - !ruby/object:Gem::Version
248
+ version: '2.7'
249
+ required_rubygems_version: !ruby/object:Gem::Requirement
250
+ requirements:
251
+ - - ">="
252
+ - !ruby/object:Gem::Version
253
+ version: '0'
254
+ requirements: []
255
+ rubygems_version: 3.3.26
256
+ signing_key:
257
+ specification_version: 4
258
+ summary: HTTParty cache
259
+ test_files: []