ruby-grape / ruby-grape/grape

Modify the VENDOR_VERSION_HEADER_REGEX to support/recognize matches on the HAL (hal+json) format

Open
#1,382 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug?
Dominant language
Ruby
Stars
10k
Forks
1.2k
Avg merge
14h 38m
Merged PRs (30d)
92

Description

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...
end

Example 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
  ......
end

We'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/

image

NEW REGEX
VENDOR_VERSION_HEADER_REGEX =

  /\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))?(?:\+([a-z0-9*\-.+]+))+\z/

image

It'd be useful to add this change, so that grape supports the hal format out of the box without any custom work needed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in lib/grape/middleware/versioner/header.rb, focusing on VENDOR_VERSION_HEADER_REGEX and an_accept_header_with_version_and_vendor_is_present?. Review the existing header versioning behavior for vendor media types, then verify that an Accept header containing application/vnd.foo-v1+hal+json is recognized without breaking existing formats.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
api
Issue type
Feature
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.