Keep a :version path capture when the API declares no version - #2846
Open
ericproulx wants to merge 1 commit into
Open
Keep a :version path capture when the API declares no version#2846ericproulx wants to merge 1 commit into
ericproulx wants to merge 1 commit into
Conversation
Grape::Request#make_params dropped :version from the routing args
unconditionally, alongside :route_info. That is right when Grape put it
there -- a path-versioned API captures the version as a segment and exposes
it through env['api.version'] rather than params -- but it is not always
Grape's.
An API that declares no version can name a param :version:
route_param :version do
get { params[:version] } # => nil
end
The route matched and Mustermann captured the segment, but the value was
filtered out before the endpoint saw it, so params[:version] came back nil
and the key was absent from params entirely. Same for a bare
get '/:version'. Silent loss of a segment on a route that had matched.
A route reports a #version only when the API declared one, so use that to
tell the two apart: drop the capture when the route carries a version,
keep it otherwise. Path, header and param versioning are unaffected --
their routes all report a version, so :version stays out of params and
env['api.version'] remains the way to read it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ericproulx
force-pushed
the
fix/route-param-named-version
branch
from
August 1, 2026 11:52
fe9290e to
09abf2b
Compare
Danger ReportErrors
Markdowns* [#UUUU](https://github.com/ruby-grape/grape/pull/UUUU): Keep a `:version` path capture in `params` when the API declares no version, instead of always dropping it as Grape's own - [@ericproulx](https://github.com/ericproulx).
does not include a pull request link |
Danger ReportNo issues found. |
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Grape::Request#make_paramsdropped:versionfrom the routing args unconditionally, alongside:route_info:That is right when Grape put it there — a path-versioned API captures the version as a segment and exposes it through
env['api.version']rather thanparams. But it is not always Grape's. An API that declares no version can name a param:version:GET /abcmatched, Mustermann capturedversion => "abc", and the value was filtered out before the endpoint saw it —params[:version]nil and the key absent fromparamsaltogether. Same for a bareget '/:version'. A segment silently lost on a route that had matched.params[:version]beforeroute_param :version"abc"get '/:version'"abc"version 'v1', using: :pathversion 'v1', using: :headerversion 'v1', using: :paramApproach
A route reports a
#versiononly when the API declared one —Grape::Router::BaseRoutealready delegates it to the pattern — so that distinguishes the two cases without any new API. Drop the capture when the route carries a version, keep it otherwise.All three versioning strategies are unaffected: their routes report a version, so
:versionstays out ofparamsandenv['api.version']remains the way to read it. A path-versioned API with a nestedroute_param :idstill gets onlyid.Backward compatibility
No UPGRADING entry. The change only adds a param that was being discarded, on APIs that declare no version — where nothing could have depended on it being absent, since the route matched but the value was unreachable.
request_spec.rb's "cuts version and route_info" asserted the old unconditional rule against a syntheticroute_info; it now covers both branches with a route double that does and does not report a version.Longstanding, not a regression: identical in 3.3.4.
Test plan
request_spec.rbsplit into version-carrying and version-less routes; verified the version-less case fails without thelib/change.🤖 Generated with Claude Code