require "social_avatar_proxy/config" require "rack" module SocialAvatarProxy class Response < Rack::Response def self.build(options = {}) # build the response response = ResponseBuilder.new(options).response # apply the HTTP caching to the response SocialAvatarProxy::Config.http_cache.apply_caching_headers(response) end end class ResponseBuilder attr_reader :service, :identifier def initialize(options) @service = options.fetch(:service) @identifier = options.fetch(:identifier) end def response return @response if defined?(@response) if file @response = Response.new do |response| write_file(response) set_file_headers(response) end else @response = Rack::Response.new("Not Found", 404) end end def set_file_headers(response) # set the modified time if file.respond_to?(:mtime) && file.mtime response["Last-Modified"] = file.mtime.httpdate end # set the content type if file.respond_to?(:content_type) && file.content_type response["Content-Type"] = file.content_type end end def write_file(response) # configure the file delivery case Config.delivery_method when :x_accel_redirect # set the NGINX header response["X-Accel-Redirect"] = file.path when :x_send_file # set the Apache header response["X-Sendfile"] = file.path else begin # read the file contents data = file.read # write it to the response response.write(data) ensure # close the file file.close end end end def file @file ||= SocialAvatarProxy::Config.caches.fetch({ service: service, identifier: identifier }) do remote_avatar_file || default_image end end private def default_image SocialAvatarProxy::Config.default_image end def remote_avatar_file # titleize the service name service_name = service.gsub(/[\_\-]/, " ").gsub(/\b([a-z])/) do |match| match.upcase end # pass it onto the service, and retrieve the file SocialAvatarProxy.const_get("#{service_name}Avatar").new(identifier).file end end end