api_valve 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/api_valve.rb +3 -6
- data/lib/api_valve/middleware.rb +43 -0
- data/lib/api_valve/middleware/error_handling.rb +15 -17
- data/lib/api_valve/middleware/logging.rb +1 -1
- data/lib/api_valve/middleware/router.rb +15 -0
- data/lib/api_valve/proxy.rb +16 -13
- data/lib/api_valve/{router.rb → route_set.rb} +15 -18
- data/lib/api_valve/runner.rb +9 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f4cba9301dc5313a548d0d0be717b8bbc0af686c5da846bac838547e08dd8e3
|
4
|
+
data.tar.gz: 42d48117b5969d38f5125bfa4fbbde0633fbde1214b738de1efd607007cbb978
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 :
|
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
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
1
|
+
class ApiValve::Middleware
|
2
|
+
class ErrorHandling
|
3
|
+
def initialize(app)
|
4
|
+
@app = app
|
5
|
+
end
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
14
|
+
private
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
@@ -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
|
data/lib/api_valve/proxy.rb
CHANGED
@@ -64,22 +64,25 @@ module ApiValve
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
attr_reader :request, :forwarder, :
|
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
|
-
@
|
72
|
-
@
|
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
|
-
|
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: :
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
20
|
-
|
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
|
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.
|
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-
|
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/
|
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
|