Module: Hanami::Action::Mime Private

Defined in:
lib/hanami/action/mime.rb,
lib/hanami/action/mime/request_mime_weight.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Since:

  • 0.1.0

Defined Under Namespace

Classes: Format, RequestMimeWeight

Constant Summary collapse

TYPES =

Most commom media types used for responses

Since:

  • 1.0.0

{
  atom: "application/atom+xml",
  avi: "video/x-msvideo",
  bmp: "image/bmp",
  bz2: "application/x-bzip2",
  bz: "application/x-bzip",
  chm: "application/vnd.ms-htmlhelp",
  css: "text/css",
  csv: "text/csv",
  flv: "video/x-flv",
  form: "application/x-www-form-urlencoded",
  gif: "image/gif",
  gz: "application/x-gzip",
  h264: "video/h264",
  html: "text/html",
  ico: "image/vnd.microsoft.icon",
  ics: "text/calendar",
  jpg: "image/jpeg",
  js: "application/javascript",
  json: "application/json",
  manifest: "text/cache-manifest",
  mov: "video/quicktime",
  mp3: "audio/mpeg",
  mp4: "video/mp4",
  mp4a: "audio/mp4",
  mpg: "video/mpeg",
  multipart: "multipart/form-data",
  oga: "audio/ogg",
  ogg: "application/ogg",
  ogv: "video/ogg",
  pdf: "application/pdf",
  pgp: "application/pgp-encrypted",
  png: "image/png",
  psd: "image/vnd.adobe.photoshop",
  rss: "application/rss+xml",
  rtf: "application/rtf",
  sh: "application/x-sh",
  svg: "image/svg+xml",
  swf: "application/x-shockwave-flash",
  tar: "application/x-tar",
  torrent: "application/x-bittorrent",
  tsv: "text/tab-separated-values",
  txt: "text/plain",
  uri: "text/uri-list",
  vcs: "text/x-vcalendar",
  wav: "audio/x-wav",
  webm: "video/webm",
  wmv: "video/x-ms-wmv",
  woff2: "application/font-woff2",
  woff: "application/font-woff",
  wsdl: "application/wsdl+xml",
  xhtml: "application/xhtml+xml",
  xml: "application/xml",
  xslt: "application/xslt+xml",
  yml: "text/yaml",
  zip: "application/zip"
}.freeze
ANY_TYPE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 0.1.0

"*/*"

Class Method Summary collapse

Class Method Details

.accepted_content_type?(content_type, config) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks if a content type is acceptable for the configured formats.

Parameters:

Returns:

  • (Boolean)

    true if acceptable

Since:

  • 0.1.0



315
316
317
318
319
# File 'lib/hanami/action/mime.rb', line 315

def accepted_content_type?(content_type, config)
  accepted_content_types(config).any? { |accepted_content_type|
    ::Rack::Mime.match?(content_type, accepted_content_type)
  }
end

.best_q_match(q_value_header, available_mimes) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Patched version of Rack::Utils.best_q_match.



299
300
301
302
303
304
305
306
# File 'lib/hanami/action/mime.rb', line 299

def best_q_match(q_value_header, available_mimes)
  ::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

.content_type_with_charset(content_type, charset) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a string combining the given content type and charset, intended for setting as a ‘Content-Type` header.

Examples:

Mime.content_type_with_charset("application/json", "utf-8")
# => "application/json; charset=utf-8"

Parameters:

  • content_type (String)
  • charset (String)

Returns:

  • (String)

Since:

  • 0.1.0



265
266
267
# File 'lib/hanami/action/mime.rb', line 265

def content_type_with_charset(content_type, charset)
  "#{content_type}; charset=#{charset}"
end

.default_response_content_type_with_charset(config) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the default response Content-Type (with charset) for a request without a usable ‘Accept` header. This depends only on config, so an action can compute it once and reuse it across requests instead of recomputing per call.

Returns:

  • (String)

See Also:

Since:

  • 0.1.0



186
187
188
189
190
191
# File 'lib/hanami/action/mime.rb', line 186

def default_response_content_type_with_charset(config)
  content_type_with_charset(
    default_response_content_type(config),
    config.default_charset || Action::DEFAULT_CHARSET
  )
end

.enforce_accept(request, config) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Yields if an action is configured with ‘formats`, the request has an `Accept` header, and 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 Also:

Since:

  • 0.1.0



127
128
129
130
131
132
133
134
# File 'lib/hanami/action/mime.rb', line 127

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? { |type| accepted_type?(type, config) }

  yield
end

.enforce_content_type(request, config) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Yields if an action is configured with ‘formats`, the request has a `Content-Type` header, 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 Also:

Since:

  • 0.1.0



147
148
149
150
151
152
153
154
155
156
157
# File 'lib/hanami/action/mime.rb', line 147

def enforce_content_type(request, config)
  # Compare media type (without parameters) instead of full Content-Type header to avoid
  # false negatives (e.g., multipart/form-data; boundary=...)
  media_type = request.media_type

  return if media_type.nil?

  return if accepted_content_type?(media_type, config)

  yield
end

.extract_media_type(content_type) ⇒ String?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Extracts the media type from a Content-Type header value, removing parameters like charset, boundary, etc.

Examples:

extract_media_type("application/json; charset=utf-8")
# => "application/json"

extract_media_type("multipart/form-data; boundary=----WebKitFormBoundary")
# => "multipart/form-data"

Parameters:

  • content_type (String, nil)

    the Content-Type header value

Returns:

  • (String, nil)

    the media type without parameters, downcased

Since:

  • 0.1.0



283
284
285
286
287
288
# File 'lib/hanami/action/mime.rb', line 283

def extract_media_type(content_type)
  return nil if content_type.nil? || content_type.empty?

  # Strip charset, boundary, and other parameters (separated by semicolon)
  content_type.split(";", 2).first.strip.downcase
end

.format_and_media_type(value, config) ⇒ Array<(Symbol, String)>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a format name and content type pair for a given format name or content type string.

Examples:

format_and_media_type(:json, config)
# => [:json, "application/json"]

format_and_media_type("application/json", config)
# => [:json, "application/json"]

Unknown format name

format_and_media_type(:unknown, config)
# raises Hanami::Action::UnknownFormatError

Unknown content type

format_and_media_type("application/unknown", config)
# => [nil, "application/unknown"]

Returns:

  • (Array<(Symbol, String)>)

Raises:

Since:

  • 0.1.0



241
242
243
244
245
246
247
248
249
250
# File 'lib/hanami/action/mime.rb', line 241

def format_and_media_type(value, config)
  case value
  when Symbol
    [value, format_to_media_type(value, config)]
  when String
    [format_from_media_type(value, config), value]
  else
    raise UnknownFormatError.new(value)
  end
end

.format_from_media_type(media_type, config) ⇒ Symbol?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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.

Examples:

format_from_media_type("application/json;charset=utf-8", config) # => :json

Returns:

  • (Symbol, nil)

See Also:

Since:

  • 0.1.0



211
212
213
214
215
216
# File 'lib/hanami/action/mime.rb', line 211

def format_from_media_type(media_type, config)
  return if media_type.nil?

  mt = extract_media_type(media_type)
  config.formats.format_for(mt) || MEDIA_TYPES_TO_FORMATS[mt]&.name
end

.response_content_type_with_charset(request, config) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a string combining a media 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.

Returns:

  • (String)

See Also:

Since:

  • 0.1.0



170
171
172
173
174
175
# File 'lib/hanami/action/mime.rb', line 170

def response_content_type_with_charset(request, config)
  content_type_with_charset(
    response_content_type(request, config),
    config.default_charset || Action::DEFAULT_CHARSET
  )
end