grape-middleware-logger 1.8.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/grape-middleware-logger.gemspec +3 -3
- metadata +5 -31
- data/.gitignore +0 -17
- data/.travis.yml +0 -8
- data/CHANGELOG.md +0 -36
- data/CODE_OF_CONDUCT.md +0 -30
- data/Gemfile +0 -10
- data/LICENSE.txt +0 -22
- data/README.md +0 -114
- data/Rakefile +0 -15
- data/spec/factories.rb +0 -120
- data/spec/fixtures/rails_app.rb +0 -6
- data/spec/integration/lib/grape/middleware/headers_option_spec.rb +0 -65
- data/spec/integration/lib/grape/middleware/logger_spec.rb +0 -68
- data/spec/integration_rails/lib/grape/middleware/logger_spec.rb +0 -82
- data/spec/lib/grape/middleware/headers_option_spec.rb +0 -57
- data/spec/lib/grape/middleware/logger_spec.rb +0 -102
- data/spec/rails_helper.rb +0 -4
- data/spec/spec_helper.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5972e8884b858451da5eb0e08dd289c7e0a80237
|
4
|
+
data.tar.gz: 9810abfbf34c36fa0bed302346b5b2de36d951a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71b4b116883c951127500b3a8af622dd5c9d87d0031bc598953f1602f93fb7e4a59670680bb76636c50aa4d68202b7558e5e1902423464536706f355f4bff755
|
7
|
+
data.tar.gz: 11d6dc7dc0ee424a33aa70700e1d058aa4b77601a34f3081175941463a0da286c984bf001173b107f9de3fde90d2257548512d10c28833b1f0a55c906fe36b98
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'grape-middleware-logger'
|
5
|
-
spec.version = '1.
|
5
|
+
spec.version = '1.9.0'
|
6
6
|
spec.platform = Gem::Platform::RUBY
|
7
7
|
spec.authors = ['Ryan Buckley']
|
8
8
|
spec.email = ['arebuckley@gmail.com']
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.homepage = 'https://github.com/ridiculous/grape-middleware-logger'
|
12
12
|
spec.license = 'MIT'
|
13
13
|
|
14
|
-
spec.files = `git ls-files -z`.split("\x0")
|
14
|
+
spec.files = `git ls-files -z`.split("\x0").grep(%r{^lib/|gemspec})
|
15
15
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
16
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
17
|
spec.require_paths = ['lib']
|
@@ -24,7 +24,7 @@ Grape::Middleware::Logger 1.7+ should be mounted with +insert_after+ to properly
|
|
24
24
|
|
25
25
|
}
|
26
26
|
|
27
|
-
spec.add_dependency 'grape', '>= 0.17', '< 1'
|
27
|
+
spec.add_dependency 'grape', '>= 0.17', '< 1.1'
|
28
28
|
|
29
29
|
spec.add_development_dependency 'bundler', '~> 1.7'
|
30
30
|
spec.add_development_dependency 'mime-types', '~> 2'
|
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.
|
4
|
+
version: 1.9.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: 2017-
|
11
|
+
date: 2017-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grape
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '0.17'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '1'
|
22
|
+
version: '1.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '0.17'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '1'
|
32
|
+
version: '1.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: bundler
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -99,26 +99,9 @@ executables: []
|
|
99
99
|
extensions: []
|
100
100
|
extra_rdoc_files: []
|
101
101
|
files:
|
102
|
-
- ".gitignore"
|
103
|
-
- ".travis.yml"
|
104
|
-
- CHANGELOG.md
|
105
|
-
- CODE_OF_CONDUCT.md
|
106
|
-
- Gemfile
|
107
|
-
- LICENSE.txt
|
108
|
-
- README.md
|
109
|
-
- Rakefile
|
110
102
|
- grape-middleware-logger.gemspec
|
111
103
|
- lib/grape/middleware/logger.rb
|
112
104
|
- lib/grape/middleware/logger/railtie.rb
|
113
|
-
- spec/factories.rb
|
114
|
-
- spec/fixtures/rails_app.rb
|
115
|
-
- spec/integration/lib/grape/middleware/headers_option_spec.rb
|
116
|
-
- spec/integration/lib/grape/middleware/logger_spec.rb
|
117
|
-
- spec/integration_rails/lib/grape/middleware/logger_spec.rb
|
118
|
-
- spec/lib/grape/middleware/headers_option_spec.rb
|
119
|
-
- spec/lib/grape/middleware/logger_spec.rb
|
120
|
-
- spec/rails_helper.rb
|
121
|
-
- spec/spec_helper.rb
|
122
105
|
homepage: https://github.com/ridiculous/grape-middleware-logger
|
123
106
|
licenses:
|
124
107
|
- MIT
|
@@ -145,13 +128,4 @@ rubygems_version: 2.4.8
|
|
145
128
|
signing_key:
|
146
129
|
specification_version: 4
|
147
130
|
summary: A logger for the Grape framework
|
148
|
-
test_files:
|
149
|
-
- spec/factories.rb
|
150
|
-
- spec/fixtures/rails_app.rb
|
151
|
-
- spec/integration/lib/grape/middleware/headers_option_spec.rb
|
152
|
-
- spec/integration/lib/grape/middleware/logger_spec.rb
|
153
|
-
- spec/integration_rails/lib/grape/middleware/logger_spec.rb
|
154
|
-
- spec/lib/grape/middleware/headers_option_spec.rb
|
155
|
-
- spec/lib/grape/middleware/logger_spec.rb
|
156
|
-
- spec/rails_helper.rb
|
157
|
-
- spec/spec_helper.rb
|
131
|
+
test_files: []
|
data/.gitignore
DELETED
data/.travis.yml
DELETED
data/CHANGELOG.md
DELETED
@@ -1,36 +0,0 @@
|
|
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
|
-
|
5
|
-
1.7.1 (11/1/2016)
|
6
|
-
==================
|
7
|
-
* Log the error class name (https://github.com/ridiculous/grape-middleware-logger/pull/13)
|
8
|
-
|
9
|
-
1.7.0 (8/2/2016)
|
10
|
-
==================
|
11
|
-
|
12
|
-
* Bump Grape dependency to 0.17
|
13
|
-
* Encourage `insert_after` when mounting to properly include query and post data
|
14
|
-
|
15
|
-
```ruby
|
16
|
-
insert_after Grape::Middleware::Formatter, Grape::Middleware::Logger
|
17
|
-
```
|
18
|
-
|
19
|
-
1.6.0 (4/4/2016)
|
20
|
-
==================
|
21
|
-
|
22
|
-
* Can use default rake command to run test suite
|
23
|
-
* Fix [#4](https://github.com/ridiculous/grape-middleware-logger/issues/4), missing JSON parameters from POST requests
|
24
|
-
* Grape::Middleware::Formatter#before is Ruby 1.9.3 friendly
|
25
|
-
|
26
|
-
1.5.1 (12/15/2015)
|
27
|
-
==================
|
28
|
-
|
29
|
-
* Refactor logger conditional to use coercion and parallel assignment
|
30
|
-
|
31
|
-
|
32
|
-
1.5.0 (12/12/2015)
|
33
|
-
==================
|
34
|
-
|
35
|
-
* Use Railtie to setup default configuration for Rails apps
|
36
|
-
* Stop logging the namespace
|
data/CODE_OF_CONDUCT.md
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# Grape::Middleware::logger Code of Conduct
|
2
|
-
|
3
|
-
The Grape::Middleware::logger project strongly values contributors from anywhere, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, ethnicity, age, religion, or nationality. As a result, the Grape::Middleware::logger team has agreed to and enforces this code of conduct in order to provide a harassment-free experience for everyone who participates in the development of Grape::Middleware::logger.
|
4
|
-
|
5
|
-
### Summary
|
6
|
-
|
7
|
-
Harassment in code and discussion or violation of physical boundaries is completely unacceptable anywhere in the Grape::Middleware::logger project’s codebases, issue trackers, chat rooms, mailing lists, meetups, and any other events. Violators will be warned and then blocked or banned by the core team at or before the 3rd violation.
|
8
|
-
|
9
|
-
### In detail
|
10
|
-
|
11
|
-
Harassment includes offensive verbal comments related to level of experience, gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, ethnicity, age, religion, nationality, the use of sexualized language or imagery, deliberate intimidation, stalking, sustained disruption, and unwelcome sexual attention.
|
12
|
-
|
13
|
-
Individuals asked to stop any harassing behavior are expected to comply immediately.
|
14
|
-
|
15
|
-
Maintainers, including the core team, are also subject to the anti-harassment policy.
|
16
|
-
|
17
|
-
If anyone engages in abusive, harassing, or otherwise unacceptable behavior, including maintainers, we may take appropriate action, up to and including warning the offender, deletion of comments, removal from the project’s codebase and communication systems, and escalation to Github support.
|
18
|
-
|
19
|
-
If you are being harassed, notice that someone else is being harassed, or have any other concerns, please contact a member of the core team immediately.
|
20
|
-
|
21
|
-
We expect everyone to follow these rules anywhere in the logger project’s codebases, issue trackers, IRC channel, group chat, and mailing lists.
|
22
|
-
|
23
|
-
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
24
|
-
|
25
|
-
Finally, don't forget that it is human to make mistakes! We all do. Let’s work together to help each other, resolve issues, and learn from the mistakes that we will all inevitably make from time to time.
|
26
|
-
|
27
|
-
|
28
|
-
### License
|
29
|
-
|
30
|
-
MIT
|
data/Gemfile
DELETED
data/LICENSE.txt
DELETED
@@ -1,22 +0,0 @@
|
|
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
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
# A logger for [Grape](https://github.com/ruby-grape/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.17'
|
20
|
-
gem 'grape-middleware-logger'
|
21
|
-
```
|
22
|
-
|
23
|
-
## Usage
|
24
|
-
```ruby
|
25
|
-
class API < Grape::API
|
26
|
-
# @note Make sure this is above your first +mount+
|
27
|
-
insert_after Grape::Middleware::Formatter, Grape::Middleware::Logger
|
28
|
-
end
|
29
|
-
```
|
30
|
-
|
31
|
-
Server requests will be logged to STDOUT by default.
|
32
|
-
|
33
|
-
## Example output
|
34
|
-
GET
|
35
|
-
```
|
36
|
-
Started GET "/v1/reports/101" at 2015-12-11 15:40:51 -0800
|
37
|
-
Processing by ReportsAPI/reports/:id
|
38
|
-
Parameters: {"id"=>"101"}
|
39
|
-
Completed 200 in 6.29ms
|
40
|
-
```
|
41
|
-
POST
|
42
|
-
```
|
43
|
-
Started POST "/v1/reports" at 2015-12-11 15:42:33 -0800
|
44
|
-
Processing by ReportsAPI/reports
|
45
|
-
Parameters: {"name"=>"foo", "password"=>"[FILTERED]"}
|
46
|
-
Error: {:error=>"undefined something something bad", :detail=>"Whoops"}
|
47
|
-
Completed 422 in 6.29ms
|
48
|
-
```
|
49
|
-
|
50
|
-
## Customization
|
51
|
-
|
52
|
-
The middleware logger can be customized with the following options:
|
53
|
-
|
54
|
-
* The `:logger` option can be any object that responds to `.info(String)`
|
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)
|
59
|
-
|
60
|
-
For example:
|
61
|
-
|
62
|
-
```ruby
|
63
|
-
insert_after Grape::Middleware::Formatter, Grape::Middleware::Logger, {
|
64
|
-
logger: Logger.new(STDERR),
|
65
|
-
filter: Class.new { def filter(opts) opts.reject { |k, _| k.to_s == 'password' } end }.new,
|
66
|
-
headers: %w(version cache-control)
|
67
|
-
}
|
68
|
-
```
|
69
|
-
|
70
|
-
## Using Rails?
|
71
|
-
`Rails.logger` and `Rails.application.config.filter_parameters` will be used automatically as the default logger and
|
72
|
-
param filterer, respectively. This behavior can be overridden by passing the `:logger` or
|
73
|
-
`:filter` option when mounting.
|
74
|
-
|
75
|
-
You may want to disable Rails logging for API endpoints, so that the logging doesn't double-up. You can achieve this
|
76
|
-
by switching around some middleware. For example:
|
77
|
-
|
78
|
-
```ruby
|
79
|
-
# config/application.rb
|
80
|
-
config.middleware.swap 'Rails::Rack::Logger', 'SelectiveLogger'
|
81
|
-
|
82
|
-
# config/initializers/selective_logger.rb
|
83
|
-
class SelectiveLogger
|
84
|
-
def initialize(app)
|
85
|
-
@app = app
|
86
|
-
end
|
87
|
-
|
88
|
-
def call(env)
|
89
|
-
if env['PATH_INFO'] =~ %r{^/api}
|
90
|
-
@app.call(env)
|
91
|
-
else
|
92
|
-
Rails::Rack::Logger.new(@app).call(env)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
```
|
97
|
-
|
98
|
-
## Rack
|
99
|
-
|
100
|
-
If you're using the `rackup` command to run your server in development, pass the `-q` flag to silence the default rack logger.
|
101
|
-
|
102
|
-
## Credits
|
103
|
-
|
104
|
-
Big thanks to jadent's question/answer on [stackoverflow](http://stackoverflow.com/questions/25048163/grape-using-error-and-grapemiddleware-after-callback)
|
105
|
-
for easily logging error responses. Borrowed some motivation from the [grape_logging](https://github.com/aserafin/grape_logging) gem
|
106
|
-
and would love to see these two consolidated at some point.
|
107
|
-
|
108
|
-
## Contributing
|
109
|
-
|
110
|
-
1. Fork it ( https://github.com/ridiculous/grape-middleware-logger/fork )
|
111
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
112
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
113
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
114
|
-
5. Create a new Pull Request
|
data/Rakefile
DELETED
@@ -1,15 +0,0 @@
|
|
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]
|
data/spec/factories.rb
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
FactoryGirl.define do
|
2
|
-
class ExpectedEnv < Hash
|
3
|
-
attr_accessor :grape_request, :params, :post_params, :rails_post_params, :grape_endpoint
|
4
|
-
end
|
5
|
-
|
6
|
-
class ParamFilter
|
7
|
-
attr_accessor :list
|
8
|
-
|
9
|
-
def filter(opts)
|
10
|
-
opts.each_pair { |key, val| val[0..-1] = '[FILTERED]' if list.include?(key) }
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class TestAPI
|
15
|
-
end
|
16
|
-
|
17
|
-
class App
|
18
|
-
attr_accessor :response
|
19
|
-
|
20
|
-
def call(_env)
|
21
|
-
response
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
factory :param_filter do
|
26
|
-
list %w[password secret]
|
27
|
-
end
|
28
|
-
|
29
|
-
require 'rack/rewindable_input'
|
30
|
-
|
31
|
-
factory :expected_env do
|
32
|
-
grape_request { build :grape_request }
|
33
|
-
grape_endpoint { build(:grape_endpoint) }
|
34
|
-
params { grape_request.params }
|
35
|
-
headers { grape_request.headers }
|
36
|
-
post_params { { 'secret' => 'key', 'customer' => [] } }
|
37
|
-
rails_post_params { { 'name' => 'foo', 'password' => 'access' } }
|
38
|
-
other_env_params { {} }
|
39
|
-
|
40
|
-
initialize_with do
|
41
|
-
new.merge(
|
42
|
-
'REQUEST_METHOD' => 'POST',
|
43
|
-
'PATH_INFO' => '/api/1.0/users',
|
44
|
-
'action_dispatch.request.request_parameters' => rails_post_params,
|
45
|
-
Grape::Env::GRAPE_REQUEST => grape_request,
|
46
|
-
Grape::Env::GRAPE_REQUEST_PARAMS => params,
|
47
|
-
Grape::Env::GRAPE_REQUEST_HEADERS => headers,
|
48
|
-
Grape::Env::RACK_REQUEST_FORM_HASH => post_params,
|
49
|
-
Grape::Env::API_ENDPOINT => grape_endpoint
|
50
|
-
).merge(other_env_params)
|
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
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
factory :grape_endpoint, class: Grape::Endpoint do
|
65
|
-
settings { Grape::Util::InheritableSetting.new }
|
66
|
-
options {
|
67
|
-
{
|
68
|
-
path: [:users],
|
69
|
-
method: 'get',
|
70
|
-
for: TestAPI
|
71
|
-
}
|
72
|
-
}
|
73
|
-
|
74
|
-
initialize_with { new(settings, options) }
|
75
|
-
|
76
|
-
trait :complex do
|
77
|
-
options {
|
78
|
-
{
|
79
|
-
path: ['/users/:name/profile'],
|
80
|
-
method: 'put',
|
81
|
-
for: TestAPI
|
82
|
-
}
|
83
|
-
}
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
factory :namespaced_endpoint, parent: :grape_endpoint do
|
88
|
-
initialize_with do
|
89
|
-
new(settings, options).tap do |me|
|
90
|
-
me.namespace_stackable(:namespace, Grape::Namespace.new('/admin', {}))
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
factory :app_response, class: Rack::Response do
|
96
|
-
initialize_with { new('Hello World', 200, {}) }
|
97
|
-
end
|
98
|
-
|
99
|
-
factory :grape_request, class: OpenStruct do
|
100
|
-
headers { {} }
|
101
|
-
|
102
|
-
initialize_with {
|
103
|
-
new(request_method: 'POST', path: '/api/1.0/users', headers: headers, params: { 'id' => '101001' })
|
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
|
114
|
-
end
|
115
|
-
|
116
|
-
factory :app do
|
117
|
-
response { build :app_response }
|
118
|
-
end
|
119
|
-
|
120
|
-
end
|
data/spec/fixtures/rails_app.rb
DELETED
@@ -1,65 +0,0 @@
|
|
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
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Grape::Middleware::Logger, type: :integration do
|
4
|
-
let(:app) { build :app }
|
5
|
-
let(:options) { { filter: build(:param_filter), logger: Logger.new(Tempfile.new('logger')) } }
|
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
|
-
expect(subject.logger).to receive(:info).with ''
|
16
|
-
expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
|
17
|
-
expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI/users)
|
18
|
-
expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "secret"=>"[FILTERED]", "customer"=>[], "name"=>"foo", "password"=>"[FILTERED]"})
|
19
|
-
expect(subject.logger).to receive(:info).with /Completed 200 in \d+.\d+ms/
|
20
|
-
expect(subject.logger).to receive(:info).with ''
|
21
|
-
subject.call!(env)
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when an exception occurs' do
|
25
|
-
it 'logs all parts of the request including the error class' do
|
26
|
-
expect(subject.logger).to receive(:info).with ''
|
27
|
-
expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
|
28
|
-
expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI/users)
|
29
|
-
expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "secret"=>"[FILTERED]", "customer"=>[], "name"=>"foo", "password"=>"[FILTERED]"})
|
30
|
-
expect(subject.logger).to receive(:info).with %Q( ArgumentError: Whoops)
|
31
|
-
expect(subject.logger).to receive(:info).with /Completed 500 in \d+\.\d+ms/
|
32
|
-
expect(subject.logger).to receive(:info).with ''
|
33
|
-
expect(subject.app).to receive(:call).and_raise(ArgumentError, 'Whoops')
|
34
|
-
expect {
|
35
|
-
subject.call!(env)
|
36
|
-
}.to raise_error(ArgumentError)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe 'the "processing by" section' do
|
41
|
-
before { subject.call!(env) }
|
42
|
-
|
43
|
-
context 'namespacing' do
|
44
|
-
let(:grape_endpoint) { build(:namespaced_endpoint) }
|
45
|
-
|
46
|
-
it 'ignores the namespacing' do
|
47
|
-
expect(subject.processed_by).to eq 'TestAPI/admin/users'
|
48
|
-
end
|
49
|
-
|
50
|
-
context 'with more complex route' do
|
51
|
-
let(:grape_endpoint) { build(:namespaced_endpoint, :complex) }
|
52
|
-
|
53
|
-
it 'only escapes the first slash and leaves the rest of the untouched' do
|
54
|
-
expect(subject.processed_by).to eq 'TestAPI/admin/users/:name/profile'
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'with more complex route' do
|
60
|
-
let(:grape_endpoint) { build(:grape_endpoint, :complex) }
|
61
|
-
|
62
|
-
it 'only escapes the first slash and leaves the rest of the untouched' do
|
63
|
-
expect(subject.processed_by).to eq 'TestAPI/users/:name/profile'
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'rails_helper'
|
2
|
-
|
3
|
-
describe Grape::Middleware::Logger, 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
|
-
describe '#logger' do
|
15
|
-
context 'when @options[:logger] is nil' do
|
16
|
-
context 'when Rails.application.config.logger is defined' do
|
17
|
-
it 'uses the Rails logger' do
|
18
|
-
expect(subject.logger).to be_present
|
19
|
-
expect(subject.logger).to be Rails.application.config.logger
|
20
|
-
expect(subject.logger.formatter).to be_nil
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when the class logger is nil' do
|
25
|
-
before { described_class.logger = nil }
|
26
|
-
|
27
|
-
it 'uses the default logger' do
|
28
|
-
expect(subject.logger).to be_present
|
29
|
-
expect(subject.logger).to_not be Rails.application.config.logger
|
30
|
-
expect(subject.logger).to be_a(Logger)
|
31
|
-
expect(subject.logger.formatter.call('foo')).to eq "foo\n"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
context 'when @options[:logger] is set' do
|
37
|
-
let(:options) { { logger: Object.new } }
|
38
|
-
|
39
|
-
it 'returns the logger object' do
|
40
|
-
expect(subject.logger).to eq options[:logger]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'logs all parts of the request' do
|
46
|
-
expect(subject.logger).to receive(:info).with ''
|
47
|
-
expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
|
48
|
-
expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI/users)
|
49
|
-
expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "secret"=>"key", "customer"=>[], "name"=>"foo", "password"=>"[FILTERED]"})
|
50
|
-
expect(subject.logger).to receive(:info).with /Completed 200 in \d+.\d+ms/
|
51
|
-
expect(subject.logger).to receive(:info).with ''
|
52
|
-
subject.call!(env)
|
53
|
-
end
|
54
|
-
|
55
|
-
describe 'the "processing by" section' do
|
56
|
-
before { subject.call!(env) }
|
57
|
-
|
58
|
-
context 'namespacing' do
|
59
|
-
let(:grape_endpoint) { build(:namespaced_endpoint) }
|
60
|
-
|
61
|
-
it 'ignores the namespacing' do
|
62
|
-
expect(subject.processed_by).to eq 'TestAPI/admin/users'
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'with more complex route' do
|
66
|
-
let(:grape_endpoint) { build(:namespaced_endpoint, :complex) }
|
67
|
-
|
68
|
-
it 'only escapes the first slash and leaves the rest of the untouched' do
|
69
|
-
expect(subject.processed_by).to eq 'TestAPI/admin/users/:name/profile'
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
context 'with more complex route' do
|
75
|
-
let(:grape_endpoint) { build(:grape_endpoint, :complex) }
|
76
|
-
|
77
|
-
it 'only escapes the first slash and leaves the rest of the untouched' do
|
78
|
-
expect(subject.processed_by).to eq 'TestAPI/users/:name/profile'
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
@@ -1,57 +0,0 @@
|
|
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
|
-
|
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Grape::Middleware::Logger 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(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)
|
30
|
-
expect(subject).to receive(:after).with(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)
|
48
|
-
expect(subject).to receive(:after).with(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
|
-
|
64
|
-
it 'calls +after+ with the :status' do
|
65
|
-
expect(subject).to receive(:after).with(403)
|
66
|
-
subject.after_failure(error)
|
67
|
-
end
|
68
|
-
|
69
|
-
context 'when :message is set in the error object' do
|
70
|
-
let(:error) { { message: 'Oops, not found' } }
|
71
|
-
|
72
|
-
it 'logs the error message' do
|
73
|
-
allow(subject).to receive(:after)
|
74
|
-
expect(subject.logger).to receive(:info).with(Regexp.new(error[:message]))
|
75
|
-
subject.after_failure(error)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe '#parameters' do
|
81
|
-
before { subject.instance_variable_set(:@env, env) }
|
82
|
-
|
83
|
-
context 'when @options[:filter] is set' do
|
84
|
-
it 'calls +filter+ with the raw parameters' do
|
85
|
-
expect(subject.options[:filter]).to receive(:filter).with({ "id" => '101001', "secret" => "key", "customer" => [], "name"=>"foo", "password"=>"access" })
|
86
|
-
subject.parameters
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'returns the filtered results' do
|
90
|
-
expect(subject.parameters).to eq({ "id" => '101001', "secret" => "[FILTERED]", "customer" => [], "name"=>"foo", "password"=>"[FILTERED]" })
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context 'when @options[:filter] is nil' do
|
95
|
-
let(:options) { {} }
|
96
|
-
|
97
|
-
it 'returns the params extracted out of @env' do
|
98
|
-
expect(subject.parameters).to eq({ "id" => '101001', "secret" => "key", "customer" => [], "name"=>"foo", "password"=>"access" })
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
data/spec/rails_helper.rb
DELETED
data/spec/spec_helper.rb
DELETED
@@ -1,13 +0,0 @@
|
|
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/logger'
|
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
|