grape-middleware-lograge 1.0.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: dd7eb695c21bda678be84d2daf06a7eb2c964668
4
+ data.tar.gz: bee831a1a57cfcf2dd0291722f78bf29173b9486
5
+ SHA512:
6
+ metadata.gz: b37a71953c1d02595cecf6c45417e2e050ebcb4959411c320db4a1fbc1a3bb68ba73bbf4972164a75635d9e15fe95ba6600e733c0a7e0c16931da983f846ae9d
7
+ data.tar.gz: 61ff8930c61798b7ba78a22ac8140548b6d38656948f27901b65870d8c07a951fdff50d0bfce35685b1bc655c7080332980d293adc58b6fc0eb7612bc06b6b05
data/.gitignore ADDED
@@ -0,0 +1,17 @@
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
15
+ *.gem
16
+ .ruby-version
17
+ .ruby-gemset
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.2.1
5
+ - 2.2.2
6
+ - 2.2.3
7
+ before_install: gem install bundler -v 1.10.5
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in grape-middleware-logger.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rake'
8
+ gem "factory_girl", "~> 4.0"
9
+ gem "rails", "~> 4.2"
10
+ end
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,81 @@
1
+ # A logger for Grape apps
2
+ [![Code Climate](https://codeclimate.com/github/ridiculous/grape-middleware-logger/badges/gpa.svg)](https://codeclimate.com/github/ridiculous/grape-middleware-logger) [![Gem Version](https://badge.fury.io/rb/grape-middleware-logger.svg)](http://badge.fury.io/rb/grape-middleware-logger)
3
+ [![Build Status](https://travis-ci.org/ridiculous/grape-middleware-logger.svg)](https://travis-ci.org/ridiculous/grape-middleware-logger)
4
+
5
+ Logs:
6
+ * Request path
7
+ * Parameters
8
+ * Endpoint class name and handler
9
+ * Response status
10
+ * Duration of the request
11
+ * Exceptions
12
+ * Error responses from `error!`
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'grape', '>= 0.14.0'
20
+ gem 'grape-middleware-logger'
21
+ ```
22
+
23
+ ## Usage
24
+ ```ruby
25
+ class API < Grape::API
26
+ # @note Make sure this above you're first +mount+
27
+ use Grape::Middleware::Lograge
28
+ end
29
+ ```
30
+
31
+ Server requests will be logged to STDOUT by default.
32
+
33
+ ## Custom setup
34
+ Customize the logging by passing the `filter` option. Example using parameter sanitization:
35
+ ```ruby
36
+ use Grape::Middleware::Lograge, {
37
+ filter: CustomFilter.new
38
+ }
39
+ ```
40
+
41
+ The `filter` option can be any object that responds to `.filter(params_hash)`
42
+
43
+ ## Example output
44
+ Get
45
+ ```
46
+ Started GET "/v1/reports/101" at 2015-12-11 15:40:51 -0800
47
+ Processing by ReportsAPI#reports/:id
48
+ Parameters: {"id"=>"101"}
49
+ Completed 200 in 6.29ms
50
+ ```
51
+ Error
52
+ ```
53
+ Started POST "/v1/reports" at 2015-12-11 15:42:33 -0800
54
+ Processing by ReportsAPI#reports
55
+ Parameters: {"name"=>"foo", "password"=>"[FILTERED]"}
56
+ Error: {:error=>"undefined something something bad", :detail=>"Whoops"}
57
+ Completed 422 in 6.29ms
58
+ ```
59
+
60
+ ## Using Rails?
61
+ `Rails.application.config.filter_parameters` will be used automatically as the default param filterer.
62
+
63
+ ## Rack
64
+
65
+ If you're using the `rackup` command to run your server in development, pass the `-q` flag to silence the default rack logger.
66
+
67
+ ## Credits
68
+
69
+ This code is forked from [grape-middleware-logger](https://github.com/ridiculous/grape-middleware-logger).
70
+
71
+ Big thanks to jadent's question/answer on [stackoverflow](http://stackoverflow.com/questions/25048163/grape-using-error-and-grapemiddleware-after-callback)
72
+ for easily logging error responses. Borrowed some motivation from the [grape_logging](https://github.com/aserafin/grape_logging) gem
73
+ and would love to see these two consolidated at some point.
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it ( https://github.com/tchak/grape-middleware-lograge/fork )
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec) do |config|
4
+ config.pattern = 'spec/lib/**/*_spec.rb'
5
+ end
6
+
7
+ RSpec::Core::RakeTask.new(:integration) do |config|
8
+ config.pattern = 'spec/integration/**/*_spec.rb'
9
+ end
10
+
11
+ RSpec::Core::RakeTask.new(:integration_rails) do |config|
12
+ config.pattern = 'spec/integration_rails/**/*_spec.rb'
13
+ end
14
+
15
+ task default: [:spec, :integration, :integration_rails]
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'grape-middleware-lograge'
5
+ spec.version = '1.0.0'
6
+ spec.platform = Gem::Platform::RUBY
7
+ spec.authors = ['Ryan Buckley', 'Paul Chavard']
8
+ spec.email = ['arebuckley@gmail.com', 'paul+github@chavard.net']
9
+ spec.summary = %q{A logger for the Grape framework}
10
+ spec.description = %q{Logging middleware for the Grape framework, that uses Lograge}
11
+ spec.homepage = 'https://github.com/tchak/grape-middleware-lograge'
12
+ spec.license = 'MIT'
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.add_dependency 'grape', '>= 0.14', '< 1'
20
+ spec.add_dependency 'lograge', '~> 0.3'
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.7'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'rspec', '>= 3.2', '< 4'
25
+ end
@@ -0,0 +1,113 @@
1
+ require 'grape'
2
+
3
+ class Grape::Middleware::Lograge < Grape::Middleware::Globals
4
+ BACKSLASH = '/'.freeze
5
+
6
+ STATUS_CODE_TO_SYMBOL = Rack::Utils::SYMBOL_TO_STATUS_CODE.each_with_object({}) do |(symbol, status_code), hash|
7
+ hash[status_code] = symbol
8
+ end
9
+
10
+ class << self
11
+ attr_accessor :filter
12
+ end
13
+
14
+ def initialize(_, options = {})
15
+ super
16
+ @options[:filter] ||= self.class.filter
17
+ end
18
+
19
+ def before
20
+ super
21
+
22
+ ActiveSupport::Notifications.instrument("start_processing.grape", raw_payload)
23
+ end
24
+
25
+ # @note Error and exception handling are required for the +after+ hooks
26
+ # Exceptions are logged as a 500 status and re-raised
27
+ # Other "errors" are caught, logged and re-thrown
28
+ def call!(env)
29
+ @env = env
30
+
31
+ before
32
+
33
+ ActiveSupport::Notifications.instrument("process_action.grape", raw_payload) do |payload|
34
+ error = catch(:error) do
35
+ begin
36
+ @app_response = @app.call(@env)
37
+ rescue => e
38
+ after_exception(payload, e)
39
+ raise e
40
+ end
41
+
42
+ nil
43
+ end
44
+
45
+ if error
46
+ after_failure(payload, error)
47
+ throw(:error, error)
48
+ else
49
+ after(payload, response.status)
50
+ end
51
+
52
+ @app_response
53
+ end
54
+ end
55
+
56
+ def after(payload, status)
57
+ payload[:status] = status
58
+ payload[:format] = env['api.format']
59
+ payload[:version] = env['api.version']
60
+ end
61
+
62
+ def after_exception(payload, e)
63
+ class_name = e.class.name
64
+ status = e.respond_to?(:status) ? e.status : 500
65
+
66
+ payload[:exception] = [class_name, e.message]
67
+ payload[:backtrace] = e.backtrace
68
+
69
+ ActionDispatch::ExceptionWrapper.rescue_responses[class_name] = STATUS_CODE_TO_SYMBOL[status]
70
+ end
71
+
72
+ def after_failure(payload, error)
73
+ after(payload, error[:status])
74
+ end
75
+
76
+ def parameters
77
+ request_params = env[Grape::Env::GRAPE_REQUEST_PARAMS].to_hash
78
+ request_params.merge!(env['action_dispatch.request.request_parameters'.freeze] || {}) # for Rails
79
+ if @options[:filter]
80
+ @options[:filter].filter(request_params)
81
+ else
82
+ request_params
83
+ end
84
+ end
85
+
86
+ def raw_payload
87
+ {
88
+ params: parameters.merge(
89
+ 'action' => action_name || 'index',
90
+ 'controller' => controller
91
+ ),
92
+ method: env[Grape::Env::GRAPE_REQUEST].request_method,
93
+ path: env[Grape::Env::GRAPE_REQUEST].path,
94
+ user_agent: env['HTTP_USER_AGENT'],
95
+ request_id: env['action_dispatch.request_id'],
96
+ remote_ip: env['action_dispatch.remote_ip']
97
+ }
98
+ end
99
+
100
+ def endpoint
101
+ env[Grape::Env::API_ENDPOINT]
102
+ end
103
+
104
+ def controller
105
+ endpoint.options[:for].to_s
106
+ end
107
+
108
+ def action_name
109
+ endpoint.options[:path].map { |path| path.to_s.sub(BACKSLASH, '') }.join(BACKSLASH)
110
+ end
111
+ end
112
+
113
+ require_relative 'lograge/railtie' if defined?(Rails)
@@ -0,0 +1,8 @@
1
+ class Grape::Middleware::Lograge::Railtie < Rails::Railtie
2
+ initializer 'grape.middleware.lograge', after: :load_config_initializers do
3
+ Grape::Middleware::Lograge.filter = ActionDispatch::Http::ParameterFilter.new Rails.application.config.filter_parameters
4
+
5
+ require 'lograge'
6
+ ::Lograge::RequestLogSubscriber.attach_to :grape
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ module Lograge
2
+ module Formatters
3
+ class RailsLogger
4
+ INTERNAL_PARAMS = %w(controller action format _method only_path)
5
+
6
+ def call(data)
7
+ lines = start_processing(data)
8
+ lines << completed(data)
9
+
10
+ lines.join("\n")
11
+ end
12
+
13
+ def start_processing(data)
14
+ params = data[:params].except(*INTERNAL_PARAMS)
15
+ format = data[:format]
16
+ format = format.to_s.upcase if format.is_a?(Symbol)
17
+
18
+ lines = []
19
+
20
+ lines << "Processing by #{data[:controller]}##{data[:action]} as #{format}"
21
+ lines << " Parameters: #{params.inspect}" unless params.empty?
22
+
23
+ lines
24
+ end
25
+
26
+ def completed(data)
27
+ status = data[:status]
28
+
29
+ puts ActionDispatch::ExceptionWrapper.rescue_responses
30
+
31
+ if data[:error]
32
+ "Exception #{status} #{data[:error]} after #{data[:duration].round}ms"
33
+ else
34
+ "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{data[:duration].round}ms"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
data/spec/factories.rb ADDED
@@ -0,0 +1,90 @@
1
+ FactoryGirl.define do
2
+ class ExpectedEnv < Hash
3
+ attr_accessor :grape_request, :params, :post_params, :grape_endpoint
4
+ end
5
+
6
+ class ParamFilter
7
+ def filter(opts)
8
+ opts.each_pair { |key, val| val[0..-1] = '[FILTERED]' if key == 'password' }
9
+ end
10
+ end
11
+
12
+ class TestAPI
13
+ end
14
+
15
+ class App
16
+ attr_accessor :response
17
+
18
+ def call(_env)
19
+ response
20
+ end
21
+ end
22
+
23
+ factory :param_filter
24
+
25
+ require 'rack/rewindable_input'
26
+
27
+ factory :expected_env do
28
+ grape_request { build :grape_request }
29
+ params { grape_request.params }
30
+ post_params { { 'name' => 'foo', 'password' => 'access' } }
31
+ grape_endpoint { build(:grape_endpoint) }
32
+
33
+ initialize_with do
34
+ new.merge(
35
+ 'REQUEST_METHOD' => 'POST',
36
+ 'PATH_INFO' => '/api/1.0/users',
37
+ 'action_dispatch.request.request_parameters' => post_params,
38
+ Grape::Env::GRAPE_REQUEST => grape_request,
39
+ Grape::Env::GRAPE_REQUEST_PARAMS => params,
40
+ Grape::Env::API_ENDPOINT => grape_endpoint
41
+ )
42
+ end
43
+ end
44
+
45
+ factory :grape_endpoint, class: Grape::Endpoint do
46
+ settings { Grape::Util::InheritableSetting.new }
47
+ options {
48
+ {
49
+ path: [:users],
50
+ method: 'get',
51
+ for: TestAPI
52
+ }
53
+ }
54
+
55
+ initialize_with { new(settings, options) }
56
+
57
+ trait :complex do
58
+ options {
59
+ {
60
+ path: ['/users/:name/profile'],
61
+ method: 'put',
62
+ for: TestAPI
63
+ }
64
+ }
65
+ end
66
+ end
67
+
68
+ factory :namespaced_endpoint, parent: :grape_endpoint do
69
+ initialize_with do
70
+ new(settings, options).tap do |me|
71
+ me.namespace_stackable(:namespace, Grape::Namespace.new('/admin', {}))
72
+ end
73
+ end
74
+ end
75
+
76
+ factory :app_response, class: Rack::Response do
77
+ initialize_with { new('Hello World', 200, {}) }
78
+ end
79
+
80
+ factory :grape_request, class: OpenStruct do
81
+ initialize_with {
82
+ new(request_method: 'POST', path: '/api/1.0/users', headers: {}, params: { 'id' => '101001' })
83
+ }
84
+ end
85
+
86
+ factory :app do
87
+ response { build :app_response }
88
+ end
89
+
90
+ end
@@ -0,0 +1,8 @@
1
+ require 'tempfile'
2
+
3
+ class RailsApp < Rails::Application
4
+ RailsLogger = Class.new Logger
5
+ config.logger = RailsLogger.new(Tempfile.new '')
6
+ config.filter_parameters += [:password]
7
+ config.eager_load = false
8
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Middleware::Lograge, type: :integration do
4
+ let(:app) { build :app }
5
+ let(:options) { { filter: build(:param_filter) } }
6
+
7
+ subject { described_class.new(app, options) }
8
+
9
+ let(:app_response) { build :app_response }
10
+ let(:grape_request) { build :grape_request }
11
+ let(:grape_endpoint) { build(:grape_endpoint) }
12
+ let(:env) { build(:expected_env, grape_endpoint: grape_endpoint) }
13
+
14
+ it 'logs all parts of the request' do
15
+ pending('test payload object')
16
+ expect(subject.logger).to receive(:info).with ''
17
+ expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
18
+ expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI#users)
19
+ expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "name"=>"foo", "password"=>"[FILTERED]"})
20
+ expect(subject.logger).to receive(:info).with /Completed 200 in \d+.\d+ms/
21
+ expect(subject.logger).to receive(:info).with ''
22
+ subject.call!(env)
23
+ end
24
+
25
+ describe 'the "processing by" section' do
26
+ before { subject.call!(env) }
27
+
28
+ context 'namespacing' do
29
+ let(:grape_endpoint) { build(:namespaced_endpoint) }
30
+
31
+ it 'ignores the namespacing' do
32
+ expect(subject.controller).to eq 'TestAPI'
33
+ expect(subject.action_name).to eq 'users'
34
+ end
35
+
36
+ context 'with more complex route' do
37
+ let(:grape_endpoint) { build(:namespaced_endpoint, :complex) }
38
+
39
+ it 'only escapes the first slash and leaves the rest of the untouched' do
40
+ expect(subject.controller).to eq 'TestAPI'
41
+ expect(subject.action_name).to eq 'users/:name/profile'
42
+ end
43
+ end
44
+ end
45
+
46
+ context 'with more complex route' do
47
+ let(:grape_endpoint) { build(:grape_endpoint, :complex) }
48
+
49
+ it 'only escapes the first slash and leaves the rest of the untouched' do
50
+ expect(subject.action_name).to eq 'users/:name/profile'
51
+ end
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,54 @@
1
+ require 'rails_helper'
2
+
3
+ describe Grape::Middleware::Lograge, type: :rails_integration do
4
+ let(:app) { build :app }
5
+ let(:options) { {} }
6
+
7
+ subject { described_class.new(app, options) }
8
+
9
+ let(:app_response) { build :app_response }
10
+ let(:grape_request) { build :grape_request }
11
+ let(:grape_endpoint) { build(:grape_endpoint) }
12
+ let(:env) { build(:expected_env, grape_endpoint: grape_endpoint) }
13
+
14
+ it 'logs all parts of the request' do
15
+ pending('test payload object')
16
+ expect(subject.logger).to receive(:info).with ''
17
+ expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
18
+ expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI#users)
19
+ expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "name"=>"foo", "password"=>"[FILTERED]"})
20
+ expect(subject.logger).to receive(:info).with /Completed 200 in \d+.\d+ms/
21
+ expect(subject.logger).to receive(:info).with ''
22
+ subject.call!(env)
23
+ end
24
+
25
+ describe 'the "processing by" section' do
26
+ before { subject.call!(env) }
27
+
28
+ context 'namespacing' do
29
+ let(:grape_endpoint) { build(:namespaced_endpoint) }
30
+
31
+ it 'ignores the namespacing' do
32
+ expect(subject.controller).to eq 'TestAPI'
33
+ expect(subject.action_name).to eq 'users'
34
+ end
35
+
36
+ context 'with more complex route' do
37
+ let(:grape_endpoint) { build(:namespaced_endpoint, :complex) }
38
+
39
+ it 'only escapes the first slash and leaves the rest of the untouched' do
40
+ expect(subject.controller).to eq 'TestAPI'
41
+ expect(subject.action_name).to eq 'users/:name/profile'
42
+ end
43
+ end
44
+ end
45
+
46
+ context 'with more complex route' do
47
+ let(:grape_endpoint) { build(:grape_endpoint, :complex) }
48
+
49
+ it 'only escapes the first slash and leaves the rest of the untouched' do
50
+ expect(subject.action_name).to eq 'users/:name/profile'
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Middleware::Lograge do
4
+ let(:app) { double('app') }
5
+ let(:options) { { filter: build(:param_filter), logger: Object.new } }
6
+
7
+ subject { described_class.new(app, options) }
8
+
9
+ let(:app_response) { build :app_response }
10
+ let(:grape_request) { build :grape_request }
11
+ let(:env) { build(:expected_env) }
12
+
13
+ describe '#call!' do
14
+ context 'when calling the app results in an error response' do
15
+ let(:error) { { status: 400 } }
16
+
17
+ it 'calls +after_failure+ and rethrows the error' do
18
+ expect(app).to receive(:call).with(env).and_throw(:error, error)
19
+ expect(subject).to receive(:before)
20
+ expect(subject).to receive(:after_failure).with(hash_including(method: 'POST'), error)
21
+ expect(subject).to receive(:throw).with(:error, error)
22
+ subject.call!(env)
23
+ end
24
+ end
25
+
26
+ context 'when there is no error' do
27
+ it 'calls +after+ with the correct status' do
28
+ expect(app).to receive(:call).with(env).and_return(app_response)
29
+ expect(subject).to receive(:before).and_call_original
30
+ expect(subject).to receive(:after).with(hash_including(method: 'POST'), 200)
31
+ subject.call!(env)
32
+ end
33
+
34
+ it 'returns the @app_response' do
35
+ expect(app).to receive(:call).with(env).and_return(app_response)
36
+ allow(subject).to receive(:before)
37
+ allow(subject).to receive(:after)
38
+ expect(subject.call!(env)).to eq app_response
39
+ end
40
+ end
41
+
42
+ context 'when calling the app results in an array response' do
43
+ let(:app_response) { [401, {}, []] }
44
+
45
+ it 'calls +after+ with the correct status' do
46
+ expect(app).to receive(:call).with(env).and_return(app_response)
47
+ expect(subject).to receive(:before).and_call_original
48
+ expect(subject).to receive(:after).with(hash_including(method: 'POST'), 401)
49
+ subject.call!(env)
50
+ end
51
+
52
+ it 'returns the @app_response' do
53
+ expect(app).to receive(:call).with(env).and_return(app_response)
54
+ allow(subject).to receive(:before)
55
+ allow(subject).to receive(:after)
56
+ expect(subject.call!(env)).to eq app_response
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#after_failure' do
62
+ let(:error) { { status: 403 } }
63
+ let(:payload) { {} }
64
+
65
+ it 'calls +after+ with the :status' do
66
+ expect(subject).to receive(:after).with(payload, 403).and_call_original
67
+ expect(subject).to receive(:env).twice.and_return(env)
68
+ subject.after_failure(payload, error)
69
+ expect(payload[:status]).to eq(403)
70
+ end
71
+
72
+ context 'when :message is set in the error object' do
73
+ let(:error) { { message: 'Oops, not found' } }
74
+
75
+ it 'logs the error message' do
76
+ pending('implement error messages')
77
+ expect(subject).to receive(:after).with(payload, nil).and_call_original
78
+ expect(subject).to receive(:env).twice.and_return(env)
79
+ subject.after_failure(payload, error)
80
+ expect(payload[:message]).to match(Regexp.new(error[:message]))
81
+ end
82
+ end
83
+ end
84
+
85
+ describe '#parameters' do
86
+ before { subject.instance_variable_set(:@env, env) }
87
+
88
+ context 'when @options[:filter] is set' do
89
+ it 'calls +filter+ with the raw parameters' do
90
+ expect(subject.options[:filter]).to receive(:filter).with({ "id" => '101001', "name" => "foo", "password" => "access" })
91
+ subject.parameters
92
+ end
93
+
94
+ it 'returns the filtered results' do
95
+ expect(subject.parameters).to eq({ "id" => '101001', "name" => "foo", "password" => "[FILTERED]" })
96
+ end
97
+ end
98
+
99
+ context 'when @options[:filter] is nil' do
100
+ let(:options) { {} }
101
+
102
+ it 'returns the params extracted out of @env' do
103
+ expect(subject.parameters).to eq({ "id" => '101001', "name" => "foo", "password" => "access" })
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,4 @@
1
+ require 'rails'
2
+ require_relative 'fixtures/rails_app'
3
+ require 'spec_helper'
4
+ RailsApp.initialize!
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'ostruct'
5
+ require 'factory_girl'
6
+ require 'grape/middleware/lograge'
7
+
8
+ FactoryGirl.find_definitions
9
+
10
+ RSpec.configure do |config|
11
+ config.raise_errors_for_deprecations!
12
+ config.include FactoryGirl::Syntax::Methods
13
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grape-middleware-lograge
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Buckley
8
+ - Paul Chavard
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-12-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: grape
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0.14'
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '1'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: '0.14'
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
34
+ - !ruby/object:Gem::Dependency
35
+ name: lograge
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.3'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.3'
48
+ - !ruby/object:Gem::Dependency
49
+ name: bundler
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: rspec
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '3.2'
83
+ - - "<"
84
+ - !ruby/object:Gem::Version
85
+ version: '4'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '3.2'
93
+ - - "<"
94
+ - !ruby/object:Gem::Version
95
+ version: '4'
96
+ description: Logging middleware for the Grape framework, that uses Lograge
97
+ email:
98
+ - arebuckley@gmail.com
99
+ - paul+github@chavard.net
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".travis.yml"
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - grape-middleware-lograge.gemspec
111
+ - lib/grape/middleware/lograge.rb
112
+ - lib/grape/middleware/lograge/railtie.rb
113
+ - lib/lograge/formatters/rails_logger.rb
114
+ - spec/factories.rb
115
+ - spec/fixtures/rails_app.rb
116
+ - spec/integration/lib/grape/middleware/lograge_spec.rb
117
+ - spec/integration_rails/lib/grape/middleware/lograge_spec.rb
118
+ - spec/lib/grape/middleware/lograge_spec.rb
119
+ - spec/rails_helper.rb
120
+ - spec/spec_helper.rb
121
+ homepage: https://github.com/tchak/grape-middleware-lograge
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.4.5.1
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: A logger for the Grape framework
145
+ test_files:
146
+ - spec/factories.rb
147
+ - spec/fixtures/rails_app.rb
148
+ - spec/integration/lib/grape/middleware/lograge_spec.rb
149
+ - spec/integration_rails/lib/grape/middleware/lograge_spec.rb
150
+ - spec/lib/grape/middleware/lograge_spec.rb
151
+ - spec/rails_helper.rb
152
+ - spec/spec_helper.rb