apia-client 2.0.0
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 +7 -0
- data/VERSION +1 -0
- data/lib/apia-client.rb +6 -0
- data/lib/apia_client.rb +21 -0
- data/lib/apia_client/api.rb +136 -0
- data/lib/apia_client/errors/connection_error.rb +6 -0
- data/lib/apia_client/errors/request_error.rb +50 -0
- data/lib/apia_client/errors/schema_not_loaded_error.rb +6 -0
- data/lib/apia_client/errors/timeout_error.rb +8 -0
- data/lib/apia_client/request.rb +34 -0
- data/lib/apia_client/request_proxy.rb +38 -0
- data/lib/apia_client/request_types/delete.rb +11 -0
- data/lib/apia_client/request_types/get.rb +22 -0
- data/lib/apia_client/request_types/patch.rb +11 -0
- data/lib/apia_client/request_types/post.rb +11 -0
- data/lib/apia_client/request_types/put.rb +11 -0
- data/lib/apia_client/response.rb +20 -0
- data/lib/apia_client/version.rb +12 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7855cdda856e2e80063bfb19c3c41280e3979e06de43b120e90d122768cb1144
|
4
|
+
data.tar.gz: 1ff0272215aa64ca9005f3749bcd88d681ee138ea1fb46170ed363140e8b9f27
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 60c2e8821cf3e0f96e0792d5be28b1d6feb1db85fa566094cfb587f48b16ebc0df336a72d728685c61705271ea2eb4fc9f61794b6479231f493292516067ce5f
|
7
|
+
data.tar.gz: ef94dd2485dd2a0fe28a12bd15ea915332ff544d266165677801a4ec21cda980e02f4594108680d86f62dfdffe8b97fdda4fc03b824b9f97f801efc844df9a74
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
data/lib/apia-client.rb
ADDED
data/lib/apia_client.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia_client/request_types/delete'
|
4
|
+
require 'apia_client/request_types/get'
|
5
|
+
require 'apia_client/request_types/patch'
|
6
|
+
require 'apia_client/request_types/post'
|
7
|
+
require 'apia_client/request_types/put'
|
8
|
+
|
9
|
+
require 'apia_client/api'
|
10
|
+
|
11
|
+
module ApiaClient
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
def load(*args, **options)
|
16
|
+
API.load(*args, **options)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
require 'apia_schema_parser'
|
6
|
+
require 'apia_client/errors/request_error'
|
7
|
+
require 'apia_client/errors/connection_error'
|
8
|
+
require 'apia_client/errors/schema_not_loaded_error'
|
9
|
+
require 'apia_client/errors/timeout_error'
|
10
|
+
require 'apia_client/response'
|
11
|
+
require 'apia_client/request_proxy'
|
12
|
+
|
13
|
+
module ApiaClient
|
14
|
+
class API
|
15
|
+
|
16
|
+
attr_reader :host
|
17
|
+
attr_reader :headers
|
18
|
+
attr_reader :schema
|
19
|
+
|
20
|
+
def initialize(host, **options)
|
21
|
+
@host = host
|
22
|
+
@headers = options[:headers] || {}
|
23
|
+
@options = options
|
24
|
+
end
|
25
|
+
|
26
|
+
def ssl?
|
27
|
+
@options[:ssl].nil? || @options[:ssl] == true
|
28
|
+
end
|
29
|
+
|
30
|
+
def port
|
31
|
+
@options[:port] || (ssl? ? 443 : 80)
|
32
|
+
end
|
33
|
+
|
34
|
+
def namespace
|
35
|
+
(@options[:namespace] || '').sub(/\A\/*/, '').sub(/\/*\z/, '')
|
36
|
+
end
|
37
|
+
|
38
|
+
def schema?
|
39
|
+
!!@schema
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_schema
|
43
|
+
response = request(Get.new('schema'))
|
44
|
+
@schema = ApiaSchemaParser::Schema.new(response.hash)
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def request(request)
|
49
|
+
status, headers, body = make_http_request(request) do |req|
|
50
|
+
request.add_arguments_to_request(req)
|
51
|
+
end
|
52
|
+
Response.new(self, request, body, headers, status)
|
53
|
+
end
|
54
|
+
|
55
|
+
def perform(*args)
|
56
|
+
request = create_request(*args)
|
57
|
+
return if request.nil?
|
58
|
+
|
59
|
+
yield request if block_given?
|
60
|
+
request.perform
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_request(method, path)
|
64
|
+
unless schema?
|
65
|
+
raise SchemaNotLoadedError, 'No schema has been loaded for this API instance'
|
66
|
+
end
|
67
|
+
|
68
|
+
route = schema.api.route_set.routes.find do |r|
|
69
|
+
r.request_method == method.to_s.upcase &&
|
70
|
+
r.path == path
|
71
|
+
end
|
72
|
+
|
73
|
+
return if route.nil?
|
74
|
+
|
75
|
+
RequestProxy.new(self, route)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def create_http(**options)
|
81
|
+
http = Net::HTTP.new(host, port)
|
82
|
+
http.use_ssl = ssl?
|
83
|
+
http.read_timeout = options[:http_read_timeout] || @options[:http_read_timeout] || 60
|
84
|
+
http.open_timeout = options[:http_open_timeout] || @options[:http_open_timeout] || 10
|
85
|
+
http
|
86
|
+
end
|
87
|
+
|
88
|
+
def make_http_request(request)
|
89
|
+
http_request = request.class.method.new("/#{namespace}/#{request.path_for_net_http}")
|
90
|
+
@headers.each do |key, value|
|
91
|
+
http_request[key] = value
|
92
|
+
end
|
93
|
+
yield http_request if block_given?
|
94
|
+
response = make_request_with_error_handling(http_request, request)
|
95
|
+
handle_response(response)
|
96
|
+
end
|
97
|
+
|
98
|
+
def make_request_with_error_handling(http_request, request)
|
99
|
+
http = create_http(
|
100
|
+
http_read_timeout: request.http_read_timeout,
|
101
|
+
http_open_timeout: request.http_open_timeout
|
102
|
+
)
|
103
|
+
http.request(http_request)
|
104
|
+
rescue Timeout::Error => e
|
105
|
+
raise ApiaClient::TimeoutError, e.message
|
106
|
+
rescue StandardError => e
|
107
|
+
raise ConnectionError, e.message
|
108
|
+
end
|
109
|
+
|
110
|
+
def handle_response(response)
|
111
|
+
if response['content-type'] =~ /application\/json/
|
112
|
+
body = JSON.parse(response.body)
|
113
|
+
else
|
114
|
+
body = response.body
|
115
|
+
end
|
116
|
+
|
117
|
+
status_code = response.code.to_i
|
118
|
+
if status_code >= 200 && status_code < 300
|
119
|
+
return [status_code, response.to_hash, body]
|
120
|
+
end
|
121
|
+
|
122
|
+
raise RequestError.new(self, status_code, body)
|
123
|
+
end
|
124
|
+
|
125
|
+
class << self
|
126
|
+
|
127
|
+
def load(*args, **options)
|
128
|
+
api = new(*args, **options)
|
129
|
+
api.load_schema
|
130
|
+
api
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiaClient
|
4
|
+
class RequestError < StandardError
|
5
|
+
|
6
|
+
attr_reader :status
|
7
|
+
attr_reader :body
|
8
|
+
|
9
|
+
# rubocop:disable Lint/MissingSuper
|
10
|
+
def initialize(client, status, body)
|
11
|
+
@client = client
|
12
|
+
@status = status
|
13
|
+
@body = body
|
14
|
+
|
15
|
+
@error = @body['error']
|
16
|
+
end
|
17
|
+
# rubocop:enable Lint/MissingSuper
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
string = ["[#{@status}]"]
|
21
|
+
if code && description
|
22
|
+
string << "#{code}: #{description}"
|
23
|
+
elsif code
|
24
|
+
string << code
|
25
|
+
else
|
26
|
+
string << @body
|
27
|
+
end
|
28
|
+
string.join(' ')
|
29
|
+
end
|
30
|
+
|
31
|
+
def code
|
32
|
+
return if @error.nil?
|
33
|
+
|
34
|
+
@error['code']
|
35
|
+
end
|
36
|
+
|
37
|
+
def description
|
38
|
+
return if @error.nil?
|
39
|
+
|
40
|
+
@error['description']
|
41
|
+
end
|
42
|
+
|
43
|
+
def detail
|
44
|
+
return if @error.nil?
|
45
|
+
|
46
|
+
@error['detail'] || {}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module ApiaClient
|
6
|
+
class Request
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
attr_accessor :method
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :path
|
15
|
+
attr_reader :arguments
|
16
|
+
attr_accessor :http_read_timeout
|
17
|
+
attr_accessor :http_open_timeout
|
18
|
+
|
19
|
+
def initialize(path)
|
20
|
+
@path = path
|
21
|
+
@arguments = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def path_for_net_http
|
25
|
+
path
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_arguments_to_request(request)
|
29
|
+
request['Content-Type'] = 'application/json'
|
30
|
+
request.body = arguments.to_json
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiaClient
|
4
|
+
class RequestProxy
|
5
|
+
|
6
|
+
METHOD_MAP = {
|
7
|
+
get: ApiaClient::Get,
|
8
|
+
post: ApiaClient::Post,
|
9
|
+
patch: ApiaClient::Patch,
|
10
|
+
put: ApiaClient::Put,
|
11
|
+
delete: ApiaClient::Delete
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
attr_reader :route
|
15
|
+
attr_reader :request
|
16
|
+
|
17
|
+
def initialize(client, route)
|
18
|
+
@client = client
|
19
|
+
@route = route
|
20
|
+
|
21
|
+
request_class = METHOD_MAP[@route.request_method.downcase.to_sym]
|
22
|
+
@request = request_class.new(@route.path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def perform
|
26
|
+
@client.request(@request)
|
27
|
+
end
|
28
|
+
|
29
|
+
def arguments
|
30
|
+
@request.arguments
|
31
|
+
end
|
32
|
+
|
33
|
+
def endpoint
|
34
|
+
@route.endpoint
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia_client/request'
|
4
|
+
require 'json'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
module ApiaClient
|
8
|
+
class Get < Request
|
9
|
+
|
10
|
+
self.method = Net::HTTP::Get
|
11
|
+
|
12
|
+
def path_for_net_http
|
13
|
+
querystring = URI.encode_www_form(_arguments: @arguments.to_json)
|
14
|
+
"#{path}?#{querystring}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_arguments_to_request(request)
|
18
|
+
# Don't need to do anything for GET requests...
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiaClient
|
4
|
+
class Response
|
5
|
+
|
6
|
+
def initialize(client, request, hash, headers, status)
|
7
|
+
@client = client
|
8
|
+
@request = request
|
9
|
+
@hash = hash
|
10
|
+
@headers = headers
|
11
|
+
@status = status
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :request
|
15
|
+
attr_reader :hash
|
16
|
+
attr_reader :headers
|
17
|
+
attr_reader :status
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiaClient
|
4
|
+
|
5
|
+
VERSION_FILE_ROOT = File.expand_path('../../VERSION', __dir__)
|
6
|
+
if File.file?(VERSION_FILE_ROOT)
|
7
|
+
VERSION = File.read(VERSION_FILE_ROOT).strip.sub(/\Av/, '')
|
8
|
+
else
|
9
|
+
VERSION = '0.0.0.dev'
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: apia-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Cooke
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-08-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: apia-schema-parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: A client library for talking to any Apia API.
|
42
|
+
email:
|
43
|
+
- adam@k.io
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- VERSION
|
49
|
+
- lib/apia-client.rb
|
50
|
+
- lib/apia_client.rb
|
51
|
+
- lib/apia_client/api.rb
|
52
|
+
- lib/apia_client/errors/connection_error.rb
|
53
|
+
- lib/apia_client/errors/request_error.rb
|
54
|
+
- lib/apia_client/errors/schema_not_loaded_error.rb
|
55
|
+
- lib/apia_client/errors/timeout_error.rb
|
56
|
+
- lib/apia_client/request.rb
|
57
|
+
- lib/apia_client/request_proxy.rb
|
58
|
+
- lib/apia_client/request_types/delete.rb
|
59
|
+
- lib/apia_client/request_types/get.rb
|
60
|
+
- lib/apia_client/request_types/patch.rb
|
61
|
+
- lib/apia_client/request_types/post.rb
|
62
|
+
- lib/apia_client/request_types/put.rb
|
63
|
+
- lib/apia_client/response.rb
|
64
|
+
- lib/apia_client/version.rb
|
65
|
+
homepage: https://github.com/krystal/apia-ruby-client
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
metadata: {}
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.5'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubygems_version: 3.1.6
|
85
|
+
signing_key:
|
86
|
+
specification_version: 4
|
87
|
+
summary: A client library for talking to any Apia API.
|
88
|
+
test_files: []
|