api_valve 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd0650e0cecef4ec781e6e8a4386ad05573de8b79174d624c7b08af1dfef02bf
4
- data.tar.gz: a608b1470fdfa950fb23edf5bd05949cff1a3ebf1a89a100994c1f3119999213
3
+ metadata.gz: 4c5ecd7703186bfbcd52c8b50d3a643a5c2af56043e92f00e56b8b1863c38fb7
4
+ data.tar.gz: 95263987cdf177ce4703955572e28f4540a3c32f47fb7b519fd0233b79506160
5
5
  SHA512:
6
- metadata.gz: 62804cac7016ef7ec069e17ccc229fe25356de1702512de74b425de0a07331464a9067750d0243aa618cdab1100fcc96e05a5095c969e289c567d66adc8d914d
7
- data.tar.gz: e36dc22f1603317981cf07e372b0deb1a6c65b3ae18b15894a287adb78c7a682e3c90385566e455b7be1dc44d70d8117b6327b31b592d207b7dbc1b3dbd80130
6
+ metadata.gz: a43f1ff0ea8e795a1676bd918b9d849d2404a14793f6ccf93adac8b70c3aa672729822a1e6d516f38201ae3505023e3d0adc46c0a4257497c6c5aaa577bc97fe
7
+ data.tar.gz: 2db871a83ee2dc02b2639ba0e6c19a795f765e24421ef0aacc8ec2f4adbefd2b682d7746cb8c99cd0e976d5afe89af70abb87cb2680dbce92c9f45d6458ed467
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ApiValve
2
2
 
3
- Lightweight API reverse proxy written in ruby. Based on rack.
3
+ Extensible rack application that serves as lightweight API reverse proxy.
4
4
 
5
5
  ## Installation
6
6
 
@@ -10,5 +10,5 @@ Just add the gem
10
10
  gem 'api_valve'
11
11
  ```
12
12
 
13
- See the [examples](https://github.com/mkon/api_valve/tree/master/examples) section on how to create & configure your own
14
- proxy using this gem.
13
+ See the [examples](https://github.com/mkon/api_valve/tree/master/examples) section on how to
14
+ create & configure your own proxy using this gem.
@@ -12,12 +12,7 @@ module ApiValve
12
12
  WHITELISTED_HEADERS = %w(
13
13
  Accept
14
14
  Content-Type
15
- Forwarded
16
15
  User-Agent
17
- X-Forwarded-For
18
- X-Forwarded-Host
19
- X-Forwarded-Port
20
- X-Forwarded-Proto
21
16
  X-Real-IP
22
17
  ).freeze
23
18
  NOT_PREFIXED_HEADERS = %w(
@@ -58,7 +53,9 @@ module ApiValve
58
53
  def headers
59
54
  whitelisted_headers.each_with_object({}) do |key, h|
60
55
  h[key] = header(key)
61
- end.merge('X-Request-Id' => Thread.current[:request_id]).compact
56
+ end.merge(forwarded_headers).merge(
57
+ 'X-Request-Id' => Thread.current[:request_id]
58
+ ).compact
62
59
  end
63
60
 
64
61
  # Returns body to forward to the target endpoint
@@ -77,6 +74,21 @@ module ApiValve
77
74
 
78
75
  private
79
76
 
77
+ def forwarded_headers
78
+ {
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-Proto' => original_request.scheme
83
+ }
84
+ end
85
+
86
+ def x_forwarded_for
87
+ (
88
+ header('X-Forwarded-For').to_s.split(', ') << original_request.env['REMOTE_ADDR']
89
+ ).join(', ')
90
+ end
91
+
80
92
  def header(name)
81
93
  name = "HTTP_#{name}" unless NOT_PREFIXED_HEADERS.include? name
82
94
  name = name.upcase.tr('-', '_')
@@ -39,7 +39,11 @@ module ApiValve
39
39
 
40
40
  def headers
41
41
  whitelisted_headers.each_with_object({}) do |k, h|
42
- h[k] = original_response.headers[k]
42
+ if k == 'Location'
43
+ h[k] = adjust_location(original_response.headers[k])
44
+ else
45
+ h[k] = original_response.headers[k]
46
+ end
43
47
  end.compact
44
48
  end
45
49
 
@@ -47,6 +51,11 @@ module ApiValve
47
51
  @options[:whitelisted_headers] || WHITELISTED_HEADERS
48
52
  end
49
53
 
54
+ def adjust_location(location)
55
+ return location if @options[:target_prefix] == @options[:local_prefix]
56
+ location&.gsub(/^#{@options[:target_prefix]}/, @options[:local_prefix])
57
+ end
58
+
50
59
  def body
51
60
  original_response.body.to_s
52
61
  end
@@ -15,6 +15,8 @@ module ApiValve
15
15
  # response: Options for the response wrapper. See Response#new
16
16
  def initialize(options = {})
17
17
  @options = options.with_indifferent_access
18
+ uri = URI(options[:endpoint])
19
+ @target_prefix = uri.path
18
20
  end
19
21
 
20
22
  # Takes the original rack request with optional options and returns a rack response
@@ -23,7 +25,14 @@ module ApiValve
23
25
  def call(original_request, local_options = {})
24
26
  request = request_klass.new(original_request, request_options.deep_merge(local_options))
25
27
  raise Error::Forbidden unless request.allowed?
26
- response_klass.new(original_request, run_request(request), response_options).rack_response
28
+ response_klass.new(
29
+ original_request,
30
+ run_request(request),
31
+ response_options.merge(
32
+ target_prefix: @target_prefix,
33
+ local_prefix: original_request.env['SCRIPT_NAME']
34
+ )
35
+ ).rack_response
27
36
  end
28
37
 
29
38
  private
@@ -43,7 +52,8 @@ module ApiValve
43
52
 
44
53
  def response_options
45
54
  # integrate permission handler options as it is instantiated in the response
46
- (@options[:response] || {}).merge(@options.slice(:permission_handler) || {})
55
+ (@options[:response] || {})
56
+ .merge(@options.slice(:permission_handler) || {})
47
57
  end
48
58
 
49
59
  def run_request(request)
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.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mkon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-04 00:00:00.000000000 Z
11
+ date: 2018-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport