namira 1.0.0.rc2 → 1.0.0.rc3
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 +4 -4
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +9 -1
- data/lib/namira.rb +7 -6
- data/lib/namira/env.rb +26 -0
- data/lib/namira/middleware.rb +15 -0
- data/lib/namira/middleware/config.rb +26 -0
- data/lib/namira/middleware/header.rb +38 -0
- data/lib/namira/middleware/logger.rb +44 -0
- data/lib/namira/middleware/network.rb +28 -0
- data/lib/namira/middleware/redirector.rb +66 -0
- data/lib/namira/middleware/responder.rb +32 -0
- data/lib/namira/middleware/timeout.rb +21 -0
- data/lib/namira/middleware/timing.rb +22 -0
- data/lib/namira/request.rb +20 -34
- data/lib/namira/stack.rb +57 -0
- data/lib/namira/version.rb +1 -1
- metadata +13 -6
- data/lib/namira/auth.rb +0 -2
- data/lib/namira/auth/base.rb +0 -39
- data/lib/namira/auth/http_basic.rb +0 -25
- data/lib/namira/backend.rb +0 -138
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 218528e873d7b85eafe5cc3e31dbb0297d9d1786
|
4
|
+
data.tar.gz: ead0b1b476362ffc18352416afde87af3578047f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c0bd6e7e24bee243dc0de7abefc331aff7b46941976434acecb0e77bbfdbd6db01fbb38aed4f709112cb477aac71f98b4b7a128258085a9ea3accea8dec2d3a
|
7
|
+
data.tar.gz: 9c2bba7ce244f44b33836c1541e12564173c82010649f4f4db9fc489fbeb86d2608c53937113907bcd0697e94a602d6d06f92cb5463ebaf4e1a97b22a1e7f646
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/lib/namira.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
require 'namira/version'
|
2
|
-
require 'namira/request'
|
3
|
-
require 'namira/response'
|
4
|
-
require 'namira/errors'
|
5
1
|
require 'namira/config'
|
2
|
+
require 'namira/env'
|
3
|
+
require 'namira/errors'
|
4
|
+
require 'namira/middleware'
|
6
5
|
require 'namira/query_builder'
|
7
|
-
require 'namira/
|
8
|
-
require 'namira/
|
6
|
+
require 'namira/request'
|
7
|
+
require 'namira/response'
|
8
|
+
require 'namira/stack'
|
9
|
+
require 'namira/version'
|
9
10
|
|
10
11
|
##
|
11
12
|
# A Ruby HTTP client
|
data/lib/namira/env.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Namira
|
2
|
+
##
|
3
|
+
# The calling environment for the request
|
4
|
+
class Env
|
5
|
+
attr_accessor \
|
6
|
+
:uri,
|
7
|
+
:headers,
|
8
|
+
:body,
|
9
|
+
:method,
|
10
|
+
:config,
|
11
|
+
:redirect_count,
|
12
|
+
:response,
|
13
|
+
:timing
|
14
|
+
|
15
|
+
def initialize(env)
|
16
|
+
@uri = Addressable::URI.parse(env[:uri].to_s)
|
17
|
+
@body = env[:body]
|
18
|
+
@method = env[:method]
|
19
|
+
@headers = Hash(env[:headers])
|
20
|
+
@config = Hash(env[:config])
|
21
|
+
@redirect_count = 0
|
22
|
+
@response = nil
|
23
|
+
@timing = nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'middleware/config'
|
2
|
+
require_relative 'middleware/header'
|
3
|
+
require_relative 'middleware/logger'
|
4
|
+
require_relative 'middleware/network'
|
5
|
+
require_relative 'middleware/redirector'
|
6
|
+
require_relative 'middleware/responder'
|
7
|
+
require_relative 'middleware/timeout'
|
8
|
+
require_relative 'middleware/timing'
|
9
|
+
|
10
|
+
module Namira
|
11
|
+
##
|
12
|
+
# Contains the middleware classes for the default stack
|
13
|
+
module Middleware
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Namira
|
2
|
+
module Middleware
|
3
|
+
##
|
4
|
+
# Duplicates the global config for modification by other middleware
|
5
|
+
class Config
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Called by the middleware runner.
|
12
|
+
#
|
13
|
+
# @param env [Namira::Env] The request environment
|
14
|
+
def call(env)
|
15
|
+
env.config = merge_config(env.config.dup)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def merge_config(config)
|
22
|
+
Namira.configure.to_h.merge(config)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Namira
|
2
|
+
module Middleware
|
3
|
+
##
|
4
|
+
# Creates the final request headers by merging global, defaults, and request headers
|
5
|
+
class Header
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Called by the middleware runner.
|
12
|
+
#
|
13
|
+
# @param env [Namira::Env] The request environment
|
14
|
+
def call(env)
|
15
|
+
headers = Hash(Namira.configure.headers.to_h).dup
|
16
|
+
headers.merge!(additional_headers(env))
|
17
|
+
headers.merge!(env.headers.to_h)
|
18
|
+
env.headers = convert_headers(headers)
|
19
|
+
@app.call(env)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def additional_headers(env)
|
25
|
+
{
|
26
|
+
'User-Agent' => env.config[:user_agent]
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def convert_headers(headers)
|
31
|
+
headers.each_with_object({}) do |(key, value), obj|
|
32
|
+
header = key.to_s.split(/-|_/).map(&:capitalize).join('-')
|
33
|
+
obj[header] = value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Namira
|
2
|
+
module Middleware
|
3
|
+
##
|
4
|
+
# Performs request logging
|
5
|
+
class Logger
|
6
|
+
##
|
7
|
+
# The key that will disable logging
|
8
|
+
SKIP_LOGGING_KEY = :skip_logging
|
9
|
+
|
10
|
+
def initialize(app)
|
11
|
+
@app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Called by the middleware runner.
|
16
|
+
#
|
17
|
+
# @param env [Namira::Env] The request environment
|
18
|
+
def call(env)
|
19
|
+
log_request(env)
|
20
|
+
@app.call(env)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def logging?(env)
|
26
|
+
if env.config.keys.include?(SKIP_LOGGING_KEY)
|
27
|
+
env.config[SKIP_LOGGING_KEY] == false
|
28
|
+
else
|
29
|
+
Namira.configure.log_requests == true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def log_request(env)
|
34
|
+
return unless logging?(env)
|
35
|
+
message = "#{env.method.to_s.upcase} - #{env.uri}"
|
36
|
+
if defined?(::Rails)
|
37
|
+
Rails.logger.debug(message)
|
38
|
+
else
|
39
|
+
STDOUT.puts(message)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Namira
|
2
|
+
module Middleware
|
3
|
+
##
|
4
|
+
# Performs the network request
|
5
|
+
class Network
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Called by the middleware runner.
|
12
|
+
#
|
13
|
+
# @param env [Namira::Env] The request environment
|
14
|
+
def call(env)
|
15
|
+
timeout = env.config[:timeout] || 30.0
|
16
|
+
http = HTTP.timeout(
|
17
|
+
:per_operation,
|
18
|
+
write: timeout,
|
19
|
+
connect: timeout,
|
20
|
+
read: timeout
|
21
|
+
)
|
22
|
+
http = http.headers(env.headers)
|
23
|
+
env.response = http.send(env.method, env.uri, body: env.body)
|
24
|
+
@app.call(env)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Namira
|
2
|
+
module Middleware
|
3
|
+
##
|
4
|
+
# Performs following the redirect and handling multiple redirect errors.
|
5
|
+
class Redirector
|
6
|
+
##
|
7
|
+
# The HTTP status codes Namira will consider a redirect
|
8
|
+
REDIRECT_STATUS = [301, 302].freeze
|
9
|
+
|
10
|
+
def initialize(app)
|
11
|
+
@app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Called by the middleware runner.
|
16
|
+
#
|
17
|
+
# @param env [Namira::Env] The request environment
|
18
|
+
def call(env)
|
19
|
+
@app.call(env)
|
20
|
+
rescue Errors::HTTPError => e
|
21
|
+
if redirect?(e, env)
|
22
|
+
handle_redirect(env, e)
|
23
|
+
else
|
24
|
+
raise e
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def handle_redirect(env, e)
|
31
|
+
count = env.redirect_count
|
32
|
+
redirect_count_error(env) if count >= max_redirect(env)
|
33
|
+
location = e.response.headers['Location']
|
34
|
+
redirect_location_error(env) if location.nil?
|
35
|
+
env.uri = Addressable::URI.parse(location)
|
36
|
+
env.redirect_count += 1
|
37
|
+
call(env)
|
38
|
+
end
|
39
|
+
|
40
|
+
def max_redirect(env)
|
41
|
+
env.config[:max_redirect] || 3
|
42
|
+
end
|
43
|
+
|
44
|
+
def redirect_count_error(env)
|
45
|
+
raise Errors::RedirectError.new(
|
46
|
+
"Max number of redirects #{env.redirect_count} for #{env.uri}",
|
47
|
+
env.uri.to_s,
|
48
|
+
env.redirect_count
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def redirect_location_error(env)
|
53
|
+
raise Errors::RedirectError.new(
|
54
|
+
'Request redirected but no location was supplied',
|
55
|
+
nil,
|
56
|
+
env.redirect_count
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
def redirect?(e, env)
|
61
|
+
return false unless env.config[:follow_redirect].nil? ? true : env.config[:follow_redirect]
|
62
|
+
REDIRECT_STATUS.include?(e.status)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Namira
|
2
|
+
module Middleware
|
3
|
+
##
|
4
|
+
# Builds the {Namira::Response} from the backend responses
|
5
|
+
class Responder
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Called by the middleware runner.
|
12
|
+
#
|
13
|
+
# @param env [Namira::Env] The request environment
|
14
|
+
def call(env)
|
15
|
+
handle_response(env.response)
|
16
|
+
env.response = Namira::Response.new(env.response)
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def handle_response(response)
|
23
|
+
final = Namira::Response.new(response)
|
24
|
+
if (200...300).cover?(response.status)
|
25
|
+
final
|
26
|
+
else
|
27
|
+
raise Errors::HTTPError.new("http_error/#{response.status}", response.status, final)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Namira
|
2
|
+
module Middleware
|
3
|
+
##
|
4
|
+
# Handles timeout errors
|
5
|
+
class Timeout
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Called by the middleware runner.
|
12
|
+
#
|
13
|
+
# @param env [Namira::Env] The request environment
|
14
|
+
def call(env)
|
15
|
+
@app.call(env)
|
16
|
+
rescue HTTP::TimeoutError => e
|
17
|
+
raise Errors::TimeoutError.new(e.message)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Namira
|
2
|
+
module Middleware
|
3
|
+
##
|
4
|
+
# Records timing for the request
|
5
|
+
class Timing
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Called by the middleware runner.
|
12
|
+
#
|
13
|
+
# @param env [Namira::Env] The request environment
|
14
|
+
def call(env)
|
15
|
+
start_time = Time.now
|
16
|
+
result = @app.call(env)
|
17
|
+
result.timing = Time.now - start_time
|
18
|
+
result
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/namira/request.rb
CHANGED
@@ -15,19 +15,14 @@ module Namira
|
|
15
15
|
# @param http_method [Symbol] The HTTP method for the request. (Default `:get`)
|
16
16
|
# @param headers [Hash] Additional headers to send with the request. (Default: `{}`)
|
17
17
|
# @param body [String, #to_s] The body to send. (Default: nil)
|
18
|
-
# @param auth [Namira::Auth::Base] The auth instance used to sign requests.
|
19
18
|
# @param config [Hash] {Namira::Config} overrides
|
20
|
-
def initialize(uri:, http_method: :get, headers: {}, body: nil,
|
21
|
-
@uri
|
22
|
-
@http_method
|
23
|
-
@headers
|
24
|
-
@body
|
25
|
-
@
|
26
|
-
@
|
27
|
-
@max_redirect = config[:max_redirect] || Namira.configure.max_redirect
|
28
|
-
@backend = config[:backend] || Namira.configure.backend || Namira::Backend
|
29
|
-
@user_agent = config[:user_agent] || Namira.configure.user_agent
|
30
|
-
@max_redirect = Backend::NO_FOLLOW_REDIRECT_COUNT if config[:follow_redirect] == false
|
19
|
+
def initialize(uri:, http_method: :get, headers: {}, body: nil, config: {})
|
20
|
+
@uri = uri
|
21
|
+
@http_method = http_method
|
22
|
+
@headers = Hash(headers)
|
23
|
+
@body = body
|
24
|
+
@config = Namira.configure.to_h.merge(Hash(config))
|
25
|
+
@stack = Namira::Stack.default
|
31
26
|
end
|
32
27
|
|
33
28
|
##
|
@@ -35,7 +30,7 @@ module Namira
|
|
35
30
|
#
|
36
31
|
# Every time this method is called a network request will be sent.
|
37
32
|
def send_request
|
38
|
-
@response = _send_request
|
33
|
+
@response = _send_request
|
39
34
|
end
|
40
35
|
|
41
36
|
##
|
@@ -51,29 +46,20 @@ module Namira
|
|
51
46
|
|
52
47
|
private
|
53
48
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
headers[k] = v
|
63
|
-
end
|
64
|
-
end
|
49
|
+
def env
|
50
|
+
Namira::Env.new(
|
51
|
+
uri: @uri,
|
52
|
+
method: @http_method,
|
53
|
+
body: @body,
|
54
|
+
headers: @headers,
|
55
|
+
config: @config
|
56
|
+
)
|
65
57
|
end
|
66
58
|
|
67
|
-
def _send_request
|
68
|
-
@
|
69
|
-
|
70
|
-
|
71
|
-
headers: build_headers,
|
72
|
-
max_redirect: @max_redirect,
|
73
|
-
timeout: @timeout,
|
74
|
-
body: @body,
|
75
|
-
auth: @auth
|
76
|
-
)
|
59
|
+
def _send_request
|
60
|
+
@stack.call(env).response
|
61
|
+
rescue Addressable::URI::InvalidURIError => e
|
62
|
+
raise Namira::Errors::InvalidURIError.new(e.message)
|
77
63
|
end
|
78
64
|
end
|
79
65
|
end
|
data/lib/namira/stack.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Namira
|
2
|
+
##
|
3
|
+
# The middleware stack used to send a request
|
4
|
+
class Stack
|
5
|
+
class << self
|
6
|
+
##
|
7
|
+
# The default middleware stack
|
8
|
+
def default
|
9
|
+
Stack.new do
|
10
|
+
use Middleware::Config
|
11
|
+
use Middleware::Header
|
12
|
+
use Middleware::Timing
|
13
|
+
use Middleware::Redirector
|
14
|
+
use Middleware::Logger
|
15
|
+
use Middleware::Timeout
|
16
|
+
use Middleware::Network
|
17
|
+
use Middleware::Responder
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(&block)
|
23
|
+
@middleware = []
|
24
|
+
instance_eval(&block)
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Called by the middleware runner.
|
29
|
+
#
|
30
|
+
# @param env [Namira::Env] The request environment
|
31
|
+
def call(env)
|
32
|
+
raise ArgumentError, 'Invalid environment' unless env.is_a?(Namira::Env)
|
33
|
+
to_app.call(env)
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Add a class to the middleware stack
|
38
|
+
#
|
39
|
+
# @param klass [Class, #call] The middleware class
|
40
|
+
# @param args [Any] Arguments passed to the class initializer
|
41
|
+
# @param block [Block] A block to pass to the class initializer
|
42
|
+
def use(klass, *args, &block)
|
43
|
+
@middleware << lambda do |app|
|
44
|
+
klass.new(app, *args, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def to_app
|
51
|
+
application = ->(env) { env }
|
52
|
+
@middleware.reverse.inject(application) do |app, component|
|
53
|
+
component.call(app)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/namira/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: namira
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Skylar Schipper
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -148,20 +148,27 @@ files:
|
|
148
148
|
- bin/console
|
149
149
|
- bin/setup
|
150
150
|
- lib/namira.rb
|
151
|
-
- lib/namira/auth.rb
|
152
|
-
- lib/namira/auth/base.rb
|
153
|
-
- lib/namira/auth/http_basic.rb
|
154
|
-
- lib/namira/backend.rb
|
155
151
|
- lib/namira/config.rb
|
152
|
+
- lib/namira/env.rb
|
156
153
|
- lib/namira/errors.rb
|
157
154
|
- lib/namira/errors/base_error.rb
|
158
155
|
- lib/namira/errors/http_error.rb
|
159
156
|
- lib/namira/errors/invalid_uri_error.rb
|
160
157
|
- lib/namira/errors/redirect_error.rb
|
161
158
|
- lib/namira/errors/timeout_error.rb
|
159
|
+
- lib/namira/middleware.rb
|
160
|
+
- lib/namira/middleware/config.rb
|
161
|
+
- lib/namira/middleware/header.rb
|
162
|
+
- lib/namira/middleware/logger.rb
|
163
|
+
- lib/namira/middleware/network.rb
|
164
|
+
- lib/namira/middleware/redirector.rb
|
165
|
+
- lib/namira/middleware/responder.rb
|
166
|
+
- lib/namira/middleware/timeout.rb
|
167
|
+
- lib/namira/middleware/timing.rb
|
162
168
|
- lib/namira/query_builder.rb
|
163
169
|
- lib/namira/request.rb
|
164
170
|
- lib/namira/response.rb
|
171
|
+
- lib/namira/stack.rb
|
165
172
|
- lib/namira/version.rb
|
166
173
|
- namira.gemspec
|
167
174
|
homepage: https://github.com/skylarsch/namira
|
data/lib/namira/auth.rb
DELETED
data/lib/namira/auth/base.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Namira
|
2
|
-
##
|
3
|
-
# Authentication
|
4
|
-
module Auth
|
5
|
-
##
|
6
|
-
# The base authentication class
|
7
|
-
class Base
|
8
|
-
attr_accessor :sign_redirects
|
9
|
-
|
10
|
-
def sign_redirects?
|
11
|
-
if @sign_redirects.nil?
|
12
|
-
true
|
13
|
-
else
|
14
|
-
@sign_redirects == true
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
##
|
19
|
-
# @private
|
20
|
-
#
|
21
|
-
# Signs a request.
|
22
|
-
#
|
23
|
-
# @param backend [HTTP] The request being signed
|
24
|
-
# @param redirect_count [Integer] The number of redirects this request has encountered
|
25
|
-
def sign_request(backend, redirect_count)
|
26
|
-
return if redirect_count > 0 && !sign_redirects?
|
27
|
-
sign(backend)
|
28
|
-
end
|
29
|
-
|
30
|
-
##
|
31
|
-
# Perform the signing of the request
|
32
|
-
#
|
33
|
-
# @param backend [HTTP] The instance of the backend request to sign.
|
34
|
-
def sign(_backend)
|
35
|
-
raise NotImplementedError, 'Auth should override the `sign` method'
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Namira
|
2
|
-
module Auth
|
3
|
-
##
|
4
|
-
# Signs a HTTP request with HTTP basic authentication
|
5
|
-
class HTTPBasic < Base
|
6
|
-
attr_reader :user, :pass
|
7
|
-
|
8
|
-
##
|
9
|
-
# Create a new instance
|
10
|
-
#
|
11
|
-
# @param user [String] The username
|
12
|
-
# @param pass [String] The password
|
13
|
-
def initialize(user:, pass:)
|
14
|
-
@user = user
|
15
|
-
@pass = pass
|
16
|
-
end
|
17
|
-
|
18
|
-
##
|
19
|
-
# Signs the request
|
20
|
-
def sign(request)
|
21
|
-
request.basic_auth(user: user, pass: pass)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/namira/backend.rb
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
module Namira
|
2
|
-
##
|
3
|
-
# The backend is responsible for sending the requests.
|
4
|
-
#
|
5
|
-
# Namira uses HTTP Gem as its default backend. You can create your own backend and override `.send_request` to
|
6
|
-
# use a different network stack.
|
7
|
-
#
|
8
|
-
# Namira.config do |c|
|
9
|
-
# c.backend = CustomBackend
|
10
|
-
# end
|
11
|
-
#
|
12
|
-
# A fully compatable backend should handle redirects, respecting the max_redirect parameter as well as
|
13
|
-
# throwing a Errors::HTTPError for anything but a redirect & 2xx status code.
|
14
|
-
class Backend
|
15
|
-
##
|
16
|
-
# This allows anyone to substitute in their own networking stack.
|
17
|
-
#
|
18
|
-
# Any class that implements this method and resturns a `Namira::Response` object can be a fully qualified backend.
|
19
|
-
#
|
20
|
-
# @param uri [String] The URI to fetch
|
21
|
-
# @param method [Symbol] The HTTP method to use, expressed as a Symbol i.e. `:get`
|
22
|
-
# @param headers [Hash] The full HTTP headers to send from the request expressed as a Hash
|
23
|
-
# @param max_redirect [Integer] The maximum number of redirects to follow. Passed from the Request
|
24
|
-
# @param timeout [Integer] The number of seconds before a timeout should occure
|
25
|
-
# @param auth [Namira::Auth::Base] The `Namira::Auth::Base` subclass instance or nil to sign the request with
|
26
|
-
#
|
27
|
-
# @return [Namira::Response] The HTTP response
|
28
|
-
def self.send_request(uri:, method:, headers:, max_redirect:, timeout:, body:, auth:)
|
29
|
-
Backend.new(
|
30
|
-
uri: uri,
|
31
|
-
method: method,
|
32
|
-
headers: headers,
|
33
|
-
max_redirect: max_redirect,
|
34
|
-
timeout: timeout,
|
35
|
-
body: body,
|
36
|
-
auth: auth
|
37
|
-
).execute
|
38
|
-
end
|
39
|
-
|
40
|
-
##
|
41
|
-
# The default max redirects to consider the request a "no follow"
|
42
|
-
NO_FOLLOW_REDIRECT_COUNT = -1
|
43
|
-
|
44
|
-
##
|
45
|
-
# @private
|
46
|
-
def initialize(opts = {})
|
47
|
-
opts.each do |key, value|
|
48
|
-
instance_variable_set("@#{key}", value)
|
49
|
-
end
|
50
|
-
@redirect_count = 0
|
51
|
-
end
|
52
|
-
|
53
|
-
##
|
54
|
-
# @private
|
55
|
-
#
|
56
|
-
# Perform the request
|
57
|
-
def execute(location = nil)
|
58
|
-
ensure_redirect_count!(location)
|
59
|
-
prepare_request
|
60
|
-
sign_request_if_needed
|
61
|
-
send_request(location || @uri)
|
62
|
-
handle_response
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
|
-
|
67
|
-
def ensure_redirect_count!(location)
|
68
|
-
return if @redirect_count.zero?
|
69
|
-
return if @redirect_count <= @max_redirect
|
70
|
-
raise Errors::RedirectError.new(
|
71
|
-
"Max number of redirects #{@redirect_count} for #{@uri}",
|
72
|
-
location,
|
73
|
-
@redirect_count
|
74
|
-
)
|
75
|
-
end
|
76
|
-
|
77
|
-
def prepare_request
|
78
|
-
@http = HTTP.timeout(
|
79
|
-
:per_operation,
|
80
|
-
write: @timeout,
|
81
|
-
connect: @timeout,
|
82
|
-
read: @timeout
|
83
|
-
).headers(@headers)
|
84
|
-
end
|
85
|
-
|
86
|
-
def log_request(method, uri)
|
87
|
-
return unless Namira.configure.log_requests
|
88
|
-
if defined?(::Rails)
|
89
|
-
Rails.logger.debug "#{method.to_s.upcase} - #{uri}"
|
90
|
-
else
|
91
|
-
STDOUT.puts "#{method.to_s.upcase} - #{uri}"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def send_request(location)
|
96
|
-
log_request(@method, location)
|
97
|
-
@response = @http.send(@method, location, body: @body)
|
98
|
-
rescue HTTP::TimeoutError => e
|
99
|
-
raise Namira::Errors::TimeoutError.new(e.message)
|
100
|
-
rescue Addressable::URI::InvalidURIError => e
|
101
|
-
raise Namira::Errors::InvalidURIError.new(e.message)
|
102
|
-
end
|
103
|
-
|
104
|
-
def sign_request_if_needed
|
105
|
-
@http = @auth.sign_request(@http, @redirect_count) unless @auth.nil?
|
106
|
-
end
|
107
|
-
|
108
|
-
def handle_response
|
109
|
-
case @response.status
|
110
|
-
when 200..299
|
111
|
-
create_response
|
112
|
-
when 301, 302
|
113
|
-
handle_redirect
|
114
|
-
else
|
115
|
-
create_error_response
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def create_response
|
120
|
-
Namira::Response.new(@response)
|
121
|
-
end
|
122
|
-
|
123
|
-
def create_error_response
|
124
|
-
raise Errors::HTTPError.new("http_error/#{@response.status}", @response.status, create_response)
|
125
|
-
end
|
126
|
-
|
127
|
-
def handle_redirect
|
128
|
-
if @max_redirect == NO_FOLLOW_REDIRECT_COUNT
|
129
|
-
create_error_response
|
130
|
-
else
|
131
|
-
@redirect_count += 1
|
132
|
-
location = @response.headers['Location']
|
133
|
-
raise Errors::RedirectError.new('Request redirected but no location was supplied', nil, @redirect_count) if location.nil?
|
134
|
-
execute(location)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|