Skip to content

Dynamic registration #2516

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

Merged
merged 19 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Add Grape::Middleware::Versioner::Base and use Grape::Util::Registry
  • Loading branch information
ericproulx committed Dec 15, 2024
commit 93fcb57320e1a13bfbbed22343d832fc95cee93e
8 changes: 5 additions & 3 deletions lib/grape/middleware/versioner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@
module Grape
module Middleware
module Versioner
extend Grape::Util::Registry

module_function

# @param strategy [Symbol] :path, :header, :accept_version_header or :param
# @return a middleware class based on strategy
def using(strategy)
Grape::Middleware::Versioner.const_get(:"#{strategy.to_s.camelize}")
rescue NameError
raise Grape::Exceptions::InvalidVersionerOption, strategy
raise Grape::Exceptions::InvalidVersionerOption, strategy unless registry.key?(strategy)

registry[strategy]
end
end
end
Expand Down
2 changes: 0 additions & 2 deletions lib/grape/middleware/versioner/accept_version_header.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ module Versioner
# X-Cascade header to alert Grape::Router to attempt the next matched
# route.
class AcceptVersionHeader < Base
include VersionerHelpers

def before
potential_version = env[Grape::Http::Headers::HTTP_ACCEPT_VERSION]&.strip
not_acceptable!('Accept-Version header must be set.') if strict? && potential_version.blank?
Expand Down
85 changes: 85 additions & 0 deletions lib/grape/middleware/versioner/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# frozen_string_literal: true

module Grape
module Middleware
module Versioner
class Base < Grape::Middleware::Base
DEFAULT_PATTERN = /.*/i.freeze
DEFAULT_PARAMETER = 'apiver'

def self.inherited(klass)
super
return if klass.name.blank?

short_name = klass.name.demodulize.underscore
Versioner.register(short_name, klass)
end

def default_options
{
versions: nil,
prefix: nil,
mount_path: nil,
pattern: DEFAULT_PATTERN,
version_options: {
strict: false,
cascade: true,
parameter: DEFAULT_PARAMETER
}
}
end

def versions
options[:versions]
end

def prefix
options[:prefix]
end

def mount_path
options[:mount_path]
end

def pattern
options[:pattern]
end

def version_options
options[:version_options]
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]
end

def vendor
version_options[:vendor]
end

def error_headers
cascade? ? { Grape::Http::Headers::X_CASCADE => 'pass' } : {}
end

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

def version_not_found!
throw :error, status: 404, message: '404 API Version Not Found', headers: { Grape::Http::Headers::X_CASCADE => 'pass' }
end
end
end
end
end
2 changes: 0 additions & 2 deletions lib/grape/middleware/versioner/header.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ module Versioner
# X-Cascade header to alert Grape::Router to attempt the next matched
# route.
class Header < Base
include VersionerHelpers

def before
match_best_quality_media_type! do |media_type|
env.update(
Expand Down
2 changes: 0 additions & 2 deletions lib/grape/middleware/versioner/param.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ module Versioner
#
# env['api.version'] => 'v1'
class Param < Base
include VersionerHelpers

def before
potential_version = Rack::Utils.parse_nested_query(env[Rack::QUERY_STRING])[parameter_key]
return if potential_version.blank?
Expand Down
2 changes: 0 additions & 2 deletions lib/grape/middleware/versioner/path.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ module Versioner
# env['api.version'] => 'v1'
#
class Path < Base
include VersionerHelpers

def before
path_info = Grape::Router.normalize_path(env[Rack::PATH_INFO])
return if path_info == '/'
Expand Down
75 changes: 0 additions & 75 deletions lib/grape/middleware/versioner_helpers.rb

This file was deleted.