Modify the VENDOR_VERSION_HEADER_REGEX to support/recognize matches on the HAL (hal+json) format
I have an endpoint which will only respond to hal format (application/hal+json) as specified in HAL's official page
Given the following:
class Foo < Grape::API
version 'v1', using: :header, vendor: 'foo', strict: true, cascade: false
content_type :hal, 'application/hal+json'
format :hal
formatter :hal, Grape::Formatter::Roar
...rest of code goes here...
endExample Request: curl -H 'Accept: application/vnd.foo-v1+hal+json' http://www.foobar.com/api/foo
In /lib/grape/middleware/versioner/header.rb#, an_accept_header_with_version_and_vendor_is_present? returns false because the regex doesn't match against the full format which is hal+json
class Header < Base
VENDOR_VERSION_HEADER_REGEX =
/\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))?(?:\+([a-z0-9*\-.]+))?\z/
HAS_VENDOR_REGEX = /\Avnd\.[a-z0-9.\-_!#\$&\^]+/
HAS_VERSION_REGEX = /\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))+/
def before
strict_header_checks if strict?
if media_type
media_type_header_handler
elsif headers_contain_wrong_vendor?
fail_with_invalid_accept_header!('API vendor not found.')
elsif headers_contain_wrong_version?
fail_with_invalid_version_header!('API version not found.')
end
end
private
def strict_header_checks
strict_accept_header_presence_check
strict_version_vendor_accept_header_presence_check
end
def strict_accept_header_presence_check
return unless header.qvalues.empty?
fail_with_invalid_accept_header!('Accept header must be set.')
end
def strict_version_vendor_accept_header_presence_check
return unless versions.present?
return if an_accept_header_with_version_and_vendor_is_present?
fail_with_invalid_accept_header!('API vendor or version not found.')
end
def an_accept_header_with_version_and_vendor_is_present?
header.qvalues.keys.any? do |h|
VENDOR_VERSION_HEADER_REGEX =~ h.sub('application/', '')
end
end
......
endWe'd need to modify VENDOR_VERSION_HEADER_REGEX to allow matching of these types of formats (hal+format)
I've modified the regex to allow match on said types:
OLD VENDOR_VERSION_HEADER_REGEX =
/\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))?(?:\+([a-z0-9*\-.]+))?\z/
NEW REGEX VENDOR_VERSION_HEADER_REGEX =
/\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))?(?:\+([a-z0-9*\-.+]+))+\z/
It'd be useful to add this change, so that grape supports the hal format out of the box without any custom work needed.
Source: ruby-grape/grape