api_proxy 0.1.3 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -5
- data/lib/api_proxy.rb +3 -2
- data/lib/api_proxy/config.rb +4 -8
- data/lib/api_proxy/headers_filter.rb +22 -0
- data/lib/api_proxy/middleware.rb +4 -13
- data/lib/api_proxy/response_builder.rb +56 -0
- data/lib/api_proxy/signed_request.rb +49 -0
- data/lib/api_proxy/version.rb +1 -1
- metadata +5 -4
- data/lib/api_proxy/request.rb +0 -40
- data/lib/api_proxy/request_options_builder.rb +0 -73
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d1ac2a1d2b57c66377b1e28d0ae1ab5c0cceff203eae7d23f089df9f5a4b1e2
|
4
|
+
data.tar.gz: 5d03d9c8643879f8d145b63c5704f37e96e9e78564e3b74944edf7f74c9f650a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfded3b838256acfa4ac94f12ff4d437992accc9fa0bae0248fe5891d366a810d91b585188ba3aeaeaaa58abb4982c97e1b33753fadc66466b71cbd75186d09d
|
7
|
+
data.tar.gz: '08ae6bbb9c9ee7c71929dca3a3b944bdf32ff972a91d379ed86e86f842bd075dd323294fe355eff22958c499e61ea44542fa56e35644aa77b83dcabb1163e559'
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -31,11 +31,7 @@ ApiProxy.configure(:my_namespace) do |config|
|
|
31
31
|
config.api_key = ENV['SERVICE_API_KEY']
|
32
32
|
config.api_secret = ENV['SERVICE_API_SECRET']
|
33
33
|
|
34
|
-
config.
|
35
|
-
config.api_host = 'localhost'
|
36
|
-
config.api_port = 3000
|
37
|
-
|
38
|
-
config.api_prefix = '/api/v1/'
|
34
|
+
config.api_url = 'http://localhost:3002/api/v1'
|
39
35
|
|
40
36
|
config.request_starts_with = '/_some_key'
|
41
37
|
end
|
data/lib/api_proxy.rb
CHANGED
@@ -8,8 +8,9 @@ require 'active_support/core_ext/module'
|
|
8
8
|
module ApiProxy
|
9
9
|
autoload :Config, 'api_proxy/config'
|
10
10
|
autoload :Middleware, 'api_proxy/middleware'
|
11
|
-
autoload :
|
12
|
-
autoload :
|
11
|
+
autoload :HeadersFilter, 'api_proxy/headers_filter'
|
12
|
+
autoload :SignedRequest, 'api_proxy/signed_request'
|
13
|
+
autoload :ResponseBuilder, 'api_proxy/response_builder'
|
13
14
|
|
14
15
|
def self.configuration(namespace)
|
15
16
|
@configuration ||= {}
|
data/lib/api_proxy/config.rb
CHANGED
@@ -4,10 +4,7 @@ module ApiProxy
|
|
4
4
|
class Config
|
5
5
|
attr_accessor :api_key,
|
6
6
|
:api_secret,
|
7
|
-
:
|
8
|
-
:api_host,
|
9
|
-
:api_port,
|
10
|
-
:api_prefix,
|
7
|
+
:api_url,
|
11
8
|
:request_starts_with,
|
12
9
|
:request_allowed,
|
13
10
|
:custom_headers,
|
@@ -17,15 +14,14 @@ module ApiProxy
|
|
17
14
|
load_defaults
|
18
15
|
end
|
19
16
|
|
17
|
+
private
|
18
|
+
|
20
19
|
def load_defaults
|
21
20
|
@api_key = 'key'
|
22
21
|
@api_secret = 'secret'
|
23
22
|
|
24
|
-
@
|
25
|
-
@api_host = 'localhost'
|
26
|
-
@api_port = 3000
|
23
|
+
@api_url = 'http://localhost:3000/api/v1'
|
27
24
|
|
28
|
-
@api_prefix = '/api/v1/'
|
29
25
|
@request_starts_with = '/_ts'
|
30
26
|
|
31
27
|
@request_allowed = ->(_env) { true }
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiProxy
|
4
|
+
class HeadersFilter
|
5
|
+
ALLOWED_HEADERS = [
|
6
|
+
'content-type',
|
7
|
+
'etag',
|
8
|
+
'cache-control',
|
9
|
+
'content-length',
|
10
|
+
'content-disposition',
|
11
|
+
'content-transfer-encoding'
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
def initialize(headers)
|
15
|
+
@headers = headers
|
16
|
+
end
|
17
|
+
|
18
|
+
def filter
|
19
|
+
@headers.select { |key, _value| ALLOWED_HEADERS.include?(key) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/api_proxy/middleware.rb
CHANGED
@@ -4,24 +4,15 @@ module ApiProxy
|
|
4
4
|
class Middleware
|
5
5
|
def initialize(app, namespace = :default)
|
6
6
|
@app = app
|
7
|
-
@
|
7
|
+
@namespace = namespace
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(env)
|
11
|
-
|
11
|
+
builder = ApiProxy::ResponseBuilder.new(env, @namespace)
|
12
12
|
|
13
|
-
|
14
|
-
request = ApiProxy::Request.new(builder)
|
13
|
+
return @app.call(env) unless builder.allow_request?
|
15
14
|
|
16
|
-
response
|
17
|
-
|
18
|
-
Rack::Response.new(response.to_s, response.code, request.headers)
|
19
|
-
end
|
20
|
-
|
21
|
-
def allow_request?(env)
|
22
|
-
return false unless env['REQUEST_PATH'].start_with?(@config.request_starts_with)
|
23
|
-
|
24
|
-
@config.request_allowed.call(env)
|
15
|
+
builder.response
|
25
16
|
end
|
26
17
|
end
|
27
18
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rack'
|
4
|
+
|
5
|
+
module ApiProxy
|
6
|
+
class ResponseBuilder
|
7
|
+
attr_reader :env, :namespace, :config
|
8
|
+
|
9
|
+
def initialize(env, namespace = :default)
|
10
|
+
@env = env
|
11
|
+
@namespace = namespace
|
12
|
+
@config = ApiProxy.configuration(namespace)
|
13
|
+
end
|
14
|
+
|
15
|
+
def allow_request?
|
16
|
+
return false unless request.path.start_with?(config.request_starts_with)
|
17
|
+
|
18
|
+
config.request_allowed.call(@env)
|
19
|
+
end
|
20
|
+
|
21
|
+
def response
|
22
|
+
Rack::Response.new(
|
23
|
+
result.to_s,
|
24
|
+
result.code,
|
25
|
+
ApiProxy::HeadersFilter.new(result.headers).filter
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def request
|
32
|
+
@request ||= Rack::Request.new(@env)
|
33
|
+
end
|
34
|
+
|
35
|
+
def result
|
36
|
+
@result ||= ApiProxy::SignedRequest.new(request.request_method, url, options).perform
|
37
|
+
end
|
38
|
+
|
39
|
+
def url
|
40
|
+
path = request.path.gsub(config.request_starts_with, '')
|
41
|
+
File.join(config.api_url.to_s, path)
|
42
|
+
end
|
43
|
+
|
44
|
+
def options
|
45
|
+
{ namespace: namespace, body: filtered_params, headers: headers }
|
46
|
+
end
|
47
|
+
|
48
|
+
def filtered_params
|
49
|
+
request.params.reject { |key, _value| config.reject_params.include?(key.to_s) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def headers
|
53
|
+
config.custom_headers.call(env)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
require 'api_signature'
|
5
|
+
|
6
|
+
module ApiProxy
|
7
|
+
class SignedRequest
|
8
|
+
include ::HTTParty
|
9
|
+
|
10
|
+
attr_reader :request_method, :url, :options
|
11
|
+
|
12
|
+
def initialize(request_method, url, options = {})
|
13
|
+
@request_method = request_method.to_s.downcase
|
14
|
+
@url = URI.parse(url)
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def perform
|
19
|
+
self.class.send(request_method, url, headers: headers, body: body, format: :json)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def headers
|
25
|
+
(options[:headers] || {}).merge(signature_headers)
|
26
|
+
end
|
27
|
+
|
28
|
+
def body
|
29
|
+
options[:body]
|
30
|
+
end
|
31
|
+
|
32
|
+
def signature_headers
|
33
|
+
ApiSignature::Builder.new(signature_options).headers
|
34
|
+
end
|
35
|
+
|
36
|
+
def signature_options
|
37
|
+
{
|
38
|
+
access_key: config.api_key,
|
39
|
+
secret: config.api_secret,
|
40
|
+
request_method: request_method,
|
41
|
+
path: url.path
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def config
|
46
|
+
ApiProxy.configuration(options[:namespace]) || :default
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/api_proxy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api_proxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Malinovskiy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -215,9 +215,10 @@ files:
|
|
215
215
|
- bin/setup
|
216
216
|
- lib/api_proxy.rb
|
217
217
|
- lib/api_proxy/config.rb
|
218
|
+
- lib/api_proxy/headers_filter.rb
|
218
219
|
- lib/api_proxy/middleware.rb
|
219
|
-
- lib/api_proxy/
|
220
|
-
- lib/api_proxy/
|
220
|
+
- lib/api_proxy/response_builder.rb
|
221
|
+
- lib/api_proxy/signed_request.rb
|
221
222
|
- lib/api_proxy/version.rb
|
222
223
|
homepage: https://github.com/psyipm/api_proxy
|
223
224
|
licenses:
|
data/lib/api_proxy/request.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'httparty'
|
4
|
-
|
5
|
-
module ApiProxy
|
6
|
-
class Request
|
7
|
-
include ::HTTParty
|
8
|
-
|
9
|
-
attr_reader :builder
|
10
|
-
|
11
|
-
delegate :url, :options, :request_method, to: :builder
|
12
|
-
|
13
|
-
ALLOWED_HEADERS = [
|
14
|
-
'content-type',
|
15
|
-
'etag',
|
16
|
-
'cache-control',
|
17
|
-
'content-length',
|
18
|
-
'content-disposition',
|
19
|
-
'content-transfer-encoding'
|
20
|
-
].freeze
|
21
|
-
|
22
|
-
def initialize(request_options_builder)
|
23
|
-
@builder = request_options_builder
|
24
|
-
end
|
25
|
-
|
26
|
-
def result
|
27
|
-
@result ||= perform_request
|
28
|
-
end
|
29
|
-
|
30
|
-
def headers
|
31
|
-
result.headers.select { |key, _value| ALLOWED_HEADERS.include?(key) }
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def perform_request
|
37
|
-
self.class.send(request_method, url, options)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'api_signature'
|
4
|
-
require 'rack'
|
5
|
-
|
6
|
-
module ApiProxy
|
7
|
-
class RequestOptionsBuilder
|
8
|
-
attr_reader :env, :config
|
9
|
-
|
10
|
-
delegate :api_key,
|
11
|
-
:api_secret,
|
12
|
-
:api_host,
|
13
|
-
:api_port,
|
14
|
-
:api_prefix,
|
15
|
-
:url_scheme,
|
16
|
-
:request_starts_with, to: :config
|
17
|
-
|
18
|
-
def initialize(env, config)
|
19
|
-
@env = env
|
20
|
-
@config = config
|
21
|
-
end
|
22
|
-
|
23
|
-
def options
|
24
|
-
{ headers: headers, body: body, format: :json }
|
25
|
-
end
|
26
|
-
|
27
|
-
def url
|
28
|
-
URI::Generic.build(scheme: url_scheme, host: api_host, port: api_port, path: path)
|
29
|
-
end
|
30
|
-
|
31
|
-
def request_method
|
32
|
-
request.request_method.downcase
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def body
|
38
|
-
request.params.reject { |key, _value| config.reject_params.include?(key) }
|
39
|
-
end
|
40
|
-
|
41
|
-
def request
|
42
|
-
@request ||= Rack::Request.new(env)
|
43
|
-
end
|
44
|
-
|
45
|
-
def headers
|
46
|
-
custom_headers = config.custom_headers.call(env)
|
47
|
-
|
48
|
-
signature_builder.headers.merge(custom_headers)
|
49
|
-
end
|
50
|
-
|
51
|
-
def signature_builder
|
52
|
-
@signature_builder ||= ApiSignature::Builder.new(request_params)
|
53
|
-
end
|
54
|
-
|
55
|
-
def request_params
|
56
|
-
{
|
57
|
-
access_key: api_key,
|
58
|
-
secret: api_secret,
|
59
|
-
request_method: request_method,
|
60
|
-
scheme: url_scheme,
|
61
|
-
host: api_host,
|
62
|
-
port: api_port,
|
63
|
-
path: path
|
64
|
-
}
|
65
|
-
end
|
66
|
-
|
67
|
-
def path
|
68
|
-
request_path = request.path.gsub(request_starts_with, '')
|
69
|
-
|
70
|
-
File.join(api_prefix, request_path)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|