spark_api 1.4.24 → 1.4.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/VERSION +1 -1
- data/lib/spark_api/configuration.rb +3 -1
- data/lib/spark_api/connection.rb +19 -6
- data/lib/spark_api/errors.rb +2 -1
- data/lib/spark_api/faraday_middleware.rb +3 -1
- data/lib/spark_api/request.rb +1 -1
- data/lib/spark_api/response.rb +21 -11
- data/spec/unit/spark_api/configuration_spec.rb +32 -1
- data/spec/unit/spark_api/request_spec.rb +13 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YWRmNWJhNzE4N2I3MTU1Y2M5MjFlYWFmMGVkMjlhNjg1MTY2NTgyOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MWViOWU1YjgzODg2NjgzZWQyOWI2MTcxZThkY2YxNWVhYmY1NTc5MA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Y2VlNjczMDNmMjQ2NGUwYmY0ZGNmMjFhOTRiZDg4OTJmYzAzYTgyZmE3ZTcz
|
10
|
+
Mzc4NzZjYTI2MzBmMjAwOGI2MTIzZmI1MTU4MzVjOGRhMTYyY2NhYTc2YjEy
|
11
|
+
NWUzZTNlYzRhMmFlZDhiM2M3NmFhNGVmZTM5ODdiMzcxMGE3NWY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MWQxOWQ0ODM3MTcyMjJkZTBlNTI1MmYyZWVjYzdhNzE2MzQzODNiOGEyZjVk
|
14
|
+
ZGZlNzUwNzg4Y2EyN2EyNTAyM2VmOTNiZjVmZjg0MjRjNDk1Y2YwYTAxZWVm
|
15
|
+
MzgwOTljMDVhZWI0MTE2YmNiMzIzYzBkYzJlNzFlZDRiYmYwY2Q=
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.4.
|
1
|
+
1.4.25
|
@@ -11,7 +11,7 @@ module SparkApi
|
|
11
11
|
# valid configuration options
|
12
12
|
VALID_OPTION_KEYS = [:api_key, :api_secret, :api_user, :endpoint,
|
13
13
|
:user_agent, :version, :ssl, :ssl_verify, :oauth2_provider, :authentication_mode,
|
14
|
-
:auth_endpoint, :callback, :compress, :timeout, :middleware].freeze
|
14
|
+
:auth_endpoint, :callback, :compress, :timeout, :middleware, :request_id_chain].freeze
|
15
15
|
OAUTH2_KEYS = [:authorization_uri, :access_uri, :client_id, :client_secret,
|
16
16
|
# Requirements for authorization_code grant type
|
17
17
|
:redirect_uri,
|
@@ -44,6 +44,7 @@ module SparkApi
|
|
44
44
|
DEFAULT_COMPRESS = false
|
45
45
|
DEFAULT_TIMEOUT = 5 # seconds
|
46
46
|
DEFAULT_MIDDLEWARE = 'spark_api'
|
47
|
+
DEFAULT_REQUEST_ID_CHAIN = nil
|
47
48
|
|
48
49
|
X_SPARK_API_USER_AGENT = "X-SparkApi-User-Agent"
|
49
50
|
|
@@ -78,6 +79,7 @@ module SparkApi
|
|
78
79
|
self.compress = DEFAULT_COMPRESS
|
79
80
|
self.timeout = DEFAULT_TIMEOUT
|
80
81
|
self.middleware = DEFAULT_MIDDLEWARE
|
82
|
+
self.request_id_chain = DEFAULT_REQUEST_ID_CHAIN
|
81
83
|
self
|
82
84
|
end
|
83
85
|
end
|
data/lib/spark_api/connection.rb
CHANGED
@@ -5,6 +5,15 @@ module SparkApi
|
|
5
5
|
# =Connection
|
6
6
|
# Mixin module for handling http connection information
|
7
7
|
module Connection
|
8
|
+
REG_HTTP = /^http:/
|
9
|
+
REG_HTTPS = /^https:/
|
10
|
+
HTTP_SCHEME = 'http:'
|
11
|
+
HTTPS_SCHEME = 'https:'
|
12
|
+
ACCEPT_ENCODING = 'Accept-Encoding'
|
13
|
+
COMPRESS_ACCEPT_ENCODING = 'gzip, deflate'
|
14
|
+
X_REQUEST_ID_CHAIN = 'X-Request-Id-Chain'
|
15
|
+
MIME_JSON = 'application/json'
|
16
|
+
MIME_RESO = 'application/json, application/xml'
|
8
17
|
# Main connection object for running requests. Bootstraps the Faraday abstraction layer with
|
9
18
|
# our client configuration.
|
10
19
|
def connection(force_ssl = false)
|
@@ -13,13 +22,17 @@ module SparkApi
|
|
13
22
|
}
|
14
23
|
if(force_ssl || self.ssl)
|
15
24
|
opts[:ssl] = {:verify => false } unless self.ssl_verify
|
16
|
-
opts[:url] = @endpoint.sub
|
25
|
+
opts[:url] = @endpoint.sub REG_HTTP, HTTPS_SCHEME
|
17
26
|
else
|
18
|
-
opts[:url] = @endpoint.sub
|
27
|
+
opts[:url] = @endpoint.sub REG_HTTPS, HTTP_SCHEME
|
19
28
|
end
|
20
29
|
|
21
30
|
if self.compress
|
22
|
-
opts[:headers][
|
31
|
+
opts[:headers][ACCEPT_ENCODING] = COMPRESS_ACCEPT_ENCODING
|
32
|
+
end
|
33
|
+
|
34
|
+
if request_id_chain
|
35
|
+
opts[:headers][X_REQUEST_ID_CHAIN] = request_id_chain
|
23
36
|
end
|
24
37
|
|
25
38
|
conn = Faraday.new(opts) do |conn|
|
@@ -42,8 +55,8 @@ module SparkApi
|
|
42
55
|
|
43
56
|
def spark_headers
|
44
57
|
{
|
45
|
-
:accept =>
|
46
|
-
:content_type =>
|
58
|
+
:accept => MIME_JSON,
|
59
|
+
:content_type => MIME_JSON,
|
47
60
|
:user_agent => Configuration::DEFAULT_USER_AGENT,
|
48
61
|
Configuration::X_SPARK_API_USER_AGENT => user_agent
|
49
62
|
}
|
@@ -51,7 +64,7 @@ module SparkApi
|
|
51
64
|
|
52
65
|
def reso_headers
|
53
66
|
{
|
54
|
-
:accept =>
|
67
|
+
:accept => MIME_RESO,
|
55
68
|
:user_agent => Configuration::DEFAULT_USER_AGENT,
|
56
69
|
Configuration::X_SPARK_API_USER_AGENT => user_agent
|
57
70
|
}
|
data/lib/spark_api/errors.rb
CHANGED
@@ -21,7 +21,7 @@ module SparkApi
|
|
21
21
|
# Errors built from API responses
|
22
22
|
class InvalidResponse < StandardError; end
|
23
23
|
class ClientError < StandardError
|
24
|
-
attr_reader :code, :status, :details, :request_path, :errors
|
24
|
+
attr_reader :code, :status, :details, :request_path, :request_id, :errors
|
25
25
|
def initialize (options = {})
|
26
26
|
# Support the standard initializer for errors
|
27
27
|
opts = options.is_a?(Hash) ? options : {:message => options.to_s}
|
@@ -29,6 +29,7 @@ module SparkApi
|
|
29
29
|
@status = opts[:status]
|
30
30
|
@details = opts[:details]
|
31
31
|
@request_path = opts[:request_path]
|
32
|
+
@request_id = opts[:request_id]
|
32
33
|
@errors = opts[:errors]
|
33
34
|
super(opts[:message])
|
34
35
|
end
|
@@ -22,7 +22,8 @@ module SparkApi
|
|
22
22
|
unless body.is_a?(Hash) && body.key?("D")
|
23
23
|
raise InvalidResponse, "The server response could not be understood"
|
24
24
|
end
|
25
|
-
|
25
|
+
request_id = env[:response_headers]['x-request-id']
|
26
|
+
response = ApiResponse.new body, request_id
|
26
27
|
paging = response.pagination
|
27
28
|
|
28
29
|
if paging.nil?
|
@@ -38,6 +39,7 @@ module SparkApi
|
|
38
39
|
|
39
40
|
error_hash = {
|
40
41
|
:request_path => env[:url],
|
42
|
+
:request_id => request_id,
|
41
43
|
:message => response.message,
|
42
44
|
:code => response.code,
|
43
45
|
:status => env[:status],
|
data/lib/spark_api/request.rb
CHANGED
@@ -79,7 +79,7 @@ module SparkApi
|
|
79
79
|
response = authenticator.request(method, request_path, post_data, request_opts)
|
80
80
|
end
|
81
81
|
request_time = Time.now - start_time
|
82
|
-
SparkApi.logger.debug { "[#{(request_time * 1000).to_i}ms] Api: #{method.to_s.upcase} #{request_path}" }
|
82
|
+
SparkApi.logger.debug { "[#{(request_time * 1000).to_i}ms] Api: #{method.to_s.upcase} #{request_path} request_id=#{response.headers['x-request-id']}" }
|
83
83
|
rescue PermissionDenied => e
|
84
84
|
if(ResponseCodes::SESSION_TOKEN_EXPIRED == e.code)
|
85
85
|
unless (attempts +=1) > 1
|
data/lib/spark_api/response.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module SparkApi
|
2
2
|
# API Response interface
|
3
3
|
module Response
|
4
|
-
ATTRIBUTES = [:code, :message, :results, :success, :pagination, :details, :d, :errors, :sparkql_errors]
|
4
|
+
ATTRIBUTES = [:code, :message, :results, :success, :pagination, :details, :d, :errors, :sparkql_errors, :request_id]
|
5
5
|
attr_accessor *ATTRIBUTES
|
6
6
|
def success?
|
7
7
|
@success
|
@@ -10,21 +10,31 @@ module SparkApi
|
|
10
10
|
|
11
11
|
# Nice and handy class wrapper for the api response hash
|
12
12
|
class ApiResponse < ::Array
|
13
|
+
MAGIC_D = 'D'
|
14
|
+
MESSAGE = 'Message'
|
15
|
+
CODE = 'Code'
|
16
|
+
RESULTS = 'Results'
|
17
|
+
SUCCESS = 'Success'
|
18
|
+
PAGINATION = 'Pagination'
|
19
|
+
DETAILS = 'Details'
|
20
|
+
ERRORS = 'Errors'
|
21
|
+
SPARKQL_ERRORS = 'SparkQLErrors'
|
13
22
|
include SparkApi::Response
|
14
|
-
def initialize
|
23
|
+
def initialize d, request_id=nil
|
15
24
|
begin
|
16
|
-
self.d = d[
|
25
|
+
self.d = d[MAGIC_D]
|
17
26
|
if self.d.nil? || self.d.empty?
|
18
27
|
raise InvalidResponse, "The server response could not be understood"
|
19
28
|
end
|
20
|
-
self.message = self.d[
|
21
|
-
self.code = self.d[
|
22
|
-
self.results = Array(self.d[
|
23
|
-
self.success = self.d[
|
24
|
-
self.pagination = self.d[
|
25
|
-
self.details = self.d[
|
26
|
-
self.errors = self.d[
|
27
|
-
self.sparkql_errors = self.d[
|
29
|
+
self.message = self.d[MESSAGE]
|
30
|
+
self.code = self.d[CODE]
|
31
|
+
self.results = Array(self.d[RESULTS])
|
32
|
+
self.success = self.d[SUCCESS]
|
33
|
+
self.pagination = self.d[PAGINATION]
|
34
|
+
self.details = self.d[DETAILS] || []
|
35
|
+
self.errors = self.d[ERRORS]
|
36
|
+
self.sparkql_errors = self.d[SPARKQL_ERRORS]
|
37
|
+
self.request_id = request_id
|
28
38
|
super(results)
|
29
39
|
rescue Exception => e
|
30
40
|
SparkApi.logger.error "Unable to understand the response! #{d}"
|
@@ -13,6 +13,7 @@ describe SparkApi::Client, "Client config" do
|
|
13
13
|
SparkApi.api_key = "my_api_key"
|
14
14
|
SparkApi.api_key.should match("my_api_key")
|
15
15
|
SparkApi.timeout.should eq(5)
|
16
|
+
SparkApi.request_id_chain.should be_nil
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -23,7 +24,8 @@ describe SparkApi::Client, "Client config" do
|
|
23
24
|
:api_user => "1234",
|
24
25
|
:auth_endpoint => "https://login.wade.dev.fbsdata.com",
|
25
26
|
:endpoint => "http://api.wade.dev.fbsdata.com",
|
26
|
-
:timeout => 15
|
27
|
+
:timeout => 15,
|
28
|
+
:request_id_chain => 'foobar')
|
27
29
|
|
28
30
|
client.api_key.should match("key_of_wade")
|
29
31
|
client.api_secret.should match("TopSecret")
|
@@ -32,6 +34,7 @@ describe SparkApi::Client, "Client config" do
|
|
32
34
|
client.endpoint.should match("http://api.wade.dev.fbsdata.com")
|
33
35
|
client.version.should match("v1")
|
34
36
|
client.timeout.should eq(15)
|
37
|
+
client.request_id_chain.should eq('foobar')
|
35
38
|
end
|
36
39
|
|
37
40
|
it "should allow unverified ssl certificates when verification is off" do
|
@@ -126,11 +129,14 @@ describe SparkApi::Client, "Client config" do
|
|
126
129
|
config.version = "veleventy"
|
127
130
|
config.endpoint = "test.api.sparkapi.com"
|
128
131
|
config.user_agent = "my useragent"
|
132
|
+
config.request_id_chain = 'foobar'
|
129
133
|
end
|
130
134
|
|
131
135
|
SparkApi.api_key.should match("my_key")
|
136
|
+
SparkApi.request_id_chain.should eq("foobar")
|
132
137
|
SparkApi.reset
|
133
138
|
SparkApi.api_key.should == SparkApi::Configuration::DEFAULT_API_KEY
|
139
|
+
SparkApi.request_id_chain.should SparkApi::Configuration::DEFAULT_REQUEST_ID_CHAIN
|
134
140
|
|
135
141
|
end
|
136
142
|
end
|
@@ -184,6 +190,31 @@ describe SparkApi::Client, "Client config" do
|
|
184
190
|
})
|
185
191
|
end
|
186
192
|
|
193
|
+
it "should pass along the request_id_chain header if set" do
|
194
|
+
reset_config
|
195
|
+
stub_auth_request
|
196
|
+
stub_request(:get, "#{SparkApi.endpoint}/#{SparkApi.version}/headers").
|
197
|
+
with(:query => {
|
198
|
+
:ApiUser => "foobar",
|
199
|
+
:ApiSig => "717a066c4f4302c5ca9507e484db4812",
|
200
|
+
:AuthToken => "c401736bf3d3f754f07c04e460e09573"
|
201
|
+
}).
|
202
|
+
to_return(:body => '{"D":{"Success": true,"Results": []}}')
|
203
|
+
SparkApi.configure do |config|
|
204
|
+
config.user_agent = "my useragent"
|
205
|
+
config.request_id_chain = 'foobar'
|
206
|
+
end
|
207
|
+
SparkApi.client.get '/headers'
|
208
|
+
WebMock.should have_requested(:get, "#{SparkApi.endpoint}/#{SparkApi.version}/headers?ApiUser=foobar&ApiSig=717a066c4f4302c5ca9507e484db4812&AuthToken=c401736bf3d3f754f07c04e460e09573").
|
209
|
+
with(:headers => {
|
210
|
+
'User-Agent' => SparkApi::Configuration::DEFAULT_USER_AGENT,
|
211
|
+
SparkApi::Configuration::X_SPARK_API_USER_AGENT => "my useragent",
|
212
|
+
'Accept'=>'application/json',
|
213
|
+
'Content-Type'=>'application/json',
|
214
|
+
'X-Request-Id-Chain' => 'foobar'
|
215
|
+
})
|
216
|
+
end
|
217
|
+
|
187
218
|
it "should not set gzip header by default" do
|
188
219
|
c = SparkApi::Client.new(:endpoint => "https://sparkapi.com")
|
189
220
|
c.connection.headers["Accept-Encoding"].should be_nil
|
@@ -2,7 +2,7 @@ require './spec/spec_helper'
|
|
2
2
|
|
3
3
|
describe SparkApi do
|
4
4
|
describe SparkApi::ClientError do
|
5
|
-
subject { SparkApi::ClientError.new({:message=>"OMG FAIL", :code=>1234, :status=>500, :request_path => '/v1/foo'}) }
|
5
|
+
subject { SparkApi::ClientError.new({:message=>"OMG FAIL", :code=>1234, :status=>500, :request_path => '/v1/foo', :request_id => 'deadbeef'}) }
|
6
6
|
it "should print a helpful to_s" do
|
7
7
|
subject.to_s.should == "OMG FAIL"
|
8
8
|
subject.message.should == "OMG FAIL"
|
@@ -18,6 +18,10 @@ describe SparkApi do
|
|
18
18
|
subject.request_path.should == '/v1/foo'
|
19
19
|
end
|
20
20
|
|
21
|
+
it "should have a request_id" do
|
22
|
+
subject.request_id.should == 'deadbeef'
|
23
|
+
end
|
24
|
+
|
21
25
|
it "should raise and exception with attached message" do
|
22
26
|
expect { raise subject.class, {:message=>"My Message", :code=>1000, :status=>404}}.to raise_error(SparkApi::ClientError) do |e|
|
23
27
|
e.message.should == "My Message"
|
@@ -38,6 +42,7 @@ describe SparkApi do
|
|
38
42
|
e.message.should == "My Message"
|
39
43
|
e.code.should be == nil
|
40
44
|
e.status.should be == nil
|
45
|
+
e.request_id.should be == nil
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
@@ -51,6 +56,13 @@ describe SparkApi do
|
|
51
56
|
r = SparkApi::ApiResponse.new({"D"=>{"Success" => true, "Results" => []}})
|
52
57
|
r.success?.should be(true)
|
53
58
|
r.results.empty?.should be(true)
|
59
|
+
r.request_id.should eq nil
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return the request_id" do
|
63
|
+
r = SparkApi::ApiResponse.new({"D"=>{"Success" => true, "Results" => []}}, 'foobar')
|
64
|
+
r.success?.should be(true)
|
65
|
+
r.request_id.should eq('foobar')
|
54
66
|
end
|
55
67
|
it "should have a message on error" do
|
56
68
|
r = SparkApi::ApiResponse.new({"D"=>{"Success" => false, "Message" => "I am a failure."}})
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spark_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.25
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Hornseth
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-06-
|
12
|
+
date: 2018-06-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|