Forked from crohr/Easy client-caching with RestClient and Rack-Cache.rb
Created
February 22, 2009 21:59
-
-
Save bmizerany/68629 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Author: Cyril Rohr | |
require 'rubygems' | |
require 'rest_client' # sudo gem install rest-client | |
require 'rack/cache' # sudo gem install rack-cache | |
module RestClient | |
# this is a quick hack to show how you can use rack-cache as a powerful client cache. | |
class CacheableResource < Resource | |
attr_reader :cache | |
CACHE_DEFAULT_OPTIONS = {}.freeze | |
def initialize(*args) | |
super(*args) | |
# rack-cache creates a singleton, so that there is only one instance of the cache at any time | |
@cache = Rack::Cache.new(self, options[:cache] || CACHE_DEFAULT_OPTIONS) | |
end | |
def get(additional_headers = {}, pass_through_cache = true) | |
if pass_through_cache && cache | |
uri = URI.parse(url) | |
uri_path_split = uri.path.split("/") | |
path_info = (last_part = uri_path_split.pop) ? "/"+last_part : "" | |
script_name = uri_path_split.join("/") | |
env = { | |
"REQUEST_METHOD" => 'GET', | |
"SCRIPT_NAME" => script_name, | |
"PATH_INFO" => path_info, | |
"QUERY_STRING" => uri.query, | |
"SERVER_NAME" => uri.host, | |
"SERVER_PORT" => uri.port | |
} | |
debeautify_headers(additional_headers).each do |key, value| | |
env.merge!("HTTP_"+key.to_s.upcase => value) | |
end | |
cache.call(env) | |
else | |
super(additional_headers) | |
end | |
end | |
def debeautify_headers(headers = {}) | |
headers.inject({}) do |out, (key, value)| | |
out[key.to_s.gsub(/_/, '-')] = value#.first | |
out | |
end | |
end | |
def call(env) | |
http_headers = env.inject({}) do |out, (header, value)| | |
if header =~ /HTTP_/ | |
out[header.gsub("HTTP_", '')] = value unless value.nil? || value.empty? | |
end | |
out | |
end | |
response = get(debeautify_headers(http_headers), pass_through_cache=false) | |
response.headers.delete(:x_content_digest) # don't know why, but it seems to make the validation fail if kept... | |
[response.code, debeautify_headers( response.headers ), response.to_s] | |
rescue RestClient::NotModified | |
# Unfortunately, RestClient does not return the Net::HTTP response in the exception... | |
[304, {}, ""] | |
end | |
end | |
end | |
RestClient.log = "stdout" | |
# will store the cached data in files | |
# cache_options = {:verbose => true, :metastore => 'file:/tmp/cache/meta', :entitystore => 'file:/tmp/cache/body'} | |
# will store the cached data in heap (all data are lost at the end of the script) | |
cache_options = {} | |
resource = RestClient::CacheableResource.new('http://some/cacheable/resource', :cache => cache_options) | |
begin | |
10.times do | |
resource['/'].get(:accept => 'application/json') | |
sleep 1 | |
end | |
rescue RestClient::ResourceNotFound | |
puts 'Resource not found.' | |
rescue RestClient::RequestTimeout | |
puts 'Timeout.' | |
rescue RestClient::Unauthorized | |
puts 'Unauthorized.' | |
rescue RestClient::RequestFailed | |
puts 'Request failed.' | |
rescue RestClient::ServerBrokeConnection | |
puts 'Connection broken.' | |
rescue Exception => e | |
puts e.message | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment