module Hanami::Action::Mime
Constants
- ANY_TYPE
- TYPES
Most commom MIME Types used for responses
@since 1.0.0 @api private
Public Class Methods
Patched version of Rack::Utils.best_q_match
.
@since 2.0.0 @api private
@see www.rubydoc.info/gems/rack/Rack/Utils#best_q_match-class_method @see github.com/rack/rack/pull/659 @see github.com/hanami/controller/issues/59 @see github.com/hanami/controller/issues/104 @see github.com/hanami/controller/issues/275
# File lib/hanami/action/mime.rb, line 182 def best_q_match(q_value_header, available_mimes = TYPES.values) ::Rack::Utils.q_values(q_value_header).each_with_index.map { |(req_mime, quality), index| match = available_mimes.find { |am| ::Rack::Mime.match?(am, req_mime) } next unless match RequestMimeWeight.new(req_mime, quality, index, match) }.compact.max&.format end
Returns a string combining the given content type and charset, intended for setting as a ‘Content-Type` header.
@example
Mime.content_type_with_charset("application/json", "utf-8") # => "application/json; charset=utf-8"
@param content_type [String] @param charset [String]
@return [String]
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 149 def content_type_with_charset(content_type, charset) "#{content_type}; charset=#{charset}" end
Returns a format name for the given content type.
The format name will come from the configured formats, if such a format is configured there, or instead from the default list of formats in ‘Mime::TYPES`.
Returns nil if no matching format can be found.
This is used to return the format name a {Response}.
@example
detect_format("application/jsonl charset=utf-8", config) # => :json
@return [Symbol, nil]
@see Response#format
@see Action#finish
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 93 def detect_format(content_type, config) return if content_type.nil? ct = content_type.split(";").first config.formats.format_for(ct) || TYPES.key(ct) end
Returns a format name and content type pair for a given format name or content type string.
@example
detect_format_and_content_type(:json, config) # => [:json, "application/json"] detect_format_and_content_type("application/json", config) # => [:json, "application/json"]
@example Unknown format name
detect_format_and_content_type(:unknown, config) # raises Hanami::Action::UnknownFormatError
@example Unknown content type
detect_format_and_content_type("application/unknown", config) # => [nil, "application/unknown"]
@return [Array<(Symbol, String)>]
@raise [Hanami::Action::UnknownFormatError] if an unknown format name is given
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 124 def detect_format_and_content_type(value, config) case value when Symbol [value, format_to_mime_type(value, config)] when String [detect_format(value, config), value] else raise UnknownFormatError.new(value) end end
Yields if an action is configured with ‘formats`, the request has an `Accept` header, an none of the Accept types matches the accepted formats. The given block is expected to halt the request handling.
If any of these conditions are not met, then the request is acceptable and the method returns without yielding.
@see Action#enforce_accepted_mime_types
@see Config#formats
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 203 def enforce_accept(request, config) return unless request.accept_header? accept_types = ::Rack::Utils.q_values(request.accept).map(&:first) return if accept_types.any? { |mime_type| accepted_mime_type?(mime_type, config) } yield end
Yields if an action is configured with ‘formats`, the request has a `Content-Type` header (or a `default_requst_format` is configured), and the content type does not match the accepted formats. The given block is expected to halt the request handling.
If any of these conditions are not met, then the request is acceptable and the method returns without yielding.
@see Action#enforce_accepted_mime_types
@see Config#formats
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 224 def enforce_content_type(request, config) content_type = request.content_type return if content_type.nil? return if accepted_mime_type?(content_type, config) yield end
Returns a string combining a MIME type and charset, intended for setting as the ‘Content-Type` header for the response to the given request.
This uses the request’s ‘Accept` header (if present) along with the configured formats to determine the best content type to return.
@return [String]
@see Action#call
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 165 def response_content_type_with_charset(request, config) content_type_with_charset( response_content_type(request, config), config.default_charset || Action::DEFAULT_CHARSET ) end
Private Class Methods
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 238 def accepted_mime_type?(mime_type, config) accepted_mime_types(config).any? { |accepted_mime_type| ::Rack::Mime.match?(mime_type, accepted_mime_type) } end
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 246 def accepted_mime_types(config) return [ANY_TYPE] if config.formats.empty? config.formats.map { |format| format_to_mime_types(format, config) }.flatten(1) end
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 271 def format_to_mime_type(format, config) config.formats.mime_type_for(format) || TYPES.fetch(format) { raise Hanami::Action::UnknownFormatError.new(format) } end
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 278 def format_to_mime_types(format, config) config.formats.mime_types_for(format).tap { |types| types << TYPES[format] if TYPES.key?(format) } end
@since 2.0.0 @api private
# File lib/hanami/action/mime.rb, line 254 def response_content_type(request, config) if request.accept_header? all_mime_types = TYPES.values + config.formats.mapping.keys content_type = best_q_match(request.accept, all_mime_types) return content_type if content_type end if config.formats.default return format_to_mime_type(config.formats.default, config) end Action::DEFAULT_CONTENT_TYPE end