grape-middleware-logger 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 38faa42e694ac5c8b974975c8e5f8819c073c028
4
+ data.tar.gz: d5da71383af6b787ad2380e7d408ea3974553c4a
5
+ SHA512:
6
+ metadata.gz: 2ad87065915b6f9a6b932b7ac198434de5cda37b55812dadc716544c1eb346fb602d5e4be32a006516cc4cba1955e44d9b3543f1e711f905bff41452c777216e
7
+ data.tar.gz: cf6f37a8a9878aa7d677b401c1f7aac37cdc559fc572057d6f0fcdcd939d798358b94f10252516ddf225a37abb24dd8bc606f28c793f19757afef8cc7bbdee69
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in grape-middleware-logger.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Ryan Buckley
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # Grape::Middleware::Logger
2
+
3
+ Dead until brought to life with the release of Grape v0.12.0
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'grape-middleware-logger'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install grape-middleware-logger
20
+
21
+ ## Usage
22
+
23
+ class API < Grape::API
24
+ use Grape::Middleware::Logger
25
+ end
26
+
27
+ Using Grape with Rails? Add consistent logging and param filtering with
28
+
29
+ use Grape::Middleware::Logger, {
30
+ logger: Rails.logger,
31
+ filter: ActionDispatch::Http::ParameterFilter.new(Rails.application.config.filter_parameters)
32
+ }
33
+
34
+ ## Credits
35
+
36
+ Big thanks to jadent's question/answer on [stackoverflow](http://stackoverflow.com/questions/25048163/grape-using-error-and-grapemiddleware-after-callback)
37
+ for easily logging error responses. Borrowed some motivation from the [grape_logging](https://github.com/aserafin/grape_logging) gem
38
+ and would love to see these two consolidated at some point.
39
+
40
+ ## Contributing
41
+
42
+ 1. Fork it ( https://github.com/ridiculous/grape-middleware-logger/fork )
43
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
44
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
45
+ 4. Push to the branch (`git push origin my-new-feature`)
46
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'rspec/core/rake_task'
2
+ RSpec::Core::RakeTask.new(:spec) do |spec|
3
+ spec.pattern = 'spec/**/*_spec.rb'
4
+ end
5
+
6
+ desc 'Run specs'
7
+ task default: :spec
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'grape/middleware/logger'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'grape-middleware-logger'
8
+ spec.version = Grape::Middleware::Logger::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.authors = ['Ryan Buckley']
11
+ spec.email = ['arebuckley@gmail.com']
12
+ spec.summary = %q{Logging middleware for Grape apps}
13
+ spec.description = %q{Logging middleware for Grape apps, similar to what Rails offers}
14
+ spec.homepage = ''
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'grape'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec', '>= 3.0'
27
+ end
@@ -0,0 +1,7 @@
1
+ module Grape
2
+ module Middleware
3
+ class Logger
4
+ VERSION = '0.1.0'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,64 @@
1
+ require 'logger'
2
+ require 'grape/middleware/globals'
3
+
4
+ module Grape
5
+ module Middleware
6
+ class Logger < Grape::Middleware::Globals
7
+
8
+ #
9
+ # Overrides
10
+ #
11
+
12
+ def call!(env)
13
+ @env = env
14
+ _before
15
+ error = catch(:error) { @app_response = @app.call(@env); nil }
16
+ if error
17
+ after_failure(error)
18
+ throw(:error, error)
19
+ else
20
+ after(@app_response.first)
21
+ end
22
+ @app_response
23
+ end
24
+
25
+ def after(status)
26
+ logger.info "Completed #{status} in #{((Time.now - @start_time) * 1000).round(2)}ms"
27
+ logger.info ''
28
+ end
29
+
30
+ #
31
+ # Helpers
32
+ #
33
+
34
+ # @todo rename to +before+ when Grape v0.12.0 is released
35
+ def _before
36
+ @start_time = Time.now
37
+ logger.info ''
38
+ logger.info %Q(Started #{env['grape.request'].request_method} "#{env['grape.request'].path}")
39
+ logger.info %Q( Parameters: #{parameters})
40
+ end
41
+
42
+ def after_failure(error)
43
+ logger.info %Q( Error: #{error[:message]}) if error[:message]
44
+ after(error[:status])
45
+ end
46
+
47
+ def parameters
48
+ request_params = env['grape.request.params'].to_hash
49
+ request_params.merge!(env['action_dispatch.request.request_parameters'] || {})
50
+ if @options[:filter]
51
+ @options[:filter].filter(request_params)
52
+ else
53
+ request_params
54
+ end
55
+ end
56
+
57
+ def logger
58
+ @logger ||= @options[:logger] || ::Logger.new(STDOUT)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ require 'grape/middleware/logger/version'
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+ require 'grape/middleware/logger'
3
+
4
+ describe Grape::Middleware::Logger do
5
+ let(:app) { double('app') }
6
+ let(:options) { { filter: ParamFilter.new, logger: Object.new } }
7
+
8
+ subject { described_class.new(app, options) }
9
+
10
+ let(:app_response) { [200, {}, 'Hello World'] }
11
+ let(:env) {
12
+ {
13
+ 'grape.request' => OpenStruct.new(request_method: 'POST', path: '/api/1.0/users'),
14
+ 'grape.request.params' => {
15
+ 'id' => '101001'
16
+ },
17
+ 'action_dispatch.request.request_parameters' => {
18
+ 'name' => 'foo',
19
+ 'password' => 'access'
20
+ }
21
+ }
22
+ }
23
+ describe '#call!' do
24
+ context 'when calling the app results in an error response' do
25
+ let(:error) { { status: 400 } }
26
+
27
+ it 'calls +after_failure+ and rethrows the error' do
28
+ expect(app).to receive(:call).with(env).and_throw(:error, error)
29
+ expect(subject).to receive(:_before)
30
+ expect(subject).to receive(:after_failure).with(error)
31
+ expect(subject).to receive(:throw).with(:error, error)
32
+ subject.call!(env)
33
+ end
34
+ end
35
+
36
+ context 'when there is no error' do
37
+ it 'calls +after+ with the correct status' do
38
+ expect(app).to receive(:call).with(env).and_return(app_response)
39
+ expect(subject).to receive(:_before)
40
+ expect(subject).to receive(:after).with(200)
41
+ subject.call!(env)
42
+ end
43
+
44
+ it 'returns the @app_response' do
45
+ expect(app).to receive(:call).with(env).and_return(app_response)
46
+ allow(subject).to receive(:_before)
47
+ allow(subject).to receive(:after)
48
+ expect(subject.call!(env)).to eq app_response
49
+ end
50
+ end
51
+
52
+ describe 'integration' do
53
+ it 'properly logs requests' do
54
+ expect(app).to receive(:call).with(env).and_return(app_response)
55
+ expect(subject.logger).to receive(:info).with('')
56
+ expect(subject.logger).to receive(:info).with(%Q(Started POST "/api/1.0/users"))
57
+ expect(subject.logger).to receive(:info).with(%Q( Parameters: {"id"=>"101001", "name"=>"foo", "password"=>"[FILTERED]"}))
58
+ expect(subject.logger).to receive(:info).with(/Completed 200 in \d.\d+ms/)
59
+ expect(subject.logger).to receive(:info).with('')
60
+ subject.call!(env)
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#after_failure' do
66
+ let(:error) { { status: 403 } }
67
+
68
+ it 'calls +after+ with the :status' do
69
+ expect(subject).to receive(:after).with(403)
70
+ subject.after_failure(error)
71
+ end
72
+
73
+ context 'when :message is set in the error object' do
74
+ let(:error) { { message: 'Oops, not found' } }
75
+
76
+ it 'logs the error message' do
77
+ allow(subject).to receive(:after)
78
+ expect(subject.logger).to receive(:info).with(Regexp.new(error[:message]))
79
+ subject.after_failure(error)
80
+ end
81
+ end
82
+ end
83
+
84
+ describe '#parameters' do
85
+ before { subject.instance_variable_set(:@env, env) }
86
+
87
+ context 'when @options[:filter] is set' do
88
+ it 'calls +filter+ with the raw parameters' do
89
+ expect(subject.options[:filter]).to receive(:filter).with({ "id" => '101001', "name" => "foo", "password" => "access" })
90
+ subject.parameters
91
+ end
92
+
93
+ it 'returns the filtered results' do
94
+ expect(subject.parameters).to eq({ "id" => '101001', "name" => "foo", "password" => "[FILTERED]" })
95
+ end
96
+ end
97
+
98
+ context 'when @options[:filter] is nil' do
99
+ let(:options) { {} }
100
+
101
+ it 'returns the params extracted out of @env' do
102
+ expect(subject.parameters).to eq({ "id" => '101001', "name" => "foo", "password" => "access" })
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#logger' do
108
+ context 'when @options[:logger] is nil' do
109
+ let(:options) { {} }
110
+
111
+ it 'defaults to the the standard Logger' do
112
+ expect(subject.logger).to be_a(Logger)
113
+ end
114
+ end
115
+
116
+ context 'when @options[:logger] is set' do
117
+ it 'returns the logger object' do
118
+ expect(subject.logger).to eq options[:logger]
119
+ end
120
+ end
121
+ end
122
+
123
+ #
124
+ # Test class
125
+ #
126
+
127
+ ParamFilter = Class.new do
128
+ def filter(opts)
129
+ opts.each_pair { |key, val| val[0..-1] = '[FILTERED]' if key == 'password' }
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'ostruct'
5
+
6
+ RSpec.configure do |config|
7
+ config.raise_errors_for_deprecations!
8
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grape-middleware-logger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Buckley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: grape
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: Logging middleware for Grape apps, similar to what Rails offers
70
+ email:
71
+ - arebuckley@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - grape-middleware-logger.gemspec
82
+ - lib/grape/middleware/logger.rb
83
+ - lib/grape/middleware/logger/version.rb
84
+ - spec/lib/grape/middleware/logger_spec.rb
85
+ - spec/spec_helper.rb
86
+ homepage: ''
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.4.3
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Logging middleware for Grape apps
110
+ test_files:
111
+ - spec/lib/grape/middleware/logger_spec.rb
112
+ - spec/spec_helper.rb