Class: TheBigDB::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/thebigdb/request.rb

Defined Under Namespace

Classes: ApiStatusError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeRequest

Prepares the basic @http object with the current values of the module (host, port, …)



8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/thebigdb/request.rb', line 8

def initialize
  @http = Net::HTTP.new(TheBigDB.api_host, TheBigDB.api_port)

  if TheBigDB.use_ssl
    @http.use_ssl = true
    if TheBigDB.verify_ssl_certificates
      raise NotImplementedError
    else
      @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    end
  end
end

Instance Attribute Details

#data_receivedObject (readonly)

Returns the value of attribute data_received.



5
6
7
# File 'lib/thebigdb/request.rb', line 5

def data_received
  @data_received
end

#data_sentObject (readonly)

Returns the value of attribute data_sent.



5
6
7
# File 'lib/thebigdb/request.rb', line 5

def data_sent
  @data_sent
end

#httpObject (readonly)

Returns the value of attribute http.



5
6
7
# File 'lib/thebigdb/request.rb', line 5

def http
  @http
end

#http_requestObject (readonly)

Returns the value of attribute http_request.



5
6
7
# File 'lib/thebigdb/request.rb', line 5

def http_request
  @http_request
end

#http_responseObject (readonly)

Returns the value of attribute http_response.



5
6
7
# File 'lib/thebigdb/request.rb', line 5

def http_response
  @http_response
end

#responseObject (readonly)

Returns the value of attribute response.



5
6
7
# File 'lib/thebigdb/request.rb', line 5

def response
  @response
end

Instance Method Details

#executeObject

Actually makes the request prepared in @http_request, and sets @http_response



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/thebigdb/request.rb', line 57

def execute
  # Here is the order of operations:
  # -> setting @data_sent
  # -> executing before_request_execution callback
  # -> executing the HTTP request
  # -> setting @response
  # -> setting @data_received
  # -> executing after_request_execution callback

  # 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))

  # About: Hash[{}.map{|k,v| [k, v.join] }]
  # it transforms the following hash:
  # {"accept"=>["*/*"], "user-agent"=>["TheBigDB RubyWrapper/X.Y.Z"], "host"=>["computer.host"]}
  # into the following hash:
  # {"accept"=>"*/*", "user-agent"=>"TheBigDB RubyWrapper/X.Y.Z", "host"=>"computer.host"}
  # which is way more useful and cleaner.
  @data_sent = {
    "headers" => Hash[@http_request.to_hash.map{|k,v| [k, v.join] }],
    "host" => @http.address,
    "port" => @http.port,
    "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 = TheBigDB.http_request_executor.call(@http, @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)

  # Raising exception if asked
  if TheBigDB.raise_on_api_status_error and @response["status"] == "error"
    raise ApiStatusError.new(@response["error"]["code"])
  end

  self
end

#prepare(method, request_uri, params = {}) ⇒ Object

Prepares the @http_request object with the actual content of the request



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/thebigdb/request.rb', line 22

def prepare(method, request_uri, params = {})
  method = method.downcase.to_s

  if TheBigDB.api_key.is_a?(String) and !TheBigDB.api_key.empty?
    params.merge!("api_key" => TheBigDB.api_key)
  end

  # 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::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::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}"

  client_user_agent = {
    "publisher" => "thebigdb",
    "version" => TheBigDB::VERSION::STRING,
    "language" => "ruby",
    "language_version" => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
  }

  @http_request["X-TheBigDB-Client-User-Agent"] = JSON(client_user_agent)

  self
end