api_valve 0.0.1.beta.1 → 0.0.1.beta.2

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: 0db44e3a1e246e94e9c31ad856fef01d7b76626cfe665bd18dfa769223c385bc
4
- data.tar.gz: 7a05b9b44d9606bb831da1709bacc50135115311d4517f87bdad59e17ea3340d
3
+ metadata.gz: 88db069feae42e9dc2fe3397891acfc31567a36b057a78c57d0a8ed2be567be7
4
+ data.tar.gz: 29aba6e067ae80f88effcde5d03d048eff6137c34b11376ae0dfba9a0b47669b
5
5
  SHA512:
6
- metadata.gz: d86f709762d7cd80fe4d1d01184310ae422e38dac84c9244a968ce52cae0ede75365975d8bd86b3fc9bdc5e9dd16d34ac1e94bf3f6129d97d662cabb13ac72d8
7
- data.tar.gz: a733954d49421ad1735f12c27b3361026c8a3f4d5378837090d5373dcfb75e8409adca6566b6d437cfb64d0512a8531b8de551a14cd65ed1c60771df4514e039
6
+ metadata.gz: 9c7d05c3e3788a426844ea4628c2fc8fa83def60bfba39e85f0138407c820ba81b942e947e3576e85d1fb27c62206698b6b60b517fdb08478cbeb202f541ab6f
7
+ data.tar.gz: 3c57ae3efe82c65ff552084300bc7b0aa494789490ed132689f0c48c91a4b0920c937767dd41564ad7e782578bdb92c567ae71e4a231de296dde1756261a7f75
@@ -39,7 +39,7 @@ module ApiValve
39
39
 
40
40
  def json_meta
41
41
  (@error.try(:to_hash).presence || {}).merge(
42
- backtrace: ApiValve.expose_backtraces ? json_backtrace : nil
42
+ backtrace: ApiValve.expose_backtraces ? @error.backtrace : nil
43
43
  ).compact.presence
44
44
  end
45
45
  end
@@ -18,6 +18,7 @@ module ApiValve
18
18
  X-Forwarded-Host
19
19
  X-Forwarded-Port
20
20
  X-Forwarded-Proto
21
+ X-Real-IP
21
22
  ).freeze
22
23
  NOT_PREFIXED_HEADERS = %w(
23
24
  Content-Length
@@ -0,0 +1,21 @@
1
+ require 'active_support/tagged_logging'
2
+ require 'logger'
3
+
4
+ module ApiValve
5
+ class Logger < ::Logger
6
+ include ActiveSupport::TaggedLogging
7
+
8
+ class Formatter < ActiveSupport::Logger::SimpleFormatter
9
+ include ActiveSupport::TaggedLogging::Formatter
10
+ end
11
+
12
+ def initialize(target = STDOUT)
13
+ super(target)
14
+ self.formatter = Formatter.new
15
+ end
16
+
17
+ # some rack apps have weird ways to write to rack.logger
18
+ alias puts error
19
+ alias write info
20
+ end
21
+ end
@@ -0,0 +1,127 @@
1
+ module ApiValve::Middleware
2
+ class Logging
3
+ include ActiveSupport::Configurable
4
+
5
+ class Log
6
+ INCOMING = %(Started %s "%s" for %s at %s).freeze
7
+ COMPLETE = %(Completed %s %s in %dms\n).freeze
8
+ URL_PARAMS = %(URL params %s).freeze
9
+ REQUEST_PAYLOAD = %(Request payload\n%s).freeze
10
+ REQUEST_HEADERS = %(Request HTTP Headers %s).freeze
11
+ RESPONSE_HEADERS = %(Response HTTP headers %s).freeze
12
+ RESPONSE_PAYLOAD = %(Response payload\n%s).freeze
13
+ NON_STANDARD_REQUEST_HEADERS = %w(CONTENT_LENGTH CONTENT_TYPE).freeze
14
+
15
+ attr_accessor :began_at, :env, :status, :response_headers, :response_payload
16
+
17
+ def initialize(options = {})
18
+ assign options
19
+ end
20
+
21
+ def assign(options = {})
22
+ options.each do |k, v|
23
+ public_send "#{k}=", v
24
+ end
25
+ end
26
+
27
+ def before_request
28
+ log_request
29
+ log_url_params
30
+ log_request_headers if Logging.log_request_headers
31
+ log_request_payload if Logging.log_request_payload
32
+ end
33
+
34
+ def after_request
35
+ log_response_headers if Logging.log_response_headers
36
+ log_response_payload if Logging.log_response_payload
37
+ log_response
38
+ end
39
+
40
+ private
41
+
42
+ delegate :logger, to: ApiValve
43
+
44
+ def log_request
45
+ logger.info INCOMING % [
46
+ env['REQUEST_METHOD'],
47
+ [env['PATH_INFO'], env['QUERY_STRING'].presence].compact.join('?'),
48
+ (env['HTTP_X_FORWARDED_FOR'] || env['REMOTE_ADDR']),
49
+ began_at.strftime('%Y-%m-%d %H:%M:%S %z')
50
+ ]
51
+ end
52
+
53
+ def log_url_params
54
+ return unless env['QUERY_STRING'].present?
55
+ logger.info URL_PARAMS % Rack::Utils.parse_nested_query(env['QUERY_STRING']).inspect
56
+ end
57
+
58
+ def log_request_headers
59
+ headers = {}
60
+ env.each_pair do |k, v|
61
+ next unless k =~ /^HTTP_/ && v.present?
62
+ next if v.blank? || (!k.start_with?('HTTP_') && !NON_STANDARD_REQUEST_HEADERS.include?(k))
63
+ headers[k] = v
64
+ end
65
+ return if headers.empty?
66
+ logger.debug REQUEST_HEADERS % headers
67
+ end
68
+
69
+ def log_request_payload
70
+ return unless %w(PATCH POST PUT).include? env['REQUEST_METHOD']
71
+ logger.debug REQUEST_PAYLOAD % env['rack.input'].read(1000)
72
+ env['rack.input'].rewind
73
+ end
74
+
75
+ def log_response_headers
76
+ return if response_headers&.empty?
77
+ logger.debug RESPONSE_HEADERS % response_headers.inspect
78
+ end
79
+
80
+ def log_response_payload
81
+ return if response_payload&.empty?
82
+ logger.debug RESPONSE_PAYLOAD % response_payload.first(config_log_body_size)
83
+ end
84
+
85
+ def log_response
86
+ logger.info COMPLETE % [
87
+ status,
88
+ Rack::Utils::HTTP_STATUS_CODES[status],
89
+ (Time.now - began_at) * 1000
90
+ ]
91
+ end
92
+ end
93
+
94
+ config_accessor :log_request_headers do
95
+ false
96
+ end
97
+
98
+ config_accessor :log_request_payload do
99
+ false
100
+ end
101
+
102
+ config_accessor :log_response_headers do
103
+ false
104
+ end
105
+
106
+ config_accessor :log_response_payload do
107
+ false
108
+ end
109
+
110
+ def initialize(app)
111
+ @app = app
112
+ end
113
+
114
+ def call(env)
115
+ env['rack.logger'] = ApiValve.logger
116
+ env['rack.errors'] = ApiValve.logger
117
+ ApiValve.logger.tagged(Thread.current[:request_id]) do
118
+ log = Log.new(began_at: Time.now, env: env)
119
+ log.before_request
120
+ status, headers, body = @app.call(env)
121
+ log.assign status: status, response_headers: headers, response_payload: body
122
+ log.after_request
123
+ [status, headers, body]
124
+ end
125
+ end
126
+ end
127
+ end
@@ -9,8 +9,8 @@ module ApiValve
9
9
  define_callbacks :call
10
10
 
11
11
  class << self
12
- def from_yaml(file_path)
13
- from_hash YAML.load_file(file_path)
12
+ def from_yaml(string)
13
+ from_hash YAML.load(string) # rubocop:disable Security/YAMLLoad
14
14
  end
15
15
 
16
16
  def from_hash(config)
data/lib/api_valve.rb CHANGED
@@ -16,6 +16,7 @@ module ApiValve
16
16
  autoload :Error, 'api_valve/error'
17
17
  autoload :ErrorResponder, 'api_valve/error_responder'
18
18
  autoload :Forwarder, 'api_valve/forwarder'
19
+ autoload :Logger, 'api_valve/logger'
19
20
  autoload :Proxy, 'api_valve/proxy'
20
21
  autoload :Router, 'api_valve/router'
21
22
 
@@ -23,6 +24,7 @@ module ApiValve
23
24
 
24
25
  module Middleware
25
26
  autoload :ErrorHandling, 'api_valve/middleware/error_handling'
27
+ autoload :Logging, 'api_valve/middleware/logging'
26
28
  end
27
29
 
28
30
  config_accessor :logger do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_valve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.beta.1
4
+ version: 0.0.1.beta.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - mkon
@@ -48,16 +48,16 @@ dependencies:
48
48
  name: multi_json
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - ">="
51
+ - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '0'
53
+ version: '1.13'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - ">="
58
+ - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '0'
60
+ version: '1.13'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rack
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -186,7 +186,9 @@ files:
186
186
  - lib/api_valve/forwarder/permission_handler.rb
187
187
  - lib/api_valve/forwarder/request.rb
188
188
  - lib/api_valve/forwarder/response.rb
189
+ - lib/api_valve/logger.rb
189
190
  - lib/api_valve/middleware/error_handling.rb
191
+ - lib/api_valve/middleware/logging.rb
190
192
  - lib/api_valve/proxy.rb
191
193
  - lib/api_valve/router.rb
192
194
  homepage: https://github.com/mkon/api_valve