api_valve 0.6.0 → 0.6.1

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: 2fdf08e3fa15d2bb46dc6f85ee53c681b696d574585b6be1e11dc7fc6b6527b1
4
- data.tar.gz: 3cf720502939fe562d385a7347e681927e79519446111410f6ba8c8f1ad7fb52
3
+ metadata.gz: 8f4cba9301dc5313a548d0d0be717b8bbc0af686c5da846bac838547e08dd8e3
4
+ data.tar.gz: 42d48117b5969d38f5125bfa4fbbde0633fbde1214b738de1efd607007cbb978
5
5
  SHA512:
6
- metadata.gz: 7e635bcd48b26f59cb92cd46551eb2b4de46fc23765a80c826c7f65993f52dfd232dceb4538586026c73a7d538a591aec96ffd681362c4f5ce1a3d9fbcf944a9
7
- data.tar.gz: 2543e426f0b25a9a3b0c1970f3e4dfc81e9d01ccc6147888438d28bff60dca3c9768f98b9e98c4aaf49b090206df93616632a1f559e0454511b8dd83e9953fe7
6
+ metadata.gz: 537cfb673ad5a8eeb6ec9f0871a0a85d6b61206326e0c9f0f4731414f341f60c45b595feab392f86ab4ea00c64819f83c3b7b98c2650a40e318e22bf1e812a64
7
+ data.tar.gz: f7e6538270b6d444c1bdf4b1fe06f9d86864c61ca1d9738201d21f9eb06c6349888e4141756ef5db7afdc63a9c427985a64d8d7c306d783d9740ad04d8934743
data/lib/api_valve.rb CHANGED
@@ -17,17 +17,14 @@ module ApiValve
17
17
  autoload :Error, 'api_valve/error'
18
18
  autoload :ErrorResponder, 'api_valve/error_responder'
19
19
  autoload :Forwarder, 'api_valve/forwarder'
20
+ autoload :Middleware, 'api_valve/middleware'
20
21
  autoload :Logger, 'api_valve/logger'
21
22
  autoload :Proxy, 'api_valve/proxy'
22
- autoload :Router, 'api_valve/router'
23
+ autoload :RouteSet, 'api_valve/route_set'
24
+ autoload :Runner, 'api_valve/runner'
23
25
 
24
26
  include ActiveSupport::Configurable
25
27
 
26
- module Middleware
27
- autoload :ErrorHandling, 'api_valve/middleware/error_handling'
28
- autoload :Logging, 'api_valve/middleware/logging'
29
- end
30
-
31
28
  config_accessor :logger do
32
29
  Logger.new(STDOUT)
33
30
  end
@@ -0,0 +1,43 @@
1
+ module ApiValve
2
+ class Middleware
3
+ autoload :ErrorHandling, 'api_valve/middleware/error_handling'
4
+ autoload :Logging, 'api_valve/middleware/logging'
5
+ autoload :Router, 'api_valve/middleware/router'
6
+
7
+ Item = Struct.new(:klass, :proc)
8
+
9
+ def initialize
10
+ @registry = []
11
+ end
12
+
13
+ def insert_after(other, middleware, *args, &block)
14
+ @registry.insert position(other) + 1, to_item(middleware, *args, &block)
15
+ end
16
+
17
+ def insert_before(other, middleware, *args, &block)
18
+ @registry.insert position(other), to_item(middleware, *args, &block)
19
+ end
20
+
21
+ def to_app(root_app)
22
+ @registry.reverse.inject(root_app) { |memo, obj| obj.proc.call memo }
23
+ end
24
+
25
+ def to_s
26
+ @registry.map(&:klass).join("\n")
27
+ end
28
+
29
+ def use(middleware, *args, &block)
30
+ @registry << to_item(middleware, *args, &block)
31
+ end
32
+
33
+ private
34
+
35
+ def position(klass)
36
+ @registry.index { |item| item.klass == klass }
37
+ end
38
+
39
+ def to_item(middleware, *args, &block)
40
+ Item.new(middleware, proc { |app| middleware.new(app, *args, &block) })
41
+ end
42
+ end
43
+ end
@@ -1,23 +1,21 @@
1
- module ApiValve
2
- module Middleware
3
- class ErrorHandling
4
- def initialize(app)
5
- @app = app
6
- end
1
+ class ApiValve::Middleware
2
+ class ErrorHandling
3
+ def initialize(app)
4
+ @app = app
5
+ end
7
6
 
8
- def call(env)
9
- @app.call(env)
10
- rescue Exception => e # rubocop:disable Lint/RescueException
11
- log_error e
12
- self.class.const_get(ApiValve.error_responder).new(e).call
13
- end
7
+ def call(env)
8
+ @app.call(env)
9
+ rescue Exception => e # rubocop:disable Lint/RescueException
10
+ log_error e
11
+ self.class.const_get(ApiValve.error_responder).new(e).call
12
+ end
14
13
 
15
- private
14
+ private
16
15
 
17
- def log_error(error)
18
- ApiValve.logger.error { "#{error.class}: #{error.message}" }
19
- ApiValve.logger.error { error.backtrace.join("\n") }
20
- end
16
+ def log_error(error)
17
+ ApiValve.logger.error { "#{error.class}: #{error.message}" }
18
+ ApiValve.logger.error { error.backtrace.join("\n") }
21
19
  end
22
20
  end
23
21
  end
@@ -1,4 +1,4 @@
1
- module ApiValve::Middleware
1
+ class ApiValve::Middleware
2
2
  class Logging
3
3
  include ActiveSupport::Configurable
4
4
 
@@ -0,0 +1,15 @@
1
+ class ApiValve::Middleware
2
+ class Router
3
+ def initialize(app, routeset)
4
+ @app = app
5
+ @routeset = routeset
6
+ end
7
+
8
+ def call(env)
9
+ route, match_data = @routeset.match env
10
+ env['api_valve.router.route'] = route
11
+ env['api_valve.router.match_data'] = match_data
12
+ @app.call(env)
13
+ end
14
+ end
15
+ end
@@ -64,22 +64,25 @@ module ApiValve
64
64
  end
65
65
  end
66
66
 
67
- attr_reader :request, :forwarder, :router
67
+ attr_reader :request, :forwarder, :middleware, :route_set
68
+
69
+ alias router route_set
68
70
 
69
71
  def initialize(forwarder)
70
72
  @forwarder = forwarder
71
- @router = Router.new
72
- @middlewares = []
73
+ @route_set = RouteSet.new
74
+ @middleware = Middleware.new
75
+ use Middleware::Router, route_set
73
76
  end
74
77
 
75
78
  def call(env)
76
- stack = @middlewares.reverse.inject(@router) { |a, e| e.call a }
77
- stack.call(env)
79
+ to_app.call(env)
78
80
  rescue ApiValve::Error::Client, ApiValve::Error::Server => e
79
81
  render_error e
80
82
  end
81
83
 
82
- delegate :add_route, to: :router
84
+ delegate :add_route, to: :route_set
85
+ delegate :use, to: :middleware
83
86
 
84
87
  def build_routes_from_config(routes_config)
85
88
  return forward_all unless routes_config
@@ -97,32 +100,32 @@ module ApiValve
97
100
 
98
101
  def forward(methods, path_regexp = nil, request_override = {})
99
102
  Array.wrap(methods).each do |method|
100
- router.public_send(method, path_regexp, proc { |request, match_data|
103
+ route_set.public_send(method, path_regexp, proc { |request, match_data|
101
104
  forwarder.call request, {'match_data' => match_data}.merge(request_override || {})
102
105
  })
103
106
  end
104
107
  end
105
108
 
106
109
  def forward_all
107
- router.any do |request, match_data|
110
+ route_set.any do |request, match_data|
108
111
  forwarder.call request, 'match_data' => match_data
109
112
  end
110
113
  end
111
114
 
112
115
  def deny(methods, path_regexp = nil, with: 'Error::Forbidden')
113
116
  Array.wrap(methods).each do |method|
114
- router.public_send(method, path_regexp, ->(*_args) { raise ApiValve.const_get(with) })
117
+ route_set.public_send(method, path_regexp, ->(*_args) { raise ApiValve.const_get(with) })
115
118
  end
116
119
  end
117
120
 
118
- def use(middleware, *args, &block)
119
- @middlewares << proc { |app| middleware.new(app, *args, &block) }
120
- end
121
-
122
121
  protected
123
122
 
124
123
  def render_error(error)
125
124
  self.class.const_get(ApiValve.error_responder).new(error).call
126
125
  end
126
+
127
+ def to_app
128
+ @to_app ||= @middleware.to_app(Runner.new)
129
+ end
127
130
  end
128
131
  end
@@ -1,5 +1,5 @@
1
1
  module ApiValve
2
- class Router
2
+ class RouteSet
3
3
  METHODS = %i(get post put patch delete head).freeze
4
4
 
5
5
  Route = Struct.new(:regexp, :block) do
@@ -16,8 +16,20 @@ module ApiValve
16
16
  reset_routes
17
17
  end
18
18
 
19
- def call(env)
20
- match Rack::Request.new(env)
19
+ def match(env)
20
+ request = Rack::Request.new(env)
21
+
22
+ # For security reasons do not allow URLs that could break out of the proxy namespace on the
23
+ # server. Preferably an nxing/apache rewrite will kill these URLs before they hit us
24
+ raise 'URL not supported' if request.path_info.include?('/../')
25
+
26
+ match_data = nil
27
+ route = @routes && @routes[request.request_method.downcase.to_sym].find do |r|
28
+ (match_data = r.match(request.path_info))
29
+ end
30
+ raise Error::NotRouted, 'Endpoint not found' unless route
31
+
32
+ [route, match_data]
21
33
  end
22
34
 
23
35
  def delete(path = nil, prok = nil)
@@ -65,20 +77,5 @@ module ApiValve
65
77
  def reset_routes
66
78
  @routes = Hash[METHODS.map { |v| [v, []] }].freeze
67
79
  end
68
-
69
- private
70
-
71
- def match(request)
72
- # For security reasons do not allow URLs that could break out of the proxy namespace on the
73
- # server. Preferably an nxing/apache rewrite will kill these URLs before they hit us
74
- raise 'URL not supported' if request.path_info.include?('/../')
75
-
76
- @routes && @routes[request.request_method.downcase.to_sym].each do |route|
77
- if (match_data = route.match(request.path_info))
78
- return route.call request, match_data
79
- end
80
- end
81
- raise Error::NotRouted, 'Endpoint not found'
82
- end
83
80
  end
84
81
  end
@@ -0,0 +1,9 @@
1
+ module ApiValve
2
+ class Runner
3
+ def call(env)
4
+ env['api_valve.router.route'].call \
5
+ Rack::Request.new(env),
6
+ env['api_valve.router.match_data']
7
+ end
8
+ end
9
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_valve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - mkon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-14 00:00:00.000000000 Z
11
+ date: 2018-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -202,10 +202,13 @@ files:
202
202
  - lib/api_valve/forwarder/request.rb
203
203
  - lib/api_valve/forwarder/response.rb
204
204
  - lib/api_valve/logger.rb
205
+ - lib/api_valve/middleware.rb
205
206
  - lib/api_valve/middleware/error_handling.rb
206
207
  - lib/api_valve/middleware/logging.rb
208
+ - lib/api_valve/middleware/router.rb
207
209
  - lib/api_valve/proxy.rb
208
- - lib/api_valve/router.rb
210
+ - lib/api_valve/route_set.rb
211
+ - lib/api_valve/runner.rb
209
212
  homepage: https://github.com/mkon/api_valve
210
213
  licenses:
211
214
  - MIT