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 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