ruby-grape/grape

View on GitHub
lib/grape/middleware/versioner/header.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

require 'grape/middleware/base'
require 'grape/util/media_type'
require 'grape/util/accept_header_handler'

module Grape
  module Middleware
    module Versioner
      # This middleware sets various version related rack environment variables
      # based on the HTTP Accept header with the pattern:
      # application/vnd.:vendor-:version+:format
      #
      # Example: For request header
      #    Accept: application/vnd.mycompany.a-cool-resource-v1+json
      #
      # The following rack env variables are set:
      #
      #    env['api.type']    => 'application'
      #    env['api.subtype'] => 'vnd.mycompany.a-cool-resource-v1+json'
      #    env['api.vendor]   => 'mycompany.a-cool-resource'
      #    env['api.version]  => 'v1'
      #    env['api.format]   => 'json'
      #
      # If version does not match this route, then a 406 is raised with
      # X-Cascade header to alert Grape::Router to attempt the next matched
      # route.
      class Header < Base
        def before
          handler = Grape::Util::AcceptHeaderHandler.new(
            accept_header: env[Grape::Http::Headers::HTTP_ACCEPT],
            versions: options[:versions],
            **options.fetch(:version_options) { {} }
          )

          handler.match_best_quality_media_type!(
            content_types: content_types,
            allowed_methods: env[Grape::Env::GRAPE_ALLOWED_METHODS]
          ) do |media_type|
            env[Grape::Env::API_TYPE] = media_type.type
            env[Grape::Env::API_SUBTYPE] = media_type.subtype
            env[Grape::Env::API_VENDOR] = media_type.vendor
            env[Grape::Env::API_VERSION] = media_type.version
            env[Grape::Env::API_FORMAT] = media_type.format
          end
        end
      end
    end
  end
end