johac 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/johac/client.rb +73 -0
- data/lib/johac/connection.rb +185 -0
- data/lib/johac/error.rb +66 -0
- data/lib/johac/response.rb +128 -0
- data/lib/johac/version.rb +3 -0
- data/lib/johac.rb +95 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c9a6e0cd9ab2cb5c7aba657db7c59a726d7ec85a
|
4
|
+
data.tar.gz: c25864469ee9ace99f7b21fc7982a1bec72a8f69
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c6a3065a97f85e39e4a05963b559eb0d9260200c7898953485b58217df614f6c99f44846d9616ce50995fd7d1af9e83fba414ac528818e0cd9f838654d954ac7
|
7
|
+
data.tar.gz: 5bd7feade84a9af0a72e0341bf8ddb048867ce778d6aff22ee0f310d6d9a0ff38500d091c712cc5867d911eda69a4fec8687a96b65a985fc26376be97f021b2b
|
data/lib/johac/client.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Johac
|
2
|
+
|
3
|
+
# Base class for Johac API Client.
|
4
|
+
#
|
5
|
+
# Extend this class and provide API specific calls
|
6
|
+
class Client
|
7
|
+
|
8
|
+
attr_reader :config
|
9
|
+
|
10
|
+
# HTTP lib inclusion
|
11
|
+
#
|
12
|
+
# Supplies one method, {#connection}.
|
13
|
+
#
|
14
|
+
# The {#connection} method should return an object that responds to HTTP verbs (eg. #get, #post, #put, #delete).
|
15
|
+
include Connection
|
16
|
+
|
17
|
+
# @param config [Johac::Config]
|
18
|
+
def initialize(config=nil)
|
19
|
+
@config = Johac.merged_config(config)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Reference to +base_uri+ set on {Johac.config} in {Johac.configure} or in the constructor.
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
def uri
|
26
|
+
config.base_uri
|
27
|
+
end
|
28
|
+
|
29
|
+
# Reference to the current environment. Set explicitly in {Johac.configure} or via
|
30
|
+
# environment variables +JOHAC_ENV+ or +RAILS_ENV+.
|
31
|
+
#
|
32
|
+
# @return [String] One of "testing", "development", or "production"
|
33
|
+
def env
|
34
|
+
config.env
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def head(path, options={})
|
40
|
+
request { connection.head(path, options[:query], options[:headers]) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def get(path, options={})
|
44
|
+
request { connection.get(path, options[:query], options[:headers]) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete(path, options={})
|
48
|
+
request { connection.delete(path, options[:query], options[:headers]) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def post(path, options={})
|
52
|
+
request { connection.post(path, options[:body], options[:headers]) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def put(path, options={})
|
56
|
+
request { connection.put(path, options[:body], options[:headers]) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def patch(path, options={})
|
60
|
+
request { connection.patch(path, options[:body], options[:headers]) }
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# Wrap the response or error, or raise an exception if configured
|
66
|
+
def request(&block)
|
67
|
+
Johac::Response.new(yield)
|
68
|
+
rescue => e
|
69
|
+
@config.raise_exceptions ? (raise e) : Johac::Response.new(e)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
module Johac
|
2
|
+
|
3
|
+
# Provides {#connection}.
|
4
|
+
#
|
5
|
+
# Uses the {https://github.com/lostisland/faraday faraday} lib to handle HTTP requests.
|
6
|
+
#
|
7
|
+
# @see https://github.com/lostisland/faraday
|
8
|
+
module Connection
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def connection
|
13
|
+
@connection ||= Faraday.new(:url => uri) do |faraday|
|
14
|
+
faraday.use :johac_connection_exceptions
|
15
|
+
|
16
|
+
faraday.request :json
|
17
|
+
faraday.request :johac_headers
|
18
|
+
faraday.request :johac_auth, @config.auth_scheme, @config.access_key, @config.secret_key
|
19
|
+
|
20
|
+
# Retry requests
|
21
|
+
faraday.request :retry, {
|
22
|
+
max: 2,
|
23
|
+
interval: 0.5,
|
24
|
+
backoff_factor: 3,
|
25
|
+
interval_randomness: 0.5,
|
26
|
+
|
27
|
+
# All connection errors + 429, 503, and 504
|
28
|
+
exceptions: [
|
29
|
+
Johac::Error::ConnectionError,
|
30
|
+
Johac::Error::RetryableError
|
31
|
+
]
|
32
|
+
}
|
33
|
+
|
34
|
+
# apparently the response middleware acts like a stack, not a queue
|
35
|
+
faraday.response :json
|
36
|
+
|
37
|
+
# Raise connection errors as exceptions
|
38
|
+
faraday.response :johac_raise_error
|
39
|
+
|
40
|
+
faraday.adapter :johac_persistent do |http|
|
41
|
+
# http param is an instance of Net::HTTP::Persistent
|
42
|
+
#
|
43
|
+
http.open_timeout = 2
|
44
|
+
http.read_timeout = 60
|
45
|
+
http.idle_timeout = 120
|
46
|
+
|
47
|
+
# http.keep_alive
|
48
|
+
# http.max_requests
|
49
|
+
# http.socket_options
|
50
|
+
http.debug_output = STDOUT if env == 'development'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Custom middleware.
|
58
|
+
module Connection::Middleware
|
59
|
+
|
60
|
+
# Wrapper of {Faraday::Adapter::NetHttpPersistent} adapter that allows for
|
61
|
+
# a block to be given when the faraday connection is created. Block is
|
62
|
+
# passed the newly created {Net::HTTP::Persistent} instance to be modified
|
63
|
+
# if desired.
|
64
|
+
#
|
65
|
+
# Allows for configuration of HTTP connection.
|
66
|
+
#
|
67
|
+
# @see https://github.com/lostisland/faraday
|
68
|
+
# @see https://github.com/drbrain/net-http-persistent
|
69
|
+
class PersistentAdapter < Faraday::Adapter::NetHttpPersistent
|
70
|
+
|
71
|
+
Faraday::Adapter.register_middleware :johac_persistent => self
|
72
|
+
|
73
|
+
# Extend Faraday::Adapter::NetHttpPersistent's initialize method with an
|
74
|
+
# optional block.
|
75
|
+
#
|
76
|
+
# @yield [Net::HTTP::Persistent] Stores the passed block for use when
|
77
|
+
# creating a new HTTP connection.
|
78
|
+
def initialize(app, &block)
|
79
|
+
@config_block = block
|
80
|
+
super(app)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Yield HTTP connection to supplied block.
|
84
|
+
def with_net_http_connection(env, &block)
|
85
|
+
http = super(env) { |v| v }
|
86
|
+
@config_block.call(http) if @config_block
|
87
|
+
yield http
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
# Write custom user agent to all requests.
|
93
|
+
class JohacHeaders < Faraday::Middleware
|
94
|
+
|
95
|
+
Faraday::Request.register_middleware :johac_headers => self
|
96
|
+
|
97
|
+
AgentString = "johac/#{Johac::Version} ruby/#{RUBY_VERSION}".freeze
|
98
|
+
Accept = 'application/json'.freeze
|
99
|
+
|
100
|
+
def call(env)
|
101
|
+
env[:request_headers]['User-Agent'] = AgentString
|
102
|
+
env[:request_headers]['Accept'] = Accept
|
103
|
+
@app.call(env)
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
# Adds Authorization header to all requests.
|
109
|
+
class Authorization < Faraday::Middleware
|
110
|
+
|
111
|
+
Faraday::Request.register_middleware :johac_auth => self
|
112
|
+
|
113
|
+
def initialize(app, scheme, access_key, secret_key)
|
114
|
+
@scheme = scheme
|
115
|
+
@access_key = access_key
|
116
|
+
@secret_key = secret_key
|
117
|
+
super(app)
|
118
|
+
end
|
119
|
+
|
120
|
+
def call(env)
|
121
|
+
if auth = case @scheme
|
122
|
+
when :basic then "Basic #{basic_auth_token}"
|
123
|
+
when :hmac then "hmac #{hmac_auth_token(env.url.path)}"
|
124
|
+
end
|
125
|
+
env[:request_headers]['Authorization'] = auth
|
126
|
+
end
|
127
|
+
@app.call(env)
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def basic_auth_token
|
133
|
+
Base64.strict_encode64("#{@access_key}:#{@secret_key}")
|
134
|
+
end
|
135
|
+
|
136
|
+
# TODO: Need a hook for generating the value
|
137
|
+
def hmac_auth_token(token)
|
138
|
+
OpenSSL::HMAC.hexdigest('sha1', @secret_key, token)
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
# Will raise some {Johac::Error::ResponseError} from an HTTP response using status codes.
|
144
|
+
class RaiseError < Faraday::Response::Middleware
|
145
|
+
|
146
|
+
Faraday::Response.register_middleware :johac_raise_error => self
|
147
|
+
|
148
|
+
def on_complete(env)
|
149
|
+
if e = ::Johac::Error::ResponseError.from_response(env.status, env.response_headers, env.body)
|
150
|
+
raise e
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
# Will raise some {Johac::Error::ConnectionError} if something happens with the connection.
|
157
|
+
class Exceptions < Faraday::Middleware
|
158
|
+
|
159
|
+
Faraday::Middleware.register_middleware :johac_connection_exceptions => self
|
160
|
+
|
161
|
+
def call(env)
|
162
|
+
@app.call(env)
|
163
|
+
rescue Faraday::Error::ConnectionFailed => e
|
164
|
+
raise ::Johac::Error::ConnectionError, e.message
|
165
|
+
rescue Faraday::Error::ResourceNotFound => e
|
166
|
+
raise ::Johac::Error::ConnectionError, e.message
|
167
|
+
rescue Faraday::Error::ParsingError => e
|
168
|
+
raise ::Johac::Error::ConnectionError, e.message
|
169
|
+
rescue Faraday::Error::TimeoutError => e
|
170
|
+
raise ::Johac::Error::ConnectionError, e.message
|
171
|
+
rescue Faraday::Error::SSLError => e
|
172
|
+
raise ::Johac::Error::ConnectionError, e.message
|
173
|
+
rescue Faraday::Error::ClientError => e
|
174
|
+
raise ::Johac::Error::ConnectionError, e.message
|
175
|
+
rescue Faraday::Error => e
|
176
|
+
raise ::Johac::Error::ConnectionError, e.message
|
177
|
+
rescue Net::HTTP::Persistent::Error => e
|
178
|
+
raise ::Johac::Error::ConnectionError, e.message, e.backtrace
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
data/lib/johac/error.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Johac
|
2
|
+
|
3
|
+
# {Johac} exception overrides.
|
4
|
+
#
|
5
|
+
# Rescue {Johac::Error Johac::Error} to catch all Johac errors.
|
6
|
+
class Error < StandardError
|
7
|
+
|
8
|
+
# Exception to be used when dealing with HTTP responses from a Johac API.
|
9
|
+
class ResponseError < Error
|
10
|
+
|
11
|
+
attr_reader :code
|
12
|
+
attr_reader :body
|
13
|
+
|
14
|
+
# Will attempt to decode a response body via JSON, and look for the 'message' key in the resulting (assumed) hash. If response body cannot be parsed via JSON the entire response body is set as the message for the exception.
|
15
|
+
#
|
16
|
+
# @param body [String] Response body.
|
17
|
+
# @param headers [Hash] Response headers.
|
18
|
+
def initialize(code, body, headers)
|
19
|
+
@code = code
|
20
|
+
@body = if headers['Content-Type'] == 'application/json'
|
21
|
+
JSON.parse(body) rescue body
|
22
|
+
else
|
23
|
+
body
|
24
|
+
end
|
25
|
+
super(body)
|
26
|
+
end
|
27
|
+
|
28
|
+
# If a problem is detected in an HTTP response, build the proper exception, otherwise return nil.
|
29
|
+
#
|
30
|
+
# @param status_code [Integer] HTTP response code.
|
31
|
+
# @param body [String] Response body.
|
32
|
+
# @param headers [Hash] Response headers.
|
33
|
+
#
|
34
|
+
# @return [Johac::Error::RetryableError] A client or server error which may be retried
|
35
|
+
# @return [Johac::Error::ClientError] The client has made a mistake and should take corrective action.
|
36
|
+
# @return [Johac::Error::ServerError] If there was a problem server-side, we're on it.
|
37
|
+
# @return [nil] If no error was detected in the response.
|
38
|
+
def self.from_response(status_code, headers, body)
|
39
|
+
if klass = case status_code
|
40
|
+
when 429 then RetryableError
|
41
|
+
when 503 then RetryableError
|
42
|
+
when 504 then RetryableError
|
43
|
+
when 400..499 then ClientError
|
44
|
+
when 500..599 then ServerError
|
45
|
+
end
|
46
|
+
klass.new(status_code, body, headers)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
# An error that we should retry
|
53
|
+
class RetryableError < ResponseError; end
|
54
|
+
|
55
|
+
# There was a problem on our side, we're working on it.
|
56
|
+
class ServerError < ResponseError; end
|
57
|
+
|
58
|
+
# There was a problem with the requested or submitted resource.
|
59
|
+
class ClientError < ResponseError; end
|
60
|
+
|
61
|
+
# Error specific to the http connection.
|
62
|
+
class ConnectionError < Error; end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Johac
|
2
|
+
class Response
|
3
|
+
|
4
|
+
attr_reader :response
|
5
|
+
attr_reader :exception
|
6
|
+
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize(result)
|
10
|
+
if result.kind_of?(Faraday::Response)
|
11
|
+
@response = result
|
12
|
+
else
|
13
|
+
@exception = result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Determine if the request failed
|
18
|
+
#
|
19
|
+
# @return true if response failed (http or expcetion)
|
20
|
+
def error?
|
21
|
+
exception != nil || status >= 400
|
22
|
+
end
|
23
|
+
|
24
|
+
# HTTP Status code
|
25
|
+
#
|
26
|
+
# @return response status code
|
27
|
+
def status
|
28
|
+
response_status || exception_status || 0
|
29
|
+
end
|
30
|
+
|
31
|
+
# HTTP Status code
|
32
|
+
#
|
33
|
+
# @return response status code
|
34
|
+
def code
|
35
|
+
status
|
36
|
+
end
|
37
|
+
|
38
|
+
# HTTP Response body as a JSON parsed object
|
39
|
+
#
|
40
|
+
# @return Hash/Array of the JSON parsed body, or empty hash
|
41
|
+
def body
|
42
|
+
response_body || exception_body || {}
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return OpenStruct object of hash
|
46
|
+
def object
|
47
|
+
OpenStruct.new(body)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Map body hash to another value using a block
|
51
|
+
#
|
52
|
+
# @param block [Block] mapping function block
|
53
|
+
#
|
54
|
+
# @return result of block
|
55
|
+
def map_object(&block)
|
56
|
+
yield body
|
57
|
+
end
|
58
|
+
|
59
|
+
# Dig for a item in the body
|
60
|
+
#
|
61
|
+
# @param args [Varargs] path of value
|
62
|
+
#
|
63
|
+
# @see {Hash.dig}
|
64
|
+
# @see {Array.dig}
|
65
|
+
#
|
66
|
+
# @return value of key path
|
67
|
+
def dig(*args)
|
68
|
+
body.dig(*args)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Enumerate over response body opject
|
72
|
+
#
|
73
|
+
# @see {Enumerable}
|
74
|
+
# @param block [Block] to invoke
|
75
|
+
def each(&block)
|
76
|
+
body.each(&block)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Invoke a block of code if the response fails, with
|
80
|
+
# the exception as the paramter.
|
81
|
+
#
|
82
|
+
# @param block [Block] to invoke
|
83
|
+
def on_error(&block)
|
84
|
+
if error?
|
85
|
+
yield exception
|
86
|
+
end
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
# Invoke a block of code if the response succeeds, with the content
|
91
|
+
# as a parameter
|
92
|
+
#
|
93
|
+
# @param block [Block] to invoke
|
94
|
+
def on_success(&block)
|
95
|
+
unless error?
|
96
|
+
yield body
|
97
|
+
end
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
protected
|
102
|
+
|
103
|
+
def response_status
|
104
|
+
response? ? response.status : nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def response_body
|
108
|
+
response? ? response.body : nil
|
109
|
+
end
|
110
|
+
|
111
|
+
def exception_status
|
112
|
+
response_error? ? exception.code : nil
|
113
|
+
end
|
114
|
+
|
115
|
+
def exception_body
|
116
|
+
response_error? ? exception.body : nil
|
117
|
+
end
|
118
|
+
|
119
|
+
def response_error?
|
120
|
+
exception.kind_of?(Johac::Error::ResponseError)
|
121
|
+
end
|
122
|
+
|
123
|
+
def response?
|
124
|
+
response != nil
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
data/lib/johac.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
$: << File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'faraday'
|
5
|
+
require 'faraday_middleware'
|
6
|
+
require 'net/http/persistent'
|
7
|
+
require 'base64'
|
8
|
+
require 'ostruct'
|
9
|
+
|
10
|
+
module Johac
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
# Simple config class used to store global {Johac::Client} settings.
|
15
|
+
#
|
16
|
+
# @attr base_uri [String] Hostname of Johac API.
|
17
|
+
# @attr auth_scheme [Symbol] Authorization scheme to be used on all requests, +:basic+ or +:hmac+.
|
18
|
+
# @attr access_key [String] Public access key used for authorization of requests.
|
19
|
+
# @attr secret_key [String] Private key used for authorization of requests.
|
20
|
+
# @attr env [String] Environment. 'testing', 'development', or 'production'.
|
21
|
+
Config = Struct.new(:base_uri, :auth_scheme, :access_key, :secret_key, :env, :logger, :raise_exceptions)
|
22
|
+
|
23
|
+
|
24
|
+
# Configure the global defaults for all clients built.
|
25
|
+
#
|
26
|
+
# @yield [config] Passes a config object to the block.
|
27
|
+
# @yieldparam config [Johac::Config] Config object.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# Johac.defaults do |config|
|
31
|
+
# config.base_uri = 'http://api.myservice.com'
|
32
|
+
# config.auth_scheme = :basic
|
33
|
+
# config.access_key = 'user'
|
34
|
+
# config.secret_key = 'password'
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# @return [Johac::Config]
|
38
|
+
def defaults(&block)
|
39
|
+
c = @config ||= Config.new
|
40
|
+
c.env = environment || 'production'
|
41
|
+
yield c
|
42
|
+
c
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return the config object for the global {Johac::Client} instance.
|
46
|
+
# @return [Johac::Config]
|
47
|
+
def config
|
48
|
+
unless defined? @config
|
49
|
+
raise "#{self.name} not configured. Configure via #{self.name}.configure { |cfg| ... }, or via client constructor"
|
50
|
+
end
|
51
|
+
@config
|
52
|
+
end
|
53
|
+
|
54
|
+
# Merge the new config with defaults
|
55
|
+
def merged_config(overrides)
|
56
|
+
case overrides
|
57
|
+
when Hash
|
58
|
+
dup_config.tap do |conf|
|
59
|
+
overrides.each do |k, v|
|
60
|
+
conf[k] = v
|
61
|
+
end
|
62
|
+
end
|
63
|
+
when Struct
|
64
|
+
dup_config.tap do |conf|
|
65
|
+
overrides.each_pair do |k, v|
|
66
|
+
conf[k] = v
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
config
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
def environment
|
77
|
+
ENV.values_at('JOHAC_ENV', 'RAILS_ENV').compact.first
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def dup_config
|
83
|
+
defined?(@config) ? @config.dup : Config.new
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
require 'johac/version'
|
91
|
+
require 'johac/error'
|
92
|
+
require 'johac/connection'
|
93
|
+
require 'johac/response'
|
94
|
+
require 'johac/client'
|
95
|
+
|
metadata
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: johac
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Simpson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-05-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.15.2
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.9.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.15.2
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.9.2
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: faraday_middleware
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.12.2
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.12.2
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: net-http-persistent
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.9'
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 2.9.4
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '2.9'
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 2.9.4
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rake
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '10.4'
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 10.4.2
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '10.4'
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 10.4.2
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: rack
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - "~>"
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.4'
|
94
|
+
type: :development
|
95
|
+
prerelease: false
|
96
|
+
version_requirements: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - "~>"
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '1.4'
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: webmock
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - "~>"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 3.3.0
|
108
|
+
type: :development
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - "~>"
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 3.3.0
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: yard
|
117
|
+
requirement: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - "~>"
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: 0.8.7.6
|
122
|
+
type: :development
|
123
|
+
prerelease: false
|
124
|
+
version_requirements: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - "~>"
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: 0.8.7.6
|
129
|
+
- !ruby/object:Gem::Dependency
|
130
|
+
name: minitest
|
131
|
+
requirement: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - "~>"
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '4.7'
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 4.7.5
|
139
|
+
type: :development
|
140
|
+
prerelease: false
|
141
|
+
version_requirements: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '4.7'
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 4.7.5
|
149
|
+
description: Opintionated library for implement HTTP+JSON API clients
|
150
|
+
email: dan.simpson@gmail.com
|
151
|
+
executables: []
|
152
|
+
extensions: []
|
153
|
+
extra_rdoc_files: []
|
154
|
+
files:
|
155
|
+
- lib/johac.rb
|
156
|
+
- lib/johac/client.rb
|
157
|
+
- lib/johac/connection.rb
|
158
|
+
- lib/johac/error.rb
|
159
|
+
- lib/johac/response.rb
|
160
|
+
- lib/johac/version.rb
|
161
|
+
homepage: https://github.com/dansimpson/johac
|
162
|
+
licenses:
|
163
|
+
- MIT
|
164
|
+
metadata: {}
|
165
|
+
post_install_message:
|
166
|
+
rdoc_options: []
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
requirements: []
|
180
|
+
rubyforge_project:
|
181
|
+
rubygems_version: 2.6.13
|
182
|
+
signing_key:
|
183
|
+
specification_version: 4
|
184
|
+
summary: JSON Over HTTP API Client
|
185
|
+
test_files: []
|
186
|
+
has_rdoc: true
|