api_client 0.5.24-java → 0.5.25-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/api_client/base.rb +77 -0
- data/lib/api_client/connection/abstract.rb +81 -0
- data/lib/api_client/connection/basic.rb +129 -0
- data/lib/api_client/connection/json.rb +14 -0
- data/lib/api_client/connection/middlewares/request/json.rb +34 -0
- data/lib/api_client/connection/middlewares/request/logger.rb +64 -0
- data/lib/api_client/connection/middlewares/request/oauth.rb +22 -0
- data/lib/api_client/connection/oauth.rb +18 -0
- data/lib/api_client/errors.rb +31 -0
- data/lib/api_client/mixins/configuration.rb +24 -0
- data/lib/api_client/mixins/connection_hooks.rb +24 -0
- data/lib/api_client/mixins/delegation.rb +23 -0
- data/lib/api_client/mixins/inheritance.rb +19 -0
- data/lib/api_client/mixins/instantiation.rb +29 -0
- data/lib/api_client/mixins/scoping.rb +49 -0
- data/lib/api_client/resource/base.rb +67 -0
- data/lib/api_client/resource/name_resolver.rb +37 -0
- data/lib/api_client/resource/scope.rb +73 -0
- data/lib/api_client/scope.rb +125 -0
- data/lib/api_client/utils.rb +18 -0
- data/lib/api_client/version.rb +3 -0
- data/spec/api_client/base/connection_hook_spec.rb +18 -0
- data/spec/api_client/base/delegation_spec.rb +15 -0
- data/spec/api_client/base/inheritance_spec.rb +44 -0
- data/spec/api_client/base/instantiation_spec.rb +55 -0
- data/spec/api_client/base/marshalling_spec.rb +33 -0
- data/spec/api_client/base/parsing_spec.rb +38 -0
- data/spec/api_client/base/scoping_spec.rb +60 -0
- data/spec/api_client/base_spec.rb +107 -0
- data/spec/api_client/connection/abstract_spec.rb +21 -0
- data/spec/api_client/connection/basic_spec.rb +191 -0
- data/spec/api_client/connection/oauth_spec.rb +27 -0
- data/spec/api_client/connection/request/json_spec.rb +30 -0
- data/spec/api_client/connection/request/logger_spec.rb +18 -0
- data/spec/api_client/connection/request/oauth_spec.rb +26 -0
- data/spec/api_client/resource/base_spec.rb +97 -0
- data/spec/api_client/resource/name_spec.rb +19 -0
- data/spec/api_client/resource/scope_spec.rb +122 -0
- data/spec/api_client/scope_spec.rb +204 -0
- data/spec/api_client/utils_spec.rb +32 -0
- data/spec/support/matchers.rb +5 -0
- metadata +62 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6aee99219c58bf02f29e11548ea72dd56ad18fba534f326626147053148f81b
|
4
|
+
data.tar.gz: 767a054b03b9ea36501f7dbdd71bc898d65d5db26b09962dbb1d4e4283c60203
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae82881334deac2a7d458e4618d6c7502580e4a070202e04836b8166603a42bba48d6abe047efda1eaff153f540993c1ccb0109a275eebffcf35e38a01985abb
|
7
|
+
data.tar.gz: 78193bbf66f1e8c8d961f83b39ed86a23348cca2c56c235e1f896ae8b19ec676aaa0f678602c00b5a239e4c0555814d7b1b3a6b9432a3d3bc3414dda1d5ad834
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
module ApiClient
|
2
|
+
|
3
|
+
class Base < Hashie::Mash
|
4
|
+
|
5
|
+
extend ApiClient::Mixins::Inheritance
|
6
|
+
extend ApiClient::Mixins::Instantiation
|
7
|
+
extend ApiClient::Mixins::Scoping
|
8
|
+
extend ApiClient::Mixins::ConnectionHooks
|
9
|
+
|
10
|
+
class << self
|
11
|
+
extend ApiClient::Mixins::Delegation
|
12
|
+
extend ApiClient::Mixins::Configuration
|
13
|
+
|
14
|
+
delegate :fetch, :get, :put, :post, :patch, :delete, :headers, :endpoint, :options, :adapter, :params, :raw, :to => :scope
|
15
|
+
|
16
|
+
dsl_accessor :format, :namespace
|
17
|
+
|
18
|
+
def subkey_class
|
19
|
+
Hashie::Mash
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse(response)
|
23
|
+
if response.is_a?(Faraday::Response)
|
24
|
+
return nil if response.status == 204
|
25
|
+
response = response.body
|
26
|
+
end
|
27
|
+
|
28
|
+
if self.format == :json
|
29
|
+
MultiJson.load(response)
|
30
|
+
elsif self.format == :xml
|
31
|
+
MultiXml.parse(response)
|
32
|
+
else
|
33
|
+
response
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# Defaults
|
40
|
+
self.format :json
|
41
|
+
|
42
|
+
def id
|
43
|
+
self['id']
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
attributes = []
|
48
|
+
attr_keys = self.keys - ['id']
|
49
|
+
attributes.push "id: #{self.id}" if self.id
|
50
|
+
attr_keys.each do |key|
|
51
|
+
attributes.push("#{key}: #{self[key].inspect}")
|
52
|
+
end
|
53
|
+
"#<#{self.class} #{attributes.join(', ')}>"
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def method_missing(method_name, *args, &blk)
|
58
|
+
if respond_to?(method_name) || has_special_ending?(method_name)
|
59
|
+
super
|
60
|
+
elsif use_strict_reader?(method_name)
|
61
|
+
fetch(method_name)
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def use_strict_reader?(method_name)
|
68
|
+
respond_to?(:strict_attr_reader?) &&
|
69
|
+
self.strict_attr_reader? &&
|
70
|
+
method_name != :to_ary
|
71
|
+
end
|
72
|
+
|
73
|
+
def has_special_ending?(name)
|
74
|
+
name.to_s =~ /[?=]$/
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ApiClient
|
2
|
+
|
3
|
+
module Connection
|
4
|
+
|
5
|
+
class Abstract
|
6
|
+
|
7
|
+
attr_accessor :endpoint, :handler, :options
|
8
|
+
|
9
|
+
def initialize(endpoint, options = {})
|
10
|
+
raise "Cannot instantiate abstract class" if self.class == ApiClient::Connection::Abstract
|
11
|
+
@endpoint = endpoint
|
12
|
+
@options = options
|
13
|
+
create_handler
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_handler
|
17
|
+
end
|
18
|
+
|
19
|
+
#### ApiClient::Connection::Abstract#get
|
20
|
+
# Performs a GET request
|
21
|
+
# Accepts three parameters:
|
22
|
+
#
|
23
|
+
# * path - the path the request should go to
|
24
|
+
# * data - (optional) the query, passed as a hash and converted into query params
|
25
|
+
# * headers - (optional) headers sent along with the request
|
26
|
+
#
|
27
|
+
def get(path, data = {}, headers = {})
|
28
|
+
end
|
29
|
+
|
30
|
+
#### ApiClient::Connection::Abstract#post
|
31
|
+
# Performs a POST request
|
32
|
+
# Accepts three parameters:
|
33
|
+
#
|
34
|
+
# * path - the path request should go to
|
35
|
+
# * data - (optional) data sent in the request
|
36
|
+
# * headers - (optional) headers sent along in the request
|
37
|
+
#
|
38
|
+
def post(path, data = {}, headers = {})
|
39
|
+
end
|
40
|
+
|
41
|
+
#### ApiClient::Connection::Abstract#patch
|
42
|
+
# Performs a PATCH request
|
43
|
+
# Accepts three parameters:
|
44
|
+
#
|
45
|
+
# * path - the path request should go to
|
46
|
+
# * data - (optional) data sent in the request
|
47
|
+
# * headers - (optional) headers sent along in the request
|
48
|
+
#
|
49
|
+
def patch(path, data = {}, headers = {})
|
50
|
+
end
|
51
|
+
|
52
|
+
#### ApiClient::Connection::Abstract#put
|
53
|
+
# Performs a PUT request
|
54
|
+
# Accepts three parameters:
|
55
|
+
#
|
56
|
+
# * path - the path request should go to
|
57
|
+
# * data - (optional) data sent in the request
|
58
|
+
# * headers - (optional) headers sent along in the request
|
59
|
+
#
|
60
|
+
def put(path, data = {}, headers = {})
|
61
|
+
end
|
62
|
+
|
63
|
+
#### FS::Connection#delete
|
64
|
+
# Performs a DELETE request
|
65
|
+
# Accepts three parameters:
|
66
|
+
#
|
67
|
+
# * path - the path request should go to
|
68
|
+
# * data - (optional) the query, passed as a hash and converted into query params
|
69
|
+
# * headers - (optional) headers sent along in the request
|
70
|
+
#
|
71
|
+
def delete(path, data = {}, headers = {})
|
72
|
+
end
|
73
|
+
|
74
|
+
def inspect
|
75
|
+
"#<#{self.class} endpoint: \"#{endpoint}\">"
|
76
|
+
end
|
77
|
+
alias :to_s :inspect
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module ApiClient
|
2
|
+
|
3
|
+
module Connection
|
4
|
+
|
5
|
+
class Basic < Abstract
|
6
|
+
|
7
|
+
def create_handler
|
8
|
+
# Create and memoize the connection object
|
9
|
+
# The empty block is necessary as we don't want Faraday to
|
10
|
+
# initialize itself, we build our own stack in finalize_handler
|
11
|
+
@handler = Faraday.new(@endpoint, @options[:faraday] || {}) do end
|
12
|
+
finalize_handler
|
13
|
+
end
|
14
|
+
|
15
|
+
def finalize_handler
|
16
|
+
@handler.use Middlewares::Request::Logger, ApiClient.logger if ApiClient.logger
|
17
|
+
@handler.use Faraday::Request::UrlEncoded
|
18
|
+
@handler.adapter Faraday.default_adapter
|
19
|
+
end
|
20
|
+
|
21
|
+
#### ApiClient::Connection::Abstract#get
|
22
|
+
# Performs a GET request
|
23
|
+
# Accepts three parameters:
|
24
|
+
#
|
25
|
+
# * path - the path the request should go to
|
26
|
+
# * data - (optional) the query, passed as a hash and converted into query params
|
27
|
+
# * headers - (optional) headers sent along with the request
|
28
|
+
#
|
29
|
+
def get(path, data = {}, headers = {})
|
30
|
+
exec_request(:get, path, data, headers)
|
31
|
+
end
|
32
|
+
|
33
|
+
#### ApiClient::Connection::Abstract#post
|
34
|
+
# Performs a POST request
|
35
|
+
# Accepts three parameters:
|
36
|
+
#
|
37
|
+
# * path - the path request should go to
|
38
|
+
# * data - (optional) data sent in the request
|
39
|
+
# * headers - (optional) headers sent along in the request
|
40
|
+
#
|
41
|
+
# This method automatically adds the application token header
|
42
|
+
def post(path, data = {}, headers = {})
|
43
|
+
exec_request(:post, path, data, headers)
|
44
|
+
end
|
45
|
+
|
46
|
+
#### ApiClient::Connection::Abstract#patch
|
47
|
+
# Performs a PATCH request
|
48
|
+
# Accepts three parameters:
|
49
|
+
#
|
50
|
+
# * path - the path request should go to
|
51
|
+
# * data - (optional) data sent in the request
|
52
|
+
# * headers - (optional) headers sent along in the request
|
53
|
+
#
|
54
|
+
# This method automatically adds the application token header
|
55
|
+
def patch(path, data = {}, headers = {})
|
56
|
+
exec_request(:patch, path, data, headers)
|
57
|
+
end
|
58
|
+
|
59
|
+
#### ApiClient::Connection::Abstract#put
|
60
|
+
# Performs a PUT request
|
61
|
+
# Accepts three parameters:
|
62
|
+
#
|
63
|
+
# * path - the path request should go to
|
64
|
+
# * data - (optional) data sent in the request
|
65
|
+
# * headers - (optional) headers sent along in the request
|
66
|
+
#
|
67
|
+
# This method automatically adds the application token header
|
68
|
+
def put(path, data = {}, headers = {})
|
69
|
+
exec_request(:put, path, data, headers)
|
70
|
+
end
|
71
|
+
|
72
|
+
#### FS::Connection#delete
|
73
|
+
# Performs a DELETE request
|
74
|
+
# Accepts three parameters:
|
75
|
+
#
|
76
|
+
# * path - the path request should go to
|
77
|
+
# * data - (optional) the query, passed as a hash and converted into query params
|
78
|
+
# * headers - (optional) headers sent along in the request
|
79
|
+
#
|
80
|
+
# This method automatically adds the application token header
|
81
|
+
def delete(path, data = {}, headers = {})
|
82
|
+
exec_request(:delete, path, data, headers)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def exec_request(method, path, data, headers)
|
88
|
+
response = @handler.send(method, path, data, headers)
|
89
|
+
request = { :method => method, :path => path, :data => data}
|
90
|
+
handle_response(request, response)
|
91
|
+
rescue Faraday::Error::ConnectionFailed => e
|
92
|
+
raise ApiClient::Errors::ConnectionFailed.new(e.message, request, response)
|
93
|
+
end
|
94
|
+
|
95
|
+
def handle_response(request, response)
|
96
|
+
raise ApiClient::Errors::ConnectionFailed.new(nil, request, response) unless response
|
97
|
+
case response.status
|
98
|
+
when 401
|
99
|
+
raise ApiClient::Errors::Unauthorized.new(nil, request, response)
|
100
|
+
when 403
|
101
|
+
raise ApiClient::Errors::Forbidden.new(nil, request, response)
|
102
|
+
when 404
|
103
|
+
raise ApiClient::Errors::NotFound.new(nil, request, response)
|
104
|
+
when 400
|
105
|
+
raise ApiClient::Errors::BadRequest.new(nil, request, response)
|
106
|
+
when 406
|
107
|
+
raise ApiClient::Errors::Unsupported.new(nil, request, response)
|
108
|
+
when 409
|
109
|
+
raise ApiClient::Errors::Conflict.new(nil, request, response)
|
110
|
+
when 410
|
111
|
+
raise ApiClient::Errors::Gone.new(nil, request, response)
|
112
|
+
when 422
|
113
|
+
raise ApiClient::Errors::UnprocessableEntity.new(response.body, request, response)
|
114
|
+
when 423
|
115
|
+
raise ApiClient::Errors::Locked.new(response.body, request, response)
|
116
|
+
when 429
|
117
|
+
raise ApiClient::Errors::TooManyRequests.new(response.body, request, response)
|
118
|
+
when 300..399
|
119
|
+
raise ApiClient::Errors::Redirect.new(response['Location'], request, response)
|
120
|
+
when 500..599
|
121
|
+
raise ApiClient::Errors::ServerError.new(nil, request, response)
|
122
|
+
else
|
123
|
+
response
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Exactly like Basic, but uses JSON encoding for request body
|
2
|
+
# if applicable
|
3
|
+
module ApiClient
|
4
|
+
module Connection
|
5
|
+
class Json < Basic
|
6
|
+
def finalize_handler
|
7
|
+
@handler.use Middlewares::Request::Logger, ApiClient.logger if ApiClient.logger
|
8
|
+
@handler.use Middlewares::Request::Json
|
9
|
+
@handler.use Faraday::Request::UrlEncoded
|
10
|
+
@handler.adapter Faraday.default_adapter
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class ApiClient::Connection::Middlewares::Request::Json < Faraday::Middleware
|
2
|
+
CONTENT_TYPE = "Content-Type".freeze
|
3
|
+
|
4
|
+
class << self
|
5
|
+
attr_accessor :mime_type
|
6
|
+
end
|
7
|
+
self.mime_type = "application/json".freeze
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
match_content_type(env) do |data|
|
11
|
+
params = Faraday::Utils::ParamsHash[data]
|
12
|
+
env[:body] = MultiJson.dump(params)
|
13
|
+
end
|
14
|
+
@app.call env
|
15
|
+
end
|
16
|
+
|
17
|
+
def match_content_type(env)
|
18
|
+
if process_request?(env)
|
19
|
+
env[:request_headers][CONTENT_TYPE] ||= self.class.mime_type
|
20
|
+
yield env[:body] unless env[:body].respond_to?(:to_str)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def process_request?(env)
|
25
|
+
type = request_type(env)
|
26
|
+
env[:body] and (type.empty? or type == self.class.mime_type)
|
27
|
+
end
|
28
|
+
|
29
|
+
def request_type(env)
|
30
|
+
type = env[:request_headers][CONTENT_TYPE].to_s
|
31
|
+
type = type.split(";", 2).first if type.index(";")
|
32
|
+
type
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
3
|
+
class ApiClient::Connection::Middlewares::Request::Logger < Faraday::Middleware
|
4
|
+
def call(env)
|
5
|
+
debug_lines = []
|
6
|
+
should_log_details = @logger.level <= ::Logger::DEBUG
|
7
|
+
|
8
|
+
gather_request_debug_lines(env, debug_lines) if should_log_details
|
9
|
+
|
10
|
+
start = CurrentTimestamp.milis
|
11
|
+
response = @app.call(env)
|
12
|
+
taken_sec = (CurrentTimestamp.milis - start) / 1000.0
|
13
|
+
|
14
|
+
gather_response_debug_lines(response, taken_sec, debug_lines) if response && should_log_details
|
15
|
+
|
16
|
+
if should_log_details
|
17
|
+
debug_lines.each { |line| line.encode!("UTF-8", invalid: :replace, undef: :replace) }
|
18
|
+
@logger.debug { debug_lines.join("\n") }
|
19
|
+
else
|
20
|
+
@logger.info { "#{env[:method].to_s.upcase} #{env[:url]}: #{"%.4f" % taken_sec} seconds" }
|
21
|
+
end
|
22
|
+
|
23
|
+
response
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(app, logger = nil)
|
27
|
+
@logger = logger || ::Logger.new(STDOUT)
|
28
|
+
@app = app
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def gather_request_debug_lines(env, debug_lines)
|
34
|
+
debug_lines << "> #{env[:method].to_s.upcase} #{env[:url]}"
|
35
|
+
env[:request_headers].each { |k, v| debug_lines << "> #{k}: #{v}" }
|
36
|
+
debug_lines << "> "
|
37
|
+
debug_lines << "> #{env[:body]}\n> " if env[:body] && env[:body] != ""
|
38
|
+
debug_lines
|
39
|
+
end
|
40
|
+
|
41
|
+
def gather_response_debug_lines(response, taken_sec, debug_lines)
|
42
|
+
debug_lines << "< responded in #{"%.4f" % taken_sec} seconds with HTTP #{response.status}"
|
43
|
+
response.headers.each { |k, v| debug_lines << "< #{k}: #{v}" }
|
44
|
+
debug_lines << "< "
|
45
|
+
debug_lines << "< #{response.body}\n> " if response.body && response.body != ""
|
46
|
+
debug_lines
|
47
|
+
end
|
48
|
+
|
49
|
+
class CurrentTimestamp
|
50
|
+
class << self
|
51
|
+
version = RUBY_VERSION.split('.').map(&:to_i)
|
52
|
+
|
53
|
+
if (version[0] < 2) || (version[0] == 2 && version[1] < 2)
|
54
|
+
def milis
|
55
|
+
(Time.now.to_f * 1000).to_i
|
56
|
+
end
|
57
|
+
else
|
58
|
+
def milis
|
59
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Borrowed from https://github.com/pengwynn/faraday_middleware/blob/master/lib/faraday/request/oauth.rb
|
2
|
+
class ApiClient::Connection::Middlewares::Request::OAuth < Faraday::Middleware
|
3
|
+
|
4
|
+
dependency 'simple_oauth'
|
5
|
+
|
6
|
+
def call(env)
|
7
|
+
params = env[:body] || {}
|
8
|
+
signature_params = params.reject{ |k,v| v.respond_to?(:content_type) }
|
9
|
+
|
10
|
+
header = SimpleOAuth::Header.new(env[:method], env[:url], signature_params, @options || {})
|
11
|
+
|
12
|
+
env[:request_headers]['Authorization'] = header.to_s
|
13
|
+
env[:request_headers]['User-Agent'] = "ApiClient gem v#{ApiClient::VERSION}"
|
14
|
+
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(app, options = {})
|
19
|
+
@app, @options = app, options
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|