grape-middleware-logger 1.7.1 → 1.8.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
  SHA1:
3
- metadata.gz: c09e5c24a2fe69018c3193eae50e2ce2f9879600
4
- data.tar.gz: 6e728c86c74a64debb9071909edcb7dc93e72273
3
+ metadata.gz: d7c3e7ac5229767e264e6037c0a1af92946af940
4
+ data.tar.gz: b471c789e7ad5107630deea636a10594f623da02
5
5
  SHA512:
6
- metadata.gz: c9a08f38acf72a89882737bb91194a2b74c266d68c3b005bd24712aa42b0ade41c41cda9c88db027ca6653936a590e536b4f00bba7844d22fa61a1b5ac83836d
7
- data.tar.gz: 2c0f0bb9dc3093a01adc33152de30235985541e6d59bfb32756b98286d922e204158500d4645546aebc279f463478e5244cc2b4dbef2b3e70f0e93c768a483b6
6
+ metadata.gz: 85a21c6f2dd2c0376eb2db6968683e2444a75dfe982206450c707fdade2a2327811eddaca6aba516c64f01c86b26b5ae1115b4cc575930105192ea768113d423
7
+ data.tar.gz: 3d4510679704050630b392f1246843a37885fac14cd56621b527bfb27490e5a6439e0cf198ed7b966ade5cf76a7a7639fa15718b83fefa134012f13c39cebd62
@@ -1,3 +1,7 @@
1
+ 1.8.0 (4/22/2017)
2
+ ==================
3
+ * [#17] Add a `:headers` option, which can be either `:all` or an array of strings. (Thanks [@yamamotok](https://github.com/yamamotok))
4
+
1
5
  1.7.1 (11/1/2016)
2
6
  ==================
3
7
  * Log the error class name (https://github.com/ridiculous/grape-middleware-logger/pull/13)
data/README.md CHANGED
@@ -53,13 +53,17 @@ The middleware logger can be customized with the following options:
53
53
 
54
54
  * The `:logger` option can be any object that responds to `.info(String)`
55
55
  * The `:filter` option can be any object that responds to `.filter(Hash)` and returns a hash.
56
+ * The `:headers` option can be either `:all` or array of strings.
57
+ + If `:all`, all request headers will be output.
58
+ + If array, output will be filtered by names in the array. (case-insensitive)
56
59
 
57
60
  For example:
58
61
 
59
62
  ```ruby
60
63
  insert_after Grape::Middleware::Formatter, Grape::Middleware::Logger, {
61
64
  logger: Logger.new(STDERR),
62
- filter: Class.new { def filter(opts) opts.reject { |k, _| k.to_s == 'password' } end }.new
65
+ filter: Class.new { def filter(opts) opts.reject { |k, _| k.to_s == 'password' } end }.new,
66
+ headers: %w(version cache-control)
63
67
  }
64
68
  ```
65
69
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'grape-middleware-logger'
5
- spec.version = '1.7.1'
5
+ spec.version = '1.8.0'
6
6
  spec.platform = Gem::Platform::RUBY
7
7
  spec.authors = ['Ryan Buckley']
8
8
  spec.email = ['arebuckley@gmail.com']
@@ -7,7 +7,7 @@ class Grape::Middleware::Logger < Grape::Middleware::Globals
7
7
  attr_reader :logger
8
8
 
9
9
  class << self
10
- attr_accessor :logger, :filter
10
+ attr_accessor :logger, :filter, :headers
11
11
 
12
12
  def default_logger
13
13
  default = Logger.new(STDOUT)
@@ -19,6 +19,7 @@ class Grape::Middleware::Logger < Grape::Middleware::Globals
19
19
  def initialize(_, options = {})
20
20
  super
21
21
  @options[:filter] ||= self.class.filter
22
+ @options[:headers] ||= self.class.headers
22
23
  @logger = options[:logger] || self.class.logger || self.class.default_logger
23
24
  end
24
25
 
@@ -34,6 +35,7 @@ class Grape::Middleware::Logger < Grape::Middleware::Globals
34
35
  ]
35
36
  logger.info %Q(Processing by #{processed_by})
36
37
  logger.info %Q( Parameters: #{parameters})
38
+ logger.info %Q( Headers: #{headers}) if @options[:headers]
37
39
  end
38
40
 
39
41
  # @note Error and exception handling are required for the +after+ hooks
@@ -91,6 +93,18 @@ class Grape::Middleware::Logger < Grape::Middleware::Globals
91
93
  end
92
94
  end
93
95
 
96
+ def headers
97
+ request_headers = env[Grape::Env::GRAPE_REQUEST_HEADERS].to_hash
98
+ return Hash[request_headers.sort] if @options[:headers] == :all
99
+
100
+ headers_needed = Array(@options[:headers])
101
+ result = {}
102
+ headers_needed.each do |need|
103
+ result.merge!(request_headers.select { |key, value| need.to_s.casecmp(key).zero? })
104
+ end
105
+ Hash[result.sort]
106
+ end
107
+
94
108
  def start_time
95
109
  @start_time ||= Time.now
96
110
  end
@@ -32,8 +32,10 @@ FactoryGirl.define do
32
32
  grape_request { build :grape_request }
33
33
  grape_endpoint { build(:grape_endpoint) }
34
34
  params { grape_request.params }
35
+ headers { grape_request.headers }
35
36
  post_params { { 'secret' => 'key', 'customer' => [] } }
36
37
  rails_post_params { { 'name' => 'foo', 'password' => 'access' } }
38
+ other_env_params { {} }
37
39
 
38
40
  initialize_with do
39
41
  new.merge(
@@ -42,10 +44,21 @@ FactoryGirl.define do
42
44
  'action_dispatch.request.request_parameters' => rails_post_params,
43
45
  Grape::Env::GRAPE_REQUEST => grape_request,
44
46
  Grape::Env::GRAPE_REQUEST_PARAMS => params,
47
+ Grape::Env::GRAPE_REQUEST_HEADERS => headers,
45
48
  Grape::Env::RACK_REQUEST_FORM_HASH => post_params,
46
49
  Grape::Env::API_ENDPOINT => grape_endpoint
47
- )
50
+ ).merge(other_env_params)
48
51
  end
52
+
53
+ trait :prefixed_basic_headers do
54
+ other_env_params { {
55
+ 'HTTP_VERSION' => 'HTTP/1.1',
56
+ 'HTTP_CACHE_CONTROL' => 'max-age=0',
57
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0',
58
+ 'HTTP_ACCEPT_LANGUAGE' => 'en-US'
59
+ } }
60
+ end
61
+
49
62
  end
50
63
 
51
64
  factory :grape_endpoint, class: Grape::Endpoint do
@@ -84,9 +97,20 @@ FactoryGirl.define do
84
97
  end
85
98
 
86
99
  factory :grape_request, class: OpenStruct do
100
+ headers { {} }
101
+
87
102
  initialize_with {
88
- new(request_method: 'POST', path: '/api/1.0/users', headers: {}, params: { 'id' => '101001' })
103
+ new(request_method: 'POST', path: '/api/1.0/users', headers: headers, params: { 'id' => '101001' })
89
104
  }
105
+
106
+ trait :basic_headers do
107
+ headers { {
108
+ 'Version' => 'HTTP/1.1',
109
+ 'Cache-Control' => 'max-age=0',
110
+ 'User-Agent' => 'Mozilla/5.0',
111
+ 'Accept-Language' => 'en-US'
112
+ } }
113
+ end
90
114
  end
91
115
 
92
116
  factory :app do
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Middleware::Logger, type: :integration do
4
+ let(:app) { build :app }
5
+
6
+ subject { described_class.new(app, options) }
7
+
8
+ let(:grape_endpoint) { build(:grape_endpoint) }
9
+ let(:env) { build(:expected_env, :prefixed_basic_headers, grape_endpoint: grape_endpoint) }
10
+
11
+ context ':all option is set to option headers' do
12
+ let(:options) { {
13
+ filter: build(:param_filter),
14
+ headers: :all,
15
+ logger: Logger.new(Tempfile.new('logger'))
16
+ } }
17
+ it 'all headers will be shown, headers will be sorted by name' do
18
+ expect(subject.logger).to receive(:info).with ''
19
+ expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
20
+ expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI/users)
21
+ expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "secret"=>"[FILTERED]", "customer"=>[], "name"=>"foo", "password"=>"[FILTERED]"})
22
+ expect(subject.logger).to receive(:info).with %Q( Headers: {"Accept-Language"=>"en-US", "Cache-Control"=>"max-age=0", "User-Agent"=>"Mozilla/5.0", "Version"=>"HTTP/1.1"})
23
+ expect(subject.logger).to receive(:info).with /Completed 200 in \d+.\d+ms/
24
+ expect(subject.logger).to receive(:info).with ''
25
+ subject.call!(env)
26
+ end
27
+ end
28
+
29
+ context 'list of names ["User-Agent", "Cache-Control"] is set to option headers' do
30
+ let(:options) { {
31
+ filter: build(:param_filter),
32
+ headers: %w(User-Agent Cache-Control),
33
+ logger: Logger.new(Tempfile.new('logger'))
34
+ } }
35
+ it 'two headers will be shown' do
36
+ expect(subject.logger).to receive(:info).with ''
37
+ expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
38
+ expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI/users)
39
+ expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "secret"=>"[FILTERED]", "customer"=>[], "name"=>"foo", "password"=>"[FILTERED]"})
40
+ expect(subject.logger).to receive(:info).with %Q( Headers: {"Cache-Control"=>"max-age=0", "User-Agent"=>"Mozilla/5.0"})
41
+ expect(subject.logger).to receive(:info).with /Completed 200 in \d+.\d+ms/
42
+ expect(subject.logger).to receive(:info).with ''
43
+ subject.call!(env)
44
+ end
45
+ end
46
+
47
+ context 'a single string "Cache-Control" is set to option headers' do
48
+ let(:options) { {
49
+ filter: build(:param_filter),
50
+ headers: 'Cache-Control',
51
+ logger: Logger.new(Tempfile.new('logger'))
52
+ } }
53
+ it 'only Cache-Control header will be shown' do
54
+ expect(subject.logger).to receive(:info).with ''
55
+ expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
56
+ expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI/users)
57
+ expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "secret"=>"[FILTERED]", "customer"=>[], "name"=>"foo", "password"=>"[FILTERED]"})
58
+ expect(subject.logger).to receive(:info).with %Q( Headers: {"Cache-Control"=>"max-age=0"})
59
+ expect(subject.logger).to receive(:info).with /Completed 200 in \d+.\d+ms/
60
+ expect(subject.logger).to receive(:info).with ''
61
+ subject.call!(env)
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Middleware::Logger do
4
+ let(:app) { double('app') }
5
+
6
+ subject { described_class.new(app, options) }
7
+
8
+ describe '#headers' do
9
+ let(:grape_request) { build :grape_request, :basic_headers }
10
+ let(:env) { build :expected_env, grape_request: grape_request }
11
+
12
+ before { subject.instance_variable_set(:@env, env) }
13
+
14
+ context 'when @options[:headers] has a symbol :all' do
15
+ let(:options) { { headers: :all, logger: Object.new } }
16
+ it 'all request headers should be retrieved' do
17
+ expect(subject.headers.fetch('Accept-Language')).to eq('en-US')
18
+ expect(subject.headers.fetch('Cache-Control')).to eq('max-age=0')
19
+ expect(subject.headers.fetch('User-Agent')).to eq('Mozilla/5.0')
20
+ expect(subject.headers.fetch('Version')).to eq('HTTP/1.1')
21
+ end
22
+ end
23
+
24
+ context 'when @options[:headers] is a string "user-agent"' do
25
+ let(:options) { { headers: 'user-agent', logger: Object.new } }
26
+ it 'only "User-Agent" should be retrieved' do
27
+ expect(subject.headers.fetch('User-Agent')).to eq('Mozilla/5.0')
28
+ expect(subject.headers.length).to eq(1)
29
+ end
30
+ end
31
+
32
+ context 'when @options[:headers] is an array of ["user-agent", "Cache-Control", "Unknown"]' do
33
+ let(:options) { { headers: %w(user-agent Cache-Control Unknown), logger: Object.new } }
34
+ it '"User-Agent" and "Cache-Control" should be retrieved' do
35
+ expect(subject.headers.fetch('Cache-Control')).to eq('max-age=0')
36
+ expect(subject.headers.fetch('User-Agent')).to eq('Mozilla/5.0')
37
+ end
38
+ it '"Unknown" name does not make any effect' do
39
+ expect(subject.headers.length).to eq(2)
40
+ end
41
+ end
42
+ end
43
+
44
+ describe '#headers if no request header' do
45
+ let(:env) { build :expected_env }
46
+ before { subject.instance_variable_set(:@env, env) }
47
+
48
+ context 'when @options[:headers] is set, but no request header is there' do
49
+ let(:options) { { headers: %w(user-agent Cache-Control), logger: Object.new } }
50
+ it 'subject.headers should return empty hash' do
51
+ expect(subject.headers.length).to eq(0)
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-middleware-logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Buckley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-02 00:00:00.000000000 Z
11
+ date: 2017-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grape
@@ -112,8 +112,10 @@ files:
112
112
  - lib/grape/middleware/logger/railtie.rb
113
113
  - spec/factories.rb
114
114
  - spec/fixtures/rails_app.rb
115
+ - spec/integration/lib/grape/middleware/headers_option_spec.rb
115
116
  - spec/integration/lib/grape/middleware/logger_spec.rb
116
117
  - spec/integration_rails/lib/grape/middleware/logger_spec.rb
118
+ - spec/lib/grape/middleware/headers_option_spec.rb
117
119
  - spec/lib/grape/middleware/logger_spec.rb
118
120
  - spec/rails_helper.rb
119
121
  - spec/spec_helper.rb
@@ -146,8 +148,10 @@ summary: A logger for the Grape framework
146
148
  test_files:
147
149
  - spec/factories.rb
148
150
  - spec/fixtures/rails_app.rb
151
+ - spec/integration/lib/grape/middleware/headers_option_spec.rb
149
152
  - spec/integration/lib/grape/middleware/logger_spec.rb
150
153
  - spec/integration_rails/lib/grape/middleware/logger_spec.rb
154
+ - spec/lib/grape/middleware/headers_option_spec.rb
151
155
  - spec/lib/grape/middleware/logger_spec.rb
152
156
  - spec/rails_helper.rb
153
157
  - spec/spec_helper.rb