api_proxy 0.1.3 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7234b39e258e9e2e84285f0cf39720cc43d6587b6f17db929da2150d46af931
4
- data.tar.gz: 2e695372d5b8ce3f211b4cbb6627bdd9fecb564d8e073ac74351a0f8512a23a0
3
+ metadata.gz: 1d1ac2a1d2b57c66377b1e28d0ae1ab5c0cceff203eae7d23f089df9f5a4b1e2
4
+ data.tar.gz: 5d03d9c8643879f8d145b63c5704f37e96e9e78564e3b74944edf7f74c9f650a
5
5
  SHA512:
6
- metadata.gz: 2ec33885e2e58f3d0d5fbc548d5950d40c4d52a435910862d9d723826d6e7e3ca1c4852b74a721a0228a170999154ec1eaa64d08136b6aa381a8fd94821f0c2d
7
- data.tar.gz: c210dc5eb556c7afad43face37d5a6fb204b010804ac27858ceb01bb5d1775300f630f92271aaea48277ac48d1d67188cba080818285ec9b3cf3e8634f8e2366
6
+ metadata.gz: dfded3b838256acfa4ac94f12ff4d437992accc9fa0bae0248fe5891d366a810d91b585188ba3aeaeaaa58abb4982c97e1b33753fadc66466b71cbd75186d09d
7
+ data.tar.gz: '08ae6bbb9c9ee7c71929dca3a3b944bdf32ff972a91d379ed86e86f842bd075dd323294fe355eff22958c499e61ea44542fa56e35644aa77b83dcabb1163e559'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- api_proxy (0.1.3)
4
+ api_proxy (0.2.3)
5
5
  activesupport (>= 4.0)
6
6
  api_signature (~> 0.1.2)
7
7
  httparty (>= 0.15)
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.url_scheme = 'http'
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
@@ -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 :RequestOptionsBuilder, 'api_proxy/request_options_builder'
12
- autoload :Request, 'api_proxy/request'
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 ||= {}
@@ -4,10 +4,7 @@ module ApiProxy
4
4
  class Config
5
5
  attr_accessor :api_key,
6
6
  :api_secret,
7
- :url_scheme,
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
- @url_scheme = 'http'
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
@@ -4,24 +4,15 @@ module ApiProxy
4
4
  class Middleware
5
5
  def initialize(app, namespace = :default)
6
6
  @app = app
7
- @config = ApiProxy.configuration(namespace)
7
+ @namespace = namespace
8
8
  end
9
9
 
10
10
  def call(env)
11
- return @app.call(env) unless allow_request?(env)
11
+ builder = ApiProxy::ResponseBuilder.new(env, @namespace)
12
12
 
13
- builder = RequestOptionsBuilder.new(env, @config)
14
- request = ApiProxy::Request.new(builder)
13
+ return @app.call(env) unless builder.allow_request?
15
14
 
16
- response = request.result
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ApiProxy
4
- VERSION = '0.1.3'
4
+ VERSION = '0.2.3'
5
5
  end
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.1.3
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-30 00:00:00.000000000 Z
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/request.rb
220
- - lib/api_proxy/request_options_builder.rb
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:
@@ -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