Skip to content

Small refactor versioner middlewares #2584

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* [#2581](https://github.com/ruby-grape/grape/pull/2581): Delegate `to_s` in Grape::API::Instance - [@ericproulx](https://github.com/ericproulx).
* [#2582](https://github.com/ruby-grape/grape/pull/2582): Fix leaky slash when normalizing - [@ericproulx](https://github.com/ericproulx).
* [#2583](https://github.com/ruby-grape/grape/pull/2583): Optimize api parameter documentation and memory usage - [@ericproulx](https://github.com/ericproulx).
* [#2584](https://github.com/ruby-grape/grape/pull/2584): Small refactor versioner middlewares - [@ericproulx](https://github.com/ericproulx).
* Your contribution here.

#### Fixes
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/middleware/versioner/accept_version_header.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module Versioner
class AcceptVersionHeader < Base
def before
potential_version = env['HTTP_ACCEPT_VERSION'].try(:scrub)
not_acceptable!('Accept-Version header must be set.') if strict? && potential_version.blank?
not_acceptable!('Accept-Version header must be set.') if strict && potential_version.blank?

return if potential_version.blank?

Expand Down
64 changes: 23 additions & 41 deletions lib/grape/middleware/versioner/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,67 +6,49 @@ module Versioner
class Base < Grape::Middleware::Base
DEFAULT_OPTIONS = {
pattern: /.*/i,
prefix: nil,
mount_path: nil,
version_options: {
strict: false,
cascade: true,
parameter: 'apiver'
parameter: 'apiver',
vendor: nil
}.freeze
}.freeze

def self.inherited(klass)
super
Versioner.register(klass)
end

def versions
options[:versions]
end

def prefix
options[:prefix]
end

def mount_path
options[:mount_path]
end
CASCADE_PASS_HEADER = { 'X-Cascade' => 'pass' }.freeze

def pattern
options[:pattern]
DEFAULT_OPTIONS.each_key do |key|
define_method key do
options[key]
end
end

def version_options
options[:version_options]
DEFAULT_OPTIONS[:version_options].each_key do |key|
define_method key do
options[:version_options][key]
end
end

def strict?
version_options[:strict]
end

# By default those errors contain an `X-Cascade` header set to `pass`, which allows nesting and stacking
# of routes (see Grape::Router) for more information). To prevent
# this behavior, and not add the `X-Cascade` header, one can set the `:cascade` option to `false`.
def cascade?
version_options[:cascade]
end

def parameter_key
version_options[:parameter]
def self.inherited(klass)
super
Versioner.register(klass)
end

def vendor
version_options[:vendor]
end
attr_reader :error_headers, :versions

def error_headers
cascade? ? { 'X-Cascade' => 'pass' } : {}
def initialize(app, **options)
super
@error_headers = cascade ? CASCADE_PASS_HEADER : {}
@versions = options[:versions]&.map(&:to_s) # making sure versions are strings to ease potential match
end

def potential_version_match?(potential_version)
versions.blank? || versions.any? { |v| v.to_s == potential_version }
versions.blank? || versions.include?(potential_version)
end

def version_not_found!
throw :error, status: 404, message: '404 API Version Not Found', headers: { 'X-Cascade' => 'pass' }
throw :error, status: 404, message: '404 API Version Not Found', headers: CASCADE_PASS_HEADER
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/middleware/versioner/header.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def accept_header
end

def strict_header_checks!
return unless strict?
return unless strict

accept_header_check!
version_and_vendor_check!
Expand Down
4 changes: 2 additions & 2 deletions lib/grape/middleware/versioner/param.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ module Versioner
# env['api.version'] => 'v1'
class Param < Base
def before
potential_version = query_params[parameter_key]
potential_version = query_params[parameter]
return if potential_version.blank?

version_not_found! unless potential_version_match?(potential_version)
env[Grape::Env::API_VERSION] = env[Rack::RACK_REQUEST_QUERY_HASH].delete(parameter_key)
env[Grape::Env::API_VERSION] = env[Rack::RACK_REQUEST_QUERY_HASH].delete(parameter)
end
end
end
Expand Down