Class: Resourceful::Request
Constant Summary collapse
- REDIRECTABLE_METHODS =
[:get, :head]
- CACHEABLE_METHODS =
[:get, :head]
- INVALIDATING_METHODS =
[:post, :put, :delete]
Instance Attribute Summary collapse
-
#accessor ⇒ Object
readonly
Returns the value of attribute accessor.
-
#body ⇒ Object
Returns the value of attribute body.
-
#header ⇒ Object
Returns the value of attribute header.
-
#method ⇒ Object
Returns the value of attribute method.
-
#request_time ⇒ Object
readonly
Returns the value of attribute request_time.
-
#resource ⇒ Object
Returns the value of attribute resource.
Instance Method Summary collapse
- #adapter ⇒ Object
-
#add_credentials! ⇒ Object
Uses the auth manager to add any valid credentials to this request.
-
#cacheable?(response) ⇒ Boolean
Is this request & response permitted to be stored in this (private) cache?.
-
#cached_response ⇒ Object
The cached response.
-
#fetch_response ⇒ Object
Performs all the work.
-
#follow_redirect(response) ⇒ Object
Follow a redirect response.
-
#forces_revalidation? ⇒ Boolean
Does this request force us to revalidate the cache?.
-
#initialize(http_method, resource, body = nil, header = nil) ⇒ Request
constructor
A new instance of Request.
-
#invalidate_cache ⇒ Object
Invalidated the cache for this uri (eg, after a POST).
-
#invalidates_cache? ⇒ Boolean
Does this request invalidate the cache?.
- #logger ⇒ Object
-
#max_age ⇒ Object
Indicates the maxmimum response age in seconds we are willing to accept.
-
#needs_authorization?(response) ⇒ Boolean
Does this request need to be authorized? Will only be true if we haven’t already tried with auth.
-
#needs_revalidation?(response) ⇒ Boolean
Do we need to revalidate our cache?.
-
#perform! ⇒ Object
Perform the request, with no magic handling of anything.
-
#retry_with_auth(response) ⇒ Object
Add any auth headers from the response to the auth manager, and try the request again.
-
#revalidate_cached_response(not_modified_response) ⇒ Object
Revalidate the cached response with what we got from a 304 response.
-
#set_validation_headers!(response) ⇒ Object
Set the validation headers of a request based on the response in the cache.
-
#should_be_redirected?(response) ⇒ Boolean
Is this a response a redirect, and are we permitted to follow it?.
-
#skip_cache? ⇒ Boolean
Should we look for a response to this request in the cache?.
-
#store_in_cache(response) ⇒ Object
Store the response to this request in the cache.
-
#uri ⇒ String
The URI against which this request will be, or was, made.
Constructor Details
#initialize(http_method, resource, body = nil, header = nil) ⇒ Request
Returns a new instance of Request.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/resourceful/request.rb', line 23 def initialize(http_method, resource, body = nil, header = nil) @method, @resource, @body = http_method, resource, body @accessor = @resource.accessor @header = header.is_a?(Resourceful::Header) ? header : Resourceful::Header.new(header) # Resourceful handled gzip encoding transparently, so set that up @header.accept_encoding ||= 'gzip, identity' # 'Host' is a required HTTP/1.1 header, overrides Host in user-provided headers @header.host = @resource.host # Setting the date isn't a bad idea, either @header.date ||= Time.now.httpdate # Add any auth credentials we might want add_credentials! end |
Instance Attribute Details
#accessor ⇒ Object (readonly)
Returns the value of attribute accessor.
16 17 18 |
# File 'lib/resourceful/request.rb', line 16 def accessor @accessor end |
#body ⇒ Object
Returns the value of attribute body.
15 16 17 |
# File 'lib/resourceful/request.rb', line 15 def body @body end |
#header ⇒ Object
Returns the value of attribute header.
15 16 17 |
# File 'lib/resourceful/request.rb', line 15 def header @header end |
#method ⇒ Object
Returns the value of attribute method.
15 16 17 |
# File 'lib/resourceful/request.rb', line 15 def method @method end |
#request_time ⇒ Object (readonly)
Returns the value of attribute request_time.
16 17 18 |
# File 'lib/resourceful/request.rb', line 16 def request_time @request_time end |
#resource ⇒ Object
Returns the value of attribute resource.
15 16 17 |
# File 'lib/resourceful/request.rb', line 15 def resource @resource end |
Instance Method Details
#adapter ⇒ Object
230 231 232 |
# File 'lib/resourceful/request.rb', line 230 def adapter accessor.http_adapter end |
#add_credentials! ⇒ Object
Uses the auth manager to add any valid credentials to this request
43 44 45 |
# File 'lib/resourceful/request.rb', line 43 def add_credentials! @accessor.auth_manager.add_credentials(self) end |
#cacheable?(response) ⇒ Boolean
Is this request & response permitted to be stored in this (private) cache?
151 152 153 154 155 156 |
# File 'lib/resourceful/request.rb', line 151 def cacheable?(response) return false unless response.success? return false unless method.in? CACHEABLE_METHODS return false if header.cache_control && header.cache_control.include?('no-store') true end |
#cached_response ⇒ Object
The cached response
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/resourceful/request.rb', line 83 def cached_response return if skip_cache? return if @cached_response.nil? && @already_checked_cache @cached_response ||= begin @already_checked_cache = true resp = accessor.cache_manager.lookup(self) logger.info(" Retrieved from cache") if resp resp end end |
#fetch_response ⇒ Object
Performs all the work. Handles caching, redirects, auth retries, etc
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/resourceful/request.rb', line 48 def fetch_response if cached_response if needs_revalidation?(cached_response) logger.info(" Cache needs revalidation") set_validation_headers!(cached_response) else # We're done! return cached_response end end response = perform! response = revalidate_cached_response(response) if cached_response && response.not_modified? response = follow_redirect(response) if should_be_redirected?(response) response = retry_with_auth(response) if (response) raise UnsuccessfulHttpRequestError.new(self, response) if response.error? if cacheable?(response) store_in_cache(response) elsif invalidates_cache? invalidate_cache end return response end |
#follow_redirect(response) ⇒ Object
Follow a redirect response
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/resourceful/request.rb', line 102 def follow_redirect(response) raise MalformedServerResponse.new(self, response) unless response.header.location if response.moved_permanently? new_uri = response.header.location.first logger.info(" Permanently redirected to #{new_uri} - Storing new location.") resource.update_uri new_uri @header.host = resource.host response = fetch_response elsif response.see_other? # Always use GET for this redirect, regardless of initial method redirected_resource = Resourceful::Resource.new(self.accessor, response.header['Location'].first) response = Request.new(:get, redirected_resource, body, header).fetch_response else redirected_resource = Resourceful::Resource.new(self.accessor, response.header['Location'].first) logger.info(" Redirected to #{redirected_resource.uri} - Caching new location.") response = Request.new(method, redirected_resource, body, header).fetch_response end end |
#forces_revalidation? ⇒ Boolean
Does this request force us to revalidate the cache?
208 209 210 211 212 213 214 215 |
# File 'lib/resourceful/request.rb', line 208 def forces_revalidation? if max_age == 0 || skip_cache? logger.info(" Client forced revalidation") true else false end end |
#invalidate_cache ⇒ Object
Invalidated the cache for this uri (eg, after a POST)
146 147 148 |
# File 'lib/resourceful/request.rb', line 146 def invalidate_cache accessor.cache_manager.invalidate(resource.uri) end |
#invalidates_cache? ⇒ Boolean
Does this request invalidate the cache?
159 160 161 |
# File 'lib/resourceful/request.rb', line 159 def invalidates_cache? return true if method.in? INVALIDATING_METHODS end |
#logger ⇒ Object
226 227 228 |
# File 'lib/resourceful/request.rb', line 226 def logger resource.logger end |
#max_age ⇒ Object
Indicates the maxmimum response age in seconds we are willing to accept
Returns nil if we don’t care how old the response is
220 221 222 223 224 |
# File 'lib/resourceful/request.rb', line 220 def max_age if header['Cache-Control'] and header['Cache-Control'].include?('max-age') header['Cache-Control'].split(',').grep(/max-age/).first.split('=').last.to_i end end |
#needs_authorization?(response) ⇒ Boolean
Does this request need to be authorized? Will only be true if we haven’t already tried with auth
131 132 133 |
# File 'lib/resourceful/request.rb', line 131 def (response) !@already_tried_with_auth && response. end |
#needs_revalidation?(response) ⇒ Boolean
Do we need to revalidate our cache?
187 188 189 190 191 192 193 |
# File 'lib/resourceful/request.rb', line 187 def needs_revalidation?(response) return true if forces_revalidation? return true if response.stale? return true if max_age && response.current_age > max_age return true if response.must_be_revalidated? false end |
#perform! ⇒ Object
Perform the request, with no magic handling of anything.
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/resourceful/request.rb', line 164 def perform! @request_time = Time.now http_resp = adapter.make_request(@method, @resource.uri, @body, @header) @response = Resourceful::Response.new(uri, *http_resp) @response.request_time = @request_time @response. = true @response end |
#retry_with_auth(response) ⇒ Object
Add any auth headers from the response to the auth manager, and try the request again
121 122 123 124 125 126 127 128 |
# File 'lib/resourceful/request.rb', line 121 def retry_with_auth(response) @already_tried_with_auth = true logger.info("Authentication Required. Retrying with auth info") accessor.auth_manager.associate_auth_info(response) add_credentials! @body.rewind if @body # Its a stringIO, and we already fed it to the adapter once, so rewind it when we try again response = fetch_response end |
#revalidate_cached_response(not_modified_response) ⇒ Object
Revalidate the cached response with what we got from a 304 response
95 96 97 98 99 |
# File 'lib/resourceful/request.rb', line 95 def revalidate_cached_response(not_modified_response) logger.info(" Resource not modified") cached_response.revalidate!(not_modified_response) cached_response end |
#set_validation_headers!(response) ⇒ Object
Set the validation headers of a request based on the response in the cache
196 197 198 199 200 |
# File 'lib/resourceful/request.rb', line 196 def set_validation_headers!(response) @header['If-None-Match'] = response.header['ETag'] if response.header.has_key?('ETag') @header['If-Modified-Since'] = response.header['Last-Modified'] if response.header.has_key?('Last-Modified') @header['Cache-Control'] = 'max-age=0' if response.must_be_revalidated? end |
#should_be_redirected?(response) ⇒ Boolean
Is this a response a redirect, and are we permitted to follow it?
176 177 178 179 180 181 182 183 184 |
# File 'lib/resourceful/request.rb', line 176 def should_be_redirected?(response) return false unless response.redirect? if resource.on_redirect.nil? return true if method.in? REDIRECTABLE_METHODS false else resource.on_redirect.call(self, response) end end |
#skip_cache? ⇒ Boolean
Should we look for a response to this request in the cache?
77 78 79 80 |
# File 'lib/resourceful/request.rb', line 77 def skip_cache? return true unless method.in? CACHEABLE_METHODS header.cache_control && header.cache_control.include?('no-cache') end |
#store_in_cache(response) ⇒ Object
Store the response to this request in the cache
136 137 138 139 140 141 142 143 |
# File 'lib/resourceful/request.rb', line 136 def store_in_cache(response) # RFC2618 - 14.18 : A received message that does not have a Date header # field MUST be assigned one by the recipient if the message will be cached # by that recipient. response.header.date ||= response.response_time.httpdate accessor.cache_manager.store(self, response) end |
#uri ⇒ String
Returns The URI against which this request will be, or was, made.
203 204 205 |
# File 'lib/resourceful/request.rb', line 203 def uri resource.uri end |