Skip to content

Commit 09e1bf5

Browse files
ericproulxdblock
andauthored
Revisit Grape's middlewares default options (#2561)
* Grape::Middleware::Base's options is now double splatted `default_options` have been transformed has const Grape::Middleware::Helpers has been removed * Fix entity_spec.rb * Add CHANGELOG.md + Upgrading notes * Do not change caller options --------- Co-authored-by: Daniel (dB.) Doubrovkine <[email protected]>
1 parent 3a0233a commit 09e1bf5

File tree

17 files changed

+69
-100
lines changed

17 files changed

+69
-100
lines changed

CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@
33
#### Features
44

55
* [#2532](https://github.com/ruby-grape/grape/pull/2532): Update RuboCop 1.71.2 - [@ericproulx](https://github.com/ericproulx).
6-
* [#2535](https://github.com/ruby-grape/grape/pull/2535): Delegates calls to inner objects - [@ericproulx](https://github.com/ericproulx).
6+
* [#2535](https://github.com/ruby-grape/grape/pull/2535): Delegate calls to inner objects - [@ericproulx](https://github.com/ericproulx).
77
* [#2537](https://github.com/ruby-grape/grape/pull/2537): Use activesupport `try` pattern - [@ericproulx](https://github.com/ericproulx).
88
* [#2536](https://github.com/ruby-grape/grape/pull/2536): Update normalize_path like Rails - [@ericproulx](https://github.com/ericproulx).
9-
* [#2540](https://github.com/ruby-grape/grape/pull/2540): Introduce Params builder with symbolized short name - [@ericproulx](https://github.com/ericproulx).
9+
* [#2540](https://github.com/ruby-grape/grape/pull/2540): Introduce params builder with symbolized short name - [@ericproulx](https://github.com/ericproulx).
1010
* [#2550](https://github.com/ruby-grape/grape/pull/2550): Drop ActiveSupport 6.0 - [@ericproulx](https://github.com/ericproulx).
1111
* [#2549](https://github.com/ruby-grape/grape/pull/2549): Delegate cookies management to `Grape::Request` - [@ericproulx](https://github.com/ericproulx).
1212
* [#2554](https://github.com/ruby-grape/grape/pull/2554): Remove `Grape::Http::Headers` and `Grape::Util::Lazy::Object` - [@ericproulx](https://github.com/ericproulx).
1313
* [#2556](https://github.com/ruby-grape/grape/pull/2556): Remove unused `Grape::Request::DEFAULT_PARAMS_BUILDER` constant - [@eriklovmo](https://github.com/eriklovmo).
1414
* [#2558](https://github.com/ruby-grape/grape/pull/2558): Add Ruby's option `enable_frozen_string_literal` in CI - [@ericproulx](https://github.com/ericproulx).
15-
* [#2557](https://github.com/ruby-grape/grape/pull/2557): Add lint! - [@ericproulx](https://github.com/ericproulx).
15+
* [#2557](https://github.com/ruby-grape/grape/pull/2557): Add `lint!` - [@ericproulx](https://github.com/ericproulx).
16+
* [#2561](https://github.com/ruby-grape/grape/pull/2561): Optimize hash alloc for middleware's default options - [@ericproulx](https://github.com/ericproulx).
1617
* Your contribution here.
1718

1819
#### Fixes

UPGRADING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ Upgrading Grape
33

44
### Upgrading to >= 2.4.0
55

6+
#### Grape::Middleware::Base
7+
8+
- Second argument `options` is now a double splat (**) instead of single splat (*). If you're redefining `initialize` in your middleware and/or calling `super` in it, you might have to adapt the signature and the `super` call. Also, you might have to remove `{}` if you're pass `options` as a literal `Hash` or add `**` if you're using a variable.
9+
- `Grape::Middleware::Helpers` has been removed. The equivalent method `context` is now part of `Grape::Middleware::Base`.
10+
611
#### Grape::Http::Headers, Grape::Util::Lazy::Object
712

813
Both have been removed. See [2554](https://github.com/ruby-grape/grape/pull/2554).

lib/grape/middleware/auth/base.rb

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ module Grape
44
module Middleware
55
module Auth
66
class Base
7-
include Helpers
8-
97
attr_accessor :options, :app, :env
108

11-
def initialize(app, *options)
9+
def initialize(app, **options)
1210
@app = app
13-
@options = options.shift
11+
@options = options
1412
end
1513

1614
def call(env)
@@ -19,24 +17,14 @@ def call(env)
1917

2018
def _call(env)
2119
self.env = env
20+
return app.call(env) unless options.key?(:type)
2221

23-
if options.key?(:type)
24-
auth_proc = options[:proc]
25-
auth_proc_context = context
26-
27-
strategy_info = Grape::Middleware::Auth::Strategies[options[:type]]
28-
29-
throw(:error, status: 401, message: 'API Authorization Failed.') if strategy_info.blank?
30-
31-
strategy = strategy_info.create(@app, options) do |*args|
32-
auth_proc_context.instance_exec(*args, &auth_proc)
33-
end
34-
35-
strategy.call(env)
22+
strategy_info = Grape::Middleware::Auth::Strategies[options[:type]]
23+
throw :error, status: 401, message: 'API Authorization Failed.' if strategy_info.blank?
3624

37-
else
38-
app.call(env)
39-
end
25+
strategy_info.create(@app, options) do |*args|
26+
env[Grape::Env::API_ENDPOINT].instance_exec(*args, &options[:proc])
27+
end.call(env)
4028
end
4129
end
4230
end

lib/grape/middleware/base.rb

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,18 @@
33
module Grape
44
module Middleware
55
class Base
6-
include Helpers
76
include Grape::DSL::Headers
87

98
attr_reader :app, :env, :options
109

1110
# @param [Rack Application] app The standard argument for a Rack middleware.
1211
# @param [Hash] options A hash of options, simply stored for use by subclasses.
13-
def initialize(app, *options)
12+
def initialize(app, **options)
1413
@app = app
15-
@options = options.any? ? default_options.deep_merge(options.shift) : default_options
14+
@options = merge_default_options(options)
1615
@app_response = nil
1716
end
1817

19-
def default_options
20-
{}
21-
end
22-
2318
def call(env)
2419
dup.call!(env).to_a
2520
end
@@ -56,10 +51,14 @@ def rack_request
5651
@rack_request ||= Rack::Request.new(env)
5752
end
5853

54+
def context
55+
env[Grape::Env::API_ENDPOINT]
56+
end
57+
5958
def response
6059
return @app_response if @app_response.is_a?(Rack::Response)
6160

62-
@app_response = Rack::Response.new(@app_response[2], @app_response[0], @app_response[1])
61+
@app_response = Rack::Response[*@app_response]
6362
end
6463

6564
def content_types
@@ -100,6 +99,16 @@ def merge_headers(response)
10099
def content_types_indifferent_access
101100
@content_types_indifferent_access ||= content_types.with_indifferent_access
102101
end
102+
103+
def merge_default_options(options)
104+
if respond_to?(:default_options)
105+
default_options.deep_merge(options)
106+
elsif self.class.const_defined?(:DEFAULT_OPTIONS)
107+
self.class::DEFAULT_OPTIONS.deep_merge(options)
108+
else
109+
options
110+
end
111+
end
103112
end
104113
end
105114
end

lib/grape/middleware/error.rb

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,22 @@
33
module Grape
44
module Middleware
55
class Error < Base
6-
def default_options
7-
{
8-
default_status: 500, # default status returned on error
9-
default_message: '',
10-
format: :txt,
11-
helpers: nil,
12-
formatters: {},
13-
error_formatters: {},
14-
rescue_all: false, # true to rescue all exceptions
15-
rescue_grape_exceptions: false,
16-
rescue_subclasses: true, # rescue subclasses of exceptions listed
17-
rescue_options: {
18-
backtrace: false, # true to display backtrace, true to let Grape handle Grape::Exceptions
19-
original_exception: false # true to display exception
20-
},
21-
rescue_handlers: {}, # rescue handler blocks
22-
base_only_rescue_handlers: {}, # rescue handler blocks rescuing only the base class
23-
all_rescue_handler: nil # rescue handler block to rescue from all exceptions
24-
}
25-
end
26-
27-
def initialize(app, *options)
6+
DEFAULT_OPTIONS = {
7+
default_status: 500,
8+
default_message: '',
9+
format: :txt,
10+
rescue_all: false,
11+
rescue_grape_exceptions: false,
12+
rescue_subclasses: true,
13+
rescue_options: {
14+
backtrace: false,
15+
original_exception: false
16+
}.freeze
17+
}.freeze
18+
19+
def initialize(app, **options)
2820
super
29-
self.class.include(@options[:helpers]) if @options[:helpers]
21+
self.class.include(options[:helpers]) if options[:helpers]
3022
end
3123

3224
def call!(env)

lib/grape/middleware/formatter.rb

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@
33
module Grape
44
module Middleware
55
class Formatter < Base
6-
def default_options
7-
{
8-
default_format: :txt,
9-
formatters: {},
10-
parsers: {}
11-
}
12-
end
6+
DEFAULT_OPTIONS = {
7+
default_format: :txt
8+
}.freeze
139

1410
def before
1511
negotiate_content_type

lib/grape/middleware/helpers.rb

Lines changed: 0 additions & 12 deletions
This file was deleted.

lib/grape/middleware/versioner/base.rb

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,20 @@ module Grape
44
module Middleware
55
module Versioner
66
class Base < Grape::Middleware::Base
7-
DEFAULT_PATTERN = /.*/i.freeze
8-
DEFAULT_PARAMETER = 'apiver'
7+
DEFAULT_OPTIONS = {
8+
pattern: /.*/i.freeze,
9+
version_options: {
10+
strict: false,
11+
cascade: true,
12+
parameter: 'apiver'
13+
}.freeze
14+
}.freeze
915

1016
def self.inherited(klass)
1117
super
1218
Versioner.register(klass)
1319
end
1420

15-
def default_options
16-
{
17-
versions: nil,
18-
prefix: nil,
19-
mount_path: nil,
20-
pattern: DEFAULT_PATTERN,
21-
version_options: {
22-
strict: false,
23-
cascade: true,
24-
parameter: DEFAULT_PARAMETER
25-
}
26-
}
27-
end
28-
2921
def versions
3022
options[:versions]
3123
end

spec/grape/middleware/base_spec.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,7 @@
141141
context 'defaults' do
142142
let(:example_ware) do
143143
Class.new(Grape::Middleware::Base) do
144-
def default_options
145-
{ monkey: true }
146-
end
144+
const_set(:DEFAULT_OPTIONS, { monkey: true }.freeze)
147145
end
148146
end
149147

spec/grape/middleware/error_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def call(_env)
2929
context = self
3030
Rack::Builder.app do
3131
use Spec::Support::EndpointFaker
32-
use Grape::Middleware::Error, opts # rubocop:disable RSpec/DescribedClass
32+
use Grape::Middleware::Error, **opts # rubocop:disable RSpec/DescribedClass
3333
run context.err_app
3434
end
3535
end

spec/grape/middleware/exception_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def call(_env)
6666
use Rack::Lint
6767
use Spec::Support::EndpointFaker
6868
if opts.any?
69-
use Grape::Middleware::Error, opts
69+
use Grape::Middleware::Error, **opts
7070
else
7171
use Grape::Middleware::Error
7272
end

spec/grape/middleware/formatter_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def to_xml
236236
end
237237

238238
it 'uses custom json formatter' do
239-
subject.options[:formatters][:json] = ->(_obj, _env) { 'CUSTOM JSON FORMAT' }
239+
subject.options[:formatters] = { json: ->(_obj, _env) { 'CUSTOM JSON FORMAT' } }
240240
r = Rack::MockResponse[*subject.call(Rack::PATH_INFO => '/info.json')]
241241
expect(r.body).to eq('CUSTOM JSON FORMAT')
242242
end

spec/grape/middleware/versioner/accept_version_header_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
describe Grape::Middleware::Versioner::AcceptVersionHeader do
4-
subject { described_class.new(app, @options) }
4+
subject { described_class.new(app, **@options) }
55

66
let(:app) { ->(env) { [200, env, env] } }
77

spec/grape/middleware/versioner/header_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
describe Grape::Middleware::Versioner::Header do
4-
subject { described_class.new(app, @options) }
4+
subject { described_class.new(app, **@options) }
55

66
let(:app) { ->(env) { [200, env, env] } }
77

spec/grape/middleware/versioner/param_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
describe Grape::Middleware::Versioner::Param do
4-
subject { described_class.new(app, options) }
4+
subject { described_class.new(app, **options) }
55

66
let(:app) { ->(env) { [200, env, env[Grape::Env::API_VERSION]] } }
77
let(:options) { {} }

spec/grape/middleware/versioner/path_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
describe Grape::Middleware::Versioner::Path do
4-
subject { described_class.new(app, options) }
4+
subject { described_class.new(app, **options) }
55

66
let(:app) { ->(env) { [200, env, env[Grape::Env::API_VERSION]] } }
77
let(:options) { {} }

spec/integration/grape_entity/entity_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ def call(_env)
348348
opts = options
349349
Rack::Builder.app do
350350
use Spec::Support::EndpointFaker
351-
use Grape::Middleware::Error, opts
351+
use Grape::Middleware::Error, **opts
352352
run ErrApp
353353
end
354354
end

0 commit comments

Comments
 (0)