lib/thebigdb/request.rb in thebigdb-1.1.0 vs lib/thebigdb/request.rb in thebigdb-1.2.0

- old
+ new

@@ -1,7 +1,9 @@ module TheBigDB class Request + class ApiStatusError < StandardError; end + attr_reader :http, :http_request, :http_response, :data_sent, :data_received, :response # Prepares the basic @http object with the current values of the module (host, port, ...) def initialize @http = Net::HTTP.new(TheBigDB.api_host, TheBigDB.api_port) @@ -22,15 +24,15 @@ # we add the API version to the URL, with a trailing slash and the rest of the request request_uri = "/v#{TheBigDB.api_version}" + (request_uri.start_with?("/") ? request_uri : "/#{request_uri}") if method == "get" - encoded_params = TheBigDB::Request::serialize_query_params(params) + encoded_params = TheBigDB::Helpers::serialize_query_params(params) @http_request = Net::HTTP::Get.new(request_uri + "?" + encoded_params) elsif method == "post" @http_request = Net::HTTP::Post.new(request_uri) - @http_request.set_form_data(TheBigDB::Request::flatten_params_keys(params)) + @http_request.set_form_data(TheBigDB::Helpers::flatten_params_keys(params)) else raise ArgumentError, "The request method must be 'get' or 'post'" end @http_request["user-agent"] = "TheBigDB RubyWrapper/#{TheBigDB::VERSION::STRING}" @@ -48,32 +50,18 @@ end # Actually makes the request prepared in @http_request, and sets @http_response def execute # Here is the order of operations: + # -> setting @data_sent # -> executing before_request_execution callback # -> executing the HTTP request # -> setting @response - # -> setting @data_sent # -> setting @data_received # -> executing after_request_execution callback - # Executing callback - TheBigDB.before_request_execution.call(self) - - # Here is where the request is actually executed - @http_response = @http.request(@http_request) - - # Setting @response - begin - # We parse the JSON answer and return it. - @response = JSON(@http_response.body) - rescue JSON::ParserError => e - @response = {"error" => {"code" => "0000", "description" => "The server gave an invalid JSON body:\n#{@http_response.body}"}} - end - - # Setting @data_sent and @data_received + # Setting @data_sent params = Rack::Utils.parse_nested_query(URI.parse(@http_request.path).query) # Since that's how it will be interpreted anyway on the server, we merge the POST params to the GET params, # but it's not supposed to happen: either every params is prepared for GET/query params, or as POST body params.merge!(Rack::Utils.parse_nested_query(@http_request.body.to_s)) @@ -90,56 +78,38 @@ "path" => URI.parse(@http_request.path).path, "method" => @http_request.method, "params" => params } + # Executing callback + TheBigDB.before_request_execution.call(self) + + # Here is where the request is actually executed + @http_response = @http.request(@http_request) + + # Setting @response + begin + # We parse the JSON answer and return it. + @response = JSON(@http_response.body) + rescue JSON::ParserError => e + @response = {"status" => "error", "error" => {"code" => "0000", "description" => "The server gave an invalid JSON body:\n#{@http_response.body}"}} + end + + # Setting @data_received @data_received = { "headers" => Hash[@http_response.to_hash.map{|k,v| [k, v.join] }], "content" => @response } + # Executing callback TheBigDB.after_request_execution.call(self) - self - end - - ############## - ## Engine Helpers - ############## - - # serialize_query_params({house: "bricks", animals: ["cat", "dog"], computers: {cool: true, drives: ["hard", "flash"]}}) - # => house=bricks&animals%5B%5D=cat&animals%5B%5D=dog&computers%5Bcool%5D=true&computers%5Bdrives%5D%5B%5D=hard&computers%5Bdrives%5D%5B%5D=flash - # which will be read by the server as: - # => house=bricks&animals[]=cat&animals[]=dog&computers[cool]=true&computers[drives][]=hard&computers[drives][]=flash - def self.serialize_query_params(params, prefix = nil) - ret = [] - params.each_pair do |key, value| - param_key = prefix ? "#{prefix}[#{key}]" : key - - if value.is_a?(Hash) - ret << self.serialize_query_params(value, param_key.to_s) - elsif value.is_a?(Array) - sub_hash = {} - value.each_with_index do |value_item, i| - sub_hash[i.to_s] = value_item - end - ret << self.serialize_query_params(sub_hash, param_key.to_s) - else - ret << URI.encode_www_form_component(param_key.to_s) + "=" + URI.encode_www_form_component(value.to_s) - end + # Raising exception if asked + if TheBigDB.raise_on_api_status_error and @response["status"] == "error" + raise ApiStatusError.new(@response["error"]["code"]) end - ret.join("&") - end - # flatten_params_keys({house: "bricks", animals: ["cat", "dog"], computers: {cool: true, drives: ["hard", "flash"]}}) - # => {"house" => "bricks", "animals[0]" => "cat", "animals[1]" => "dog", "computers[cool]" => "true", "computers[drives][0]" => "hard", "computers[drives][1]" => "flash"} - def self.flatten_params_keys(params) - serialized_params = self.serialize_query_params(params) - new_params = {} - serialized_params.split("&").each do |assign| - key, value = assign.split("=") - new_params[URI.decode(key)] = URI.decode(value) - end - new_params + self end + end end \ No newline at end of file