api_valve 0.7.2 → 1.0.0
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 +4 -4
- data/README.md +19 -1
- data/lib/api_valve.rb +2 -1
- data/lib/api_valve/error_responder.rb +1 -1
- data/lib/api_valve/forwarder.rb +3 -2
- data/lib/api_valve/forwarder/request.rb +8 -7
- data/lib/api_valve/logger.rb +1 -1
- data/lib/api_valve/middleware/permission_check.rb +1 -1
- data/lib/api_valve/proxy.rb +3 -3
- data/lib/api_valve/proxy/builder.rb +3 -4
- data/lib/api_valve/route_set.rb +21 -21
- metadata +23 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0e6669812fb7067607a8013b6080931d548f23df184bfd4f7a722d0a2ead98d
|
4
|
+
data.tar.gz: 241d1a7a8cac8aa6795418e3dbb54b016262eb476f3cfba5fdfece748ab204da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44e8eba0a335b9740b37cc189f3418358c42bb99245a614b6acf042201096fced3f3eb306814ccb2c628566cf80b78676339f4db47a4a7490476275f746c2013
|
7
|
+
data.tar.gz: d1d4909884073aafce0cbbd9d091d3613c84422d90db4911c4f6bb540c62eba6b80fb6a3a1a5365dedf9166e24db17b4721a8e31ddd9e81e0a516f58e5016df2
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# ApiValve
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/api_valve)
|
4
|
-
|
4
|
+

|
5
5
|
[](https://depfu.com/github/mkon/api_valve?project_id=5958)
|
6
6
|
|
7
7
|
Extensible rack application that serves as lightweight API reverse proxy.
|
@@ -18,3 +18,21 @@ gem 'api_valve'
|
|
18
18
|
|
19
19
|
See the [examples](https://github.com/mkon/api_valve/tree/master/examples) section on how to
|
20
20
|
create & configure your own proxy using this gem.
|
21
|
+
|
22
|
+
### Headers
|
23
|
+
|
24
|
+
By default the following headers are forwarded:
|
25
|
+
|
26
|
+
* `Accept`
|
27
|
+
* `Content-Type`
|
28
|
+
* `User-Agent`
|
29
|
+
* `X-Real-IP`
|
30
|
+
* `X-Request-Id`
|
31
|
+
|
32
|
+
Additionally these headers are generated:
|
33
|
+
|
34
|
+
* `X-Forwarded-For`: The ApiGateway is added to the list
|
35
|
+
* `X-Forwarded-Host`: Filled with original request host
|
36
|
+
* `X-Forwarded-Port`: Filled with original request port
|
37
|
+
* `X-Forwarded-Prefix`: Filled with the path prefix of the forwarder within the Api Gateway (eg `SCRIPT_NAME` env)
|
38
|
+
* `X-Forwarded-Proto`: Filled with original request scheme
|
data/lib/api_valve.rb
CHANGED
@@ -5,6 +5,7 @@ require 'active_support/core_ext/hash'
|
|
5
5
|
require 'active_support/core_ext/object'
|
6
6
|
require 'active_support/core_ext/module'
|
7
7
|
require 'active_support/json'
|
8
|
+
require 'active_support/notifications'
|
8
9
|
require 'active_support/rescuable'
|
9
10
|
require 'benchmark'
|
10
11
|
require 'faraday'
|
@@ -26,7 +27,7 @@ module ApiValve
|
|
26
27
|
include ActiveSupport::Configurable
|
27
28
|
|
28
29
|
config_accessor :logger do
|
29
|
-
Logger.new(
|
30
|
+
Logger.new($stdout)
|
30
31
|
end
|
31
32
|
|
32
33
|
config_accessor :error_responder do
|
data/lib/api_valve/forwarder.rb
CHANGED
@@ -69,7 +69,7 @@ module ApiValve
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def log_request(request)
|
72
|
-
ApiValve.logger.
|
72
|
+
ApiValve.logger.debug do
|
73
73
|
format(
|
74
74
|
'-> %<method>s %<endpoint>s%<path>s',
|
75
75
|
method: request.method.upcase,
|
@@ -80,7 +80,7 @@ module ApiValve
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def log_response(response, elapsed_time)
|
83
|
-
ApiValve.logger.
|
83
|
+
ApiValve.logger.debug do
|
84
84
|
format(
|
85
85
|
'<- %<status>s in %<ms>dms',
|
86
86
|
status: response.status,
|
@@ -94,6 +94,7 @@ module ApiValve
|
|
94
94
|
url: endpoint,
|
95
95
|
ssl: {verify: false}
|
96
96
|
) do |config|
|
97
|
+
config.request :instrumentation
|
97
98
|
config.adapter Faraday.default_adapter
|
98
99
|
end
|
99
100
|
end
|
@@ -76,18 +76,19 @@ module ApiValve
|
|
76
76
|
|
77
77
|
def forwarded_headers
|
78
78
|
{
|
79
|
-
'X-Forwarded-For'
|
80
|
-
'X-Forwarded-Host'
|
81
|
-
'X-Forwarded-Port'
|
82
|
-
'X-Forwarded-
|
83
|
-
|
79
|
+
'X-Forwarded-For' => x_forwarded_for,
|
80
|
+
'X-Forwarded-Host' => original_request.host,
|
81
|
+
'X-Forwarded-Port' => original_request.port.to_s,
|
82
|
+
'X-Forwarded-Prefix' => original_request.env['SCRIPT_NAME'].presence,
|
83
|
+
'X-Forwarded-Proto' => original_request.scheme
|
84
|
+
}.compact
|
84
85
|
end
|
85
86
|
|
86
87
|
def override_path(options)
|
87
88
|
return unless (path = options['path'])
|
88
|
-
return path unless options
|
89
|
+
return path unless options['match_data']
|
89
90
|
|
90
|
-
path % options
|
91
|
+
path % options['match_data'].named_captures.symbolize_keys
|
91
92
|
end
|
92
93
|
|
93
94
|
def x_forwarded_for
|
data/lib/api_valve/logger.rb
CHANGED
data/lib/api_valve/proxy.rb
CHANGED
@@ -34,9 +34,9 @@ module ApiValve
|
|
34
34
|
|
35
35
|
def forward(methods, path_regexp = nil, options = {})
|
36
36
|
options = options.with_indifferent_access
|
37
|
-
route_set.append(methods, path_regexp, options.except(:request)
|
37
|
+
route_set.append(methods, path_regexp, options.except(:request)) do |request, match_data|
|
38
38
|
forwarder.call request, {'match_data' => match_data}.merge(options[:request] || {}).with_indifferent_access
|
39
|
-
|
39
|
+
end
|
40
40
|
end
|
41
41
|
|
42
42
|
def forward_all(options = {})
|
@@ -44,7 +44,7 @@ module ApiValve
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def deny(methods, path_regexp = nil, with: 'Error::Forbidden')
|
47
|
-
route_set.append(methods, path_regexp, {}
|
47
|
+
route_set.append(methods, path_regexp, {}) { raise ApiValve.const_get(with) }
|
48
48
|
end
|
49
49
|
|
50
50
|
protected
|
@@ -1,10 +1,9 @@
|
|
1
1
|
module ApiValve
|
2
2
|
class Proxy
|
3
3
|
module Builder
|
4
|
-
# Creates
|
4
|
+
# Creates an instance from a config hash and takes optional block
|
5
5
|
# which is executed in scope of the proxy
|
6
|
-
def build(config)
|
7
|
-
block = Proc.new if block_given? # capture the yield
|
6
|
+
def build(config, &block)
|
8
7
|
from_hash(config).tap do |proxy|
|
9
8
|
proxy.instance_eval(&block) if block
|
10
9
|
end
|
@@ -16,7 +15,7 @@ module ApiValve
|
|
16
15
|
raise "Config not found for #{name.underscore}(.yml|.yml.erb) in #{ApiValve.config_paths.inspect}" unless path
|
17
16
|
|
18
17
|
yaml = File.read(path)
|
19
|
-
yaml = ERB.new(yaml,
|
18
|
+
yaml = ERB.new(yaml, trim_mode: '-').result if path.fnmatch? '*.erb'
|
20
19
|
from_yaml yaml
|
21
20
|
end
|
22
21
|
|
data/lib/api_valve/route_set.rb
CHANGED
@@ -32,54 +32,54 @@ module ApiValve
|
|
32
32
|
[route, match_data]
|
33
33
|
end
|
34
34
|
|
35
|
-
def delete(path = nil, options = {},
|
36
|
-
push :delete, path, options,
|
35
|
+
def delete(path = nil, options = {}, &block)
|
36
|
+
push :delete, path, options, &block
|
37
37
|
end
|
38
38
|
|
39
|
-
def get(path = nil, options = {},
|
40
|
-
push :get, path, options,
|
39
|
+
def get(path = nil, options = {}, &block)
|
40
|
+
push :get, path, options, &block
|
41
41
|
end
|
42
42
|
|
43
|
-
def head(path = nil, options = {},
|
44
|
-
push :head, path, options,
|
43
|
+
def head(path = nil, options = {}, &block)
|
44
|
+
push :head, path, options, &block
|
45
45
|
end
|
46
46
|
|
47
|
-
def patch(path = nil, options = {},
|
48
|
-
push :patch, path, options,
|
47
|
+
def patch(path = nil, options = {}, &block)
|
48
|
+
push :patch, path, options, &block
|
49
49
|
end
|
50
50
|
|
51
|
-
def post(path = nil, options = {},
|
52
|
-
push :post, path, options,
|
51
|
+
def post(path = nil, options = {}, &block)
|
52
|
+
push :post, path, options, &block
|
53
53
|
end
|
54
54
|
|
55
|
-
def put(path = nil, options = {},
|
56
|
-
push :put, path, options,
|
55
|
+
def put(path = nil, options = {}, &block)
|
56
|
+
push :put, path, options, &block
|
57
57
|
end
|
58
58
|
|
59
|
-
def any(path = nil, options = {},
|
60
|
-
append METHODS, path, options,
|
59
|
+
def any(path = nil, options = {}, &block)
|
60
|
+
append METHODS, path, options, &block
|
61
61
|
end
|
62
62
|
|
63
|
-
def push(methods, regexp, options = {},
|
64
|
-
add_route :push, methods, regexp, options,
|
63
|
+
def push(methods, regexp, options = {}, &block)
|
64
|
+
add_route :push, methods, regexp, options, &block
|
65
65
|
end
|
66
66
|
|
67
67
|
alias append push
|
68
68
|
|
69
|
-
def unshift(methods, regexp = nil, options = {},
|
70
|
-
add_route :unshift, methods, regexp, options,
|
69
|
+
def unshift(methods, regexp = nil, options = {}, &block)
|
70
|
+
add_route :unshift, methods, regexp, options, &block
|
71
71
|
end
|
72
72
|
|
73
73
|
def reset_routes
|
74
|
-
@routes =
|
74
|
+
@routes = METHODS.map { |v| [v, []] }.to_h.with_indifferent_access.freeze
|
75
75
|
end
|
76
76
|
|
77
77
|
private
|
78
78
|
|
79
|
-
def add_route(how, methods, regexp, options,
|
79
|
+
def add_route(how, methods, regexp, options, &block)
|
80
80
|
methods = METHODS if methods.to_s == 'any'
|
81
81
|
Array.wrap(methods).each do |method|
|
82
|
-
@routes[method].public_send how, Route.new(regexp, options,
|
82
|
+
@routes[method].public_send how, Route.new(regexp, options, block)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
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.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mkon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,34 +16,40 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5
|
19
|
+
version: '5'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 5
|
29
|
+
version: '5'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: faraday
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '0.14'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '2'
|
40
43
|
type: :runtime
|
41
44
|
prerelease: false
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
43
46
|
requirements:
|
44
|
-
- - "
|
47
|
+
- - ">="
|
45
48
|
- !ruby/object:Gem::Version
|
46
49
|
version: '0.14'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2'
|
47
53
|
- !ruby/object:Gem::Dependency
|
48
54
|
name: multi_json
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,28 +126,28 @@ dependencies:
|
|
120
126
|
requirements:
|
121
127
|
- - '='
|
122
128
|
- !ruby/object:Gem::Version
|
123
|
-
version:
|
129
|
+
version: 1.18.2
|
124
130
|
type: :development
|
125
131
|
prerelease: false
|
126
132
|
version_requirements: !ruby/object:Gem::Requirement
|
127
133
|
requirements:
|
128
134
|
- - '='
|
129
135
|
- !ruby/object:Gem::Version
|
130
|
-
version:
|
136
|
+
version: 1.18.2
|
131
137
|
- !ruby/object:Gem::Dependency
|
132
138
|
name: rubocop-rspec
|
133
139
|
requirement: !ruby/object:Gem::Requirement
|
134
140
|
requirements:
|
135
141
|
- - '='
|
136
142
|
- !ruby/object:Gem::Version
|
137
|
-
version:
|
143
|
+
version: 2.4.0
|
138
144
|
type: :development
|
139
145
|
prerelease: false
|
140
146
|
version_requirements: !ruby/object:Gem::Requirement
|
141
147
|
requirements:
|
142
148
|
- - '='
|
143
149
|
- !ruby/object:Gem::Version
|
144
|
-
version:
|
150
|
+
version: 2.4.0
|
145
151
|
- !ruby/object:Gem::Dependency
|
146
152
|
name: simplecov
|
147
153
|
requirement: !ruby/object:Gem::Requirement
|
@@ -223,14 +229,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
223
229
|
requirements:
|
224
230
|
- - ">="
|
225
231
|
- !ruby/object:Gem::Version
|
226
|
-
version: '
|
232
|
+
version: '2.6'
|
233
|
+
- - "<"
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
version: '3.1'
|
227
236
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
228
237
|
requirements:
|
229
238
|
- - ">="
|
230
239
|
- !ruby/object:Gem::Version
|
231
240
|
version: '0'
|
232
241
|
requirements: []
|
233
|
-
rubygems_version: 3.0.
|
242
|
+
rubygems_version: 3.0.3.1
|
234
243
|
signing_key:
|
235
244
|
specification_version: 4
|
236
245
|
summary: Lightweight ruby/rack API reverse proxy or gateway
|