Class: Grape::Middleware::Versioner::Header
- Defined in:
- lib/grape/middleware/versioner/header.rb
Overview
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-v1+json
The following rack env variables are set:
env['api.type'] => 'application'
env['api.subtype'] => 'vnd.mycompany-v1+json'
env['api.vendor] => 'mycompany'
env['api.version] => 'v1'
env['api.format] => 'format'
If version does not match this route, then a 406 is throw with X-Cascade header to alert Rack::Mount to attempt the next matched route.
Constant Summary
Constants inherited from Base
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
Methods inherited from Base
#after, #call, #call!, #content_type, #content_types, #default_options, #initialize, #mime_types, #request, #response
Constructor Details
This class inherits a constructor from Grape::Middleware::Base
Instance Method Details
#before ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/grape/middleware/versioner/header.rb', line 29 def before header = Rack::Accept::MediaType.new env['HTTP_ACCEPT'] if strict? # If no Accept header: if header.qvalues.empty? throw :error, :status => 406, :headers => {'X-Cascade' => 'pass'}, :message => 'Accept header must be set' end # Remove any acceptable content types with ranges. header.qvalues.reject! do |media_type,_| Rack::Accept::Header.parse_media_type(media_type).find{|s| s == '*'} end # If all Accept headers included a range: if header.qvalues.empty? throw :error, :status => 406, :headers => {'X-Cascade' => 'pass'}, :message => 'Accept header must not contain ranges ("*")' end end media_type = header.best_of available_media_types if media_type type, subtype = Rack::Accept::Header.parse_media_type media_type env['api.type'] = type env['api.subtype'] = subtype if /\Avnd\.([a-z0-9*.]+)(?:-([a-z0-9*\-.]+))?(?:\+([a-z0-9*\-.+]+))?\z/ =~ subtype env['api.vendor'] = $1 env['api.version'] = $2 env['api.format'] = $3 # weird that Grape::Middleware::Formatter also does this end # If none of the available content types are acceptable: elsif strict? throw :error, :status => 406, :headers => {'X-Cascade' => 'pass'}, :message => '406 Not Acceptable' # If all acceptable content types specify a vendor or version that doesn't exist: elsif header.values.all?{|media_type| has_vendor?(media_type) || has_version?(media_type)} throw :error, :status => 406, :headers => {'X-Cascade' => 'pass'}, :message => 'API vendor or version not found' end end |