Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save bmizerany/68629 to your computer and use it in GitHub Desktop.
Save bmizerany/68629 to your computer and use it in GitHub Desktop.
# 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