module Projector::Transport::HTTP
Persistent HTTP
API transport adapter.
Constants
- ERROR_MAP
Status code to exception map.
- MAX_REDIRECTS
Maximum URI redrects to follow before failing.
Private Instance Methods
Returns true if the request is not an error or redirect @return [Boolean]
# File lib/projector/transport/http.rb, line 183 def boolean_from_response(*args) response = request(*args) (200..299).include? response.code.to_i end
Constructs a request object based off the method @param [Symbol] method the HTTP
method @param [String] uri the HTTP
URI to request
# File lib/projector/transport/http.rb, line 115 def build_request(method, uri) case method when :get Net::HTTP::Get.new(uri.request_uri) when :post Net::HTTP::Post.new(uri.request_uri) when :put Net::HTTP::Put.new(uri.request_uri) when :delete Net::HTTP::Delete.new(uri.request_uri) when :patch Net::HTTP::Patch.new(uri.request_uri) end end
Returns true if the HTTP
method can post data @return [Boolean]
# File lib/projector/transport/http.rb, line 190 def can_post_data?(method) [:post, :put, :patch].include?(method) end
Raises the appropriate error based on the {ERROR_MAP} raise [Projector::Error]
# File lib/projector/transport/http.rb, line 157 def handle_error(request, response) return unless error = ERROR_MAP[response.code.to_i] message = nil begin message = JSON.parse(response.body) || request.path rescue JSON::ParserError end # Raise error err = error.new(message) err.retry_after = response['retry-after'].to_i if response.code.to_i >= 500 err.request = request err.response = response err.response_body = message err.request_id = request['request-id'] raise err end
Returns an instance of the HTTP
client @return [Net::HTTP::Persistent]
# File lib/projector/transport/http.rb, line 103 def http @http ||= begin http = Net::HTTP::Persistent.new('projector') http.open_timeout = 5 http.read_timeout = 2 http end end
Makes a request and parses the result as a JSON object @return [Response]
# File lib/projector/transport/http.rb, line 176 def json_request(*args) # Perform request, pass result format Response.new(request(*args)) end
Logs all HTTP
request data to STDOUT if the PROJECTOR_DEBUG_HTTP env variable is set
# File lib/projector/transport/http.rb, line 195 def log_debug_data(*args) return unless ENV['PROJECTOR_DEBUG_HTTP'] @logger ||= begin require 'logger' Logger.new(STDOUT) end @logger.info(args.reject{|s| s = s.to_s; s.nil? || s.empty?}.join(' - ')) end
Escapes params to a URI-safe form
# File lib/projector/transport/http.rb, line 142 def param_for(key, value, parent = nil) if value.is_a?(Hash) params = [] value.each_pair do |value_key, value_value| value_parent = parent ? parent + "[#{key}]" : key.to_s params << param_for(value_key, value_value, value_parent) end params else ["#{parent ? parent + "[#{key}]" : key.to_s}=#{CGI::escape(value.to_s)}"] end end
Makes an HTTP
Request
@param [String] method The HTTP
method to use @param [String] host the host to connect to @param [String] path the path to request @param [Hash] params (nil) the parameters to send @param [Integer] redirect_count (0) the number of redirects that have been followed so far
# File lib/projector/transport/http.rb, line 44 def request(method, host, path, params = nil, redirect_count = 0) uri = URI.parse("#{host}#{path}") # if the request requires parameters in the query string, merge them in if params && !can_post_data?(method) query_values = uri.query ? URI.decode_www_form(uri.query).inject({}) {|h,(k,v)| h[k]=v; h} : {} uri.query = to_url_params((query_values || {}).merge(params)) end # Build request request = build_request(method, uri) # Add headers request['Authorization'] = "Token #{self.token}" request['Content-Type'] = 'application/json' request['Accept'] = "application/vnd.projector+json; version=#{Projector::API_VERSION}" request['User-Agent'] = "ProjectorRubySdk/#{Projector::VERSION}" request['Request-Id'] = SecureRandom.uuid # Add params as JSON if they exist request.body = JSON.generate(params) if can_post_data?(method) && params log_debug_data(uri, request.method, request.body) # Request response = http.request(uri, request) # Log debug data if needed log_debug_data(uri, response.code, response.body) # If we've been given a redirect if [301, 302].include?(response.code.to_i) # Make sure we aren't in a giant redirect loop if redirect_count >= MAX_REDIRECTS err = Projector::Error::TooManyRedirects.new err.request = request err.response = response err.redirect_count = redirect_count raise err end # Parse the new location uri = URI.parse(response['Location']) # Make the call to the redirected location, incrementing the redirect count by 1 return request(method, uri.select(:scheme, :host).join("://"), uri.path, params, redirect_count + 1) # Return the result of the redirected request end # Check for errors handle_error(request, response) # Return the raw response object response end
Converts a hash to HTTP
URI format @param [Hash] hash the hash to be converted @return [String]
# File lib/projector/transport/http.rb, line 133 def to_url_params(hash) params = [] hash.each_pair do |key, value| params << param_for(key, value).flatten end params.sort.join('&') end