actionpack 4.2.10 → 7.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +86 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -14
- data/lib/abstract_controller/asset_paths.rb +5 -1
- data/lib/abstract_controller/base.rb +166 -136
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +126 -57
- data/lib/abstract_controller/collector.rb +13 -15
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +181 -132
- data/lib/abstract_controller/logger.rb +5 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
- data/lib/abstract_controller/rendering.rb +56 -56
- data/lib/abstract_controller/translation.rb +29 -15
- data/lib/abstract_controller/url_for.rb +15 -11
- data/lib/abstract_controller.rb +21 -5
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +154 -0
- data/lib/action_controller/base.rb +219 -155
- data/lib/action_controller/caching.rb +28 -68
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +35 -22
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +259 -122
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +9 -5
- data/lib/action_controller/metal/data_streaming.rb +87 -104
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
- data/lib/action_controller/metal/exceptions.rb +71 -24
- data/lib/action_controller/metal/flash.rb +26 -19
- data/lib/action_controller/metal/head.rb +45 -36
- data/lib/action_controller/metal/helpers.rb +80 -64
- data/lib/action_controller/metal/http_authentication.rb +297 -244
- data/lib/action_controller/metal/implicit_render.rb +57 -9
- data/lib/action_controller/metal/instrumentation.rb +76 -64
- data/lib/action_controller/metal/live.rb +238 -176
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +177 -166
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +145 -118
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +203 -64
- data/lib/action_controller/metal/renderers.rb +108 -65
- data/lib/action_controller/metal/rendering.rb +216 -56
- data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
- data/lib/action_controller/metal/rescue.rb +19 -21
- data/lib/action_controller/metal/streaming.rb +179 -138
- data/lib/action_controller/metal/strong_parameters.rb +1058 -382
- data/lib/action_controller/metal/testing.rb +11 -17
- data/lib/action_controller/metal/url_for.rb +37 -21
- data/lib/action_controller/metal.rb +236 -138
- data/lib/action_controller/railtie.rb +89 -11
- data/lib/action_controller/railties/helpers.rb +5 -1
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +425 -497
- data/lib/action_controller.rb +44 -22
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +119 -63
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +364 -0
- data/lib/action_dispatch/http/filter_parameters.rb +36 -34
- data/lib/action_dispatch/http/filter_redirect.rb +24 -12
- data/lib/action_dispatch/http/headers.rb +66 -31
- data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
- data/lib/action_dispatch/http/mime_type.rb +196 -136
- data/lib/action_dispatch/http/mime_types.rb +25 -7
- data/lib/action_dispatch/http/parameters.rb +97 -45
- data/lib/action_dispatch/http/permissions_policy.rb +187 -0
- data/lib/action_dispatch/http/rack_cache.rb +6 -0
- data/lib/action_dispatch/http/request.rb +299 -170
- data/lib/action_dispatch/http/response.rb +311 -160
- data/lib/action_dispatch/http/upload.rb +52 -23
- data/lib/action_dispatch/http/url.rb +201 -125
- data/lib/action_dispatch/journey/formatter.rb +110 -50
- data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
- data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
- data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
- data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
- data/lib/action_dispatch/journey/nodes/node.rb +100 -20
- data/lib/action_dispatch/journey/parser.rb +19 -17
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +14 -4
- data/lib/action_dispatch/journey/path/pattern.rb +79 -63
- data/lib/action_dispatch/journey/route.rb +108 -44
- data/lib/action_dispatch/journey/router/utils.rb +41 -29
- data/lib/action_dispatch/journey/router.rb +64 -57
- data/lib/action_dispatch/journey/routes.rb +23 -21
- data/lib/action_dispatch/journey/scanner.rb +28 -17
- data/lib/action_dispatch/journey/visitors.rb +100 -54
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +7 -6
- data/lib/action_dispatch/middleware/cookies.rb +471 -328
- data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +143 -101
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
- data/lib/action_dispatch/middleware/reloader.rb +10 -92
- data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
- data/lib/action_dispatch/middleware/request_id.rb +29 -15
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
- data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
- data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
- data/lib/action_dispatch/middleware/ssl.rb +134 -36
- data/lib/action_dispatch/middleware/stack.rb +109 -44
- data/lib/action_dispatch/middleware/static.rb +159 -90
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
- data/lib/action_dispatch/railtie.rb +44 -16
- data/lib/action_dispatch/request/session.rb +159 -69
- data/lib/action_dispatch/request/utils.rb +97 -23
- data/lib/action_dispatch/routing/endpoint.rb +11 -2
- data/lib/action_dispatch/routing/inspector.rb +195 -106
- data/lib/action_dispatch/routing/mapper.rb +1338 -955
- data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
- data/lib/action_dispatch/routing/redirection.rb +78 -51
- data/lib/action_dispatch/routing/route_set.rb +460 -374
- data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
- data/lib/action_dispatch/routing/url_for.rb +172 -124
- data/lib/action_dispatch/routing.rb +159 -158
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +84 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +71 -39
- data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
- data/lib/action_dispatch/testing/assertions.rb +9 -6
- data/lib/action_dispatch/testing/integration.rb +486 -306
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +35 -22
- data/lib/action_dispatch/testing/test_request.rb +29 -34
- data/lib/action_dispatch/testing/test_response.rb +48 -15
- data/lib/action_dispatch.rb +82 -40
- data/lib/action_pack/gem_version.rb +8 -4
- data/lib/action_pack/version.rb +6 -2
- data/lib/action_pack.rb +21 -18
- metadata +146 -56
- data/lib/action_controller/caching/fragments.rb +0 -103
- data/lib/action_controller/metal/force_ssl.rb +0 -97
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/http/parameter_filter.rb +0 -72
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,23 +1,45 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "singleton"
|
5
6
|
|
6
7
|
module Mime
|
7
|
-
class Mimes
|
8
|
-
|
9
|
-
|
8
|
+
class Mimes
|
9
|
+
attr_reader :symbols
|
10
|
+
|
11
|
+
include Enumerable
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@mimes = []
|
15
|
+
@symbols = []
|
16
|
+
@symbols_set = Set.new
|
10
17
|
end
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
def each(&block)
|
20
|
+
@mimes.each(&block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def <<(type)
|
24
|
+
@mimes << type
|
25
|
+
sym_type = type.to_sym
|
26
|
+
@symbols << sym_type
|
27
|
+
@symbols_set << sym_type
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete_if
|
31
|
+
@mimes.delete_if do |x|
|
32
|
+
if yield x
|
33
|
+
sym_type = x.to_sym
|
34
|
+
@symbols.delete(sym_type)
|
35
|
+
@symbols_set.delete(sym_type)
|
36
|
+
true
|
19
37
|
end
|
20
|
-
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid_symbols?(symbols) # :nodoc
|
42
|
+
symbols.all? { |s| @symbols_set.include?(s) }
|
21
43
|
end
|
22
44
|
end
|
23
45
|
|
@@ -31,42 +53,48 @@ module Mime
|
|
31
53
|
Type.lookup_by_extension(type)
|
32
54
|
end
|
33
55
|
|
34
|
-
def
|
56
|
+
def symbols
|
57
|
+
SET.symbols
|
58
|
+
end
|
59
|
+
|
60
|
+
def valid_symbols?(symbols) # :nodoc:
|
61
|
+
SET.valid_symbols?(symbols)
|
62
|
+
end
|
63
|
+
|
64
|
+
def fetch(type, &block)
|
35
65
|
return type if type.is_a?(Type)
|
36
|
-
EXTENSION_LOOKUP.fetch(type.to_s)
|
66
|
+
EXTENSION_LOOKUP.fetch(type.to_s, &block)
|
37
67
|
end
|
38
68
|
end
|
39
69
|
|
40
|
-
# Encapsulates the notion of a
|
70
|
+
# Encapsulates the notion of a MIME type. Can be used at render time, for
|
71
|
+
# example, with:
|
41
72
|
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
73
|
+
# class PostsController < ActionController::Base
|
74
|
+
# def show
|
75
|
+
# @post = Post.find(params[:id])
|
45
76
|
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
77
|
+
# respond_to do |format|
|
78
|
+
# format.html
|
79
|
+
# format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") }
|
80
|
+
# format.xml { render xml: @post }
|
81
|
+
# end
|
50
82
|
# end
|
51
83
|
# end
|
52
|
-
# end
|
53
84
|
class Type
|
54
|
-
@@html_types = Set.new [:html, :all]
|
55
|
-
cattr_reader :html_types
|
56
|
-
|
57
85
|
attr_reader :symbol
|
58
86
|
|
59
87
|
@register_callbacks = []
|
60
88
|
|
61
|
-
# A simple helper class used in parsing the accept header
|
62
|
-
class AcceptItem
|
89
|
+
# A simple helper class used in parsing the accept header.
|
90
|
+
class AcceptItem # :nodoc:
|
63
91
|
attr_accessor :index, :name, :q
|
64
92
|
alias :to_s :name
|
65
93
|
|
66
94
|
def initialize(index, name, q = nil)
|
67
95
|
@index = index
|
68
96
|
@name = name
|
69
|
-
q ||= 0.0 if @name ==
|
97
|
+
q ||= 0.0 if @name == "*/*" # Default wildcard match to end of list.
|
70
98
|
@q = ((q || 1.0).to_f * 100).to_i
|
71
99
|
end
|
72
100
|
|
@@ -75,77 +103,72 @@ module Mime
|
|
75
103
|
result = @index <=> item.index if result == 0
|
76
104
|
result
|
77
105
|
end
|
78
|
-
|
79
|
-
def ==(item)
|
80
|
-
@name == item.to_s
|
81
|
-
end
|
82
106
|
end
|
83
107
|
|
84
|
-
class AcceptList
|
85
|
-
def
|
86
|
-
sort!
|
108
|
+
class AcceptList # :nodoc:
|
109
|
+
def self.sort!(list)
|
110
|
+
list.sort!
|
87
111
|
|
88
|
-
|
112
|
+
text_xml_idx = find_item_by_name list, "text/xml"
|
113
|
+
app_xml_idx = find_item_by_name list, Mime[:xml].to_s
|
114
|
+
|
115
|
+
# Take care of the broken text/xml entry by renaming or deleting it.
|
89
116
|
if text_xml_idx && app_xml_idx
|
90
|
-
app_xml
|
91
|
-
|
92
|
-
|
117
|
+
app_xml = list[app_xml_idx]
|
118
|
+
text_xml = list[text_xml_idx]
|
119
|
+
|
120
|
+
app_xml.q = [text_xml.q, app_xml.q].max # Set the q value to the max of the two.
|
121
|
+
if app_xml_idx > text_xml_idx # Make sure app_xml is ahead of text_xml in the list.
|
122
|
+
list[app_xml_idx], list[text_xml_idx] = text_xml, app_xml
|
123
|
+
app_xml_idx, text_xml_idx = text_xml_idx, app_xml_idx
|
124
|
+
end
|
125
|
+
list.delete_at(text_xml_idx) # Delete text_xml from the list.
|
93
126
|
elsif text_xml_idx
|
94
|
-
|
127
|
+
list[text_xml_idx].name = Mime[:xml].to_s
|
95
128
|
end
|
96
129
|
|
97
|
-
# Look for more specific XML-based types and sort them ahead of app/xml
|
130
|
+
# Look for more specific XML-based types and sort them ahead of app/xml.
|
98
131
|
if app_xml_idx
|
132
|
+
app_xml = list[app_xml_idx]
|
99
133
|
idx = app_xml_idx
|
100
134
|
|
101
|
-
while idx < length
|
102
|
-
type =
|
135
|
+
while idx < list.length
|
136
|
+
type = list[idx]
|
103
137
|
break if type.q < app_xml.q
|
104
138
|
|
105
|
-
if type.name.
|
106
|
-
|
107
|
-
|
139
|
+
if type.name.end_with? "+xml"
|
140
|
+
list[app_xml_idx], list[idx] = list[idx], app_xml
|
141
|
+
app_xml_idx = idx
|
108
142
|
end
|
109
143
|
idx += 1
|
110
144
|
end
|
111
145
|
end
|
112
146
|
|
113
|
-
map! { |i| Mime::Type.lookup(i.name) }.uniq!
|
114
|
-
|
147
|
+
list.map! { |i| Mime::Type.lookup(i.name) }.uniq!
|
148
|
+
list
|
115
149
|
end
|
116
150
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
def app_xml_idx
|
123
|
-
@app_xml_idx ||= index(Mime::XML.to_s)
|
124
|
-
end
|
125
|
-
|
126
|
-
def text_xml
|
127
|
-
self[text_xml_idx]
|
128
|
-
end
|
129
|
-
|
130
|
-
def app_xml
|
131
|
-
self[app_xml_idx]
|
132
|
-
end
|
133
|
-
|
134
|
-
def exchange_xml_items
|
135
|
-
self[app_xml_idx], self[text_xml_idx] = text_xml, app_xml
|
136
|
-
@app_xml_idx, @text_xml_idx = text_xml_idx, app_xml_idx
|
137
|
-
end
|
151
|
+
def self.find_item_by_name(array, name)
|
152
|
+
array.index { |item| item.name == name }
|
153
|
+
end
|
138
154
|
end
|
139
155
|
|
140
156
|
class << self
|
141
|
-
TRAILING_STAR_REGEXP =
|
142
|
-
|
157
|
+
TRAILING_STAR_REGEXP = /^(text|application)\/\*/
|
158
|
+
# all media-type parameters need to be before the q-parameter
|
159
|
+
# https://www.rfc-editor.org/rfc/rfc7231#section-5.3.2
|
160
|
+
PARAMETER_SEPARATOR_REGEXP = /;\s*q="?/
|
161
|
+
ACCEPT_HEADER_REGEXP = /[^,\s"](?:[^,"]|"[^"]*")*/
|
143
162
|
|
144
163
|
def register_callback(&block)
|
145
164
|
@register_callbacks << block
|
146
165
|
end
|
147
166
|
|
148
167
|
def lookup(string)
|
168
|
+
return LOOKUP[string] if LOOKUP.key?(string)
|
169
|
+
|
170
|
+
# fallback to the media-type without parameters if it was not found
|
171
|
+
string = string.split(";", 2)[0]&.rstrip
|
149
172
|
LOOKUP[string] || Type.new(string)
|
150
173
|
end
|
151
174
|
|
@@ -153,46 +176,51 @@ module Mime
|
|
153
176
|
EXTENSION_LOOKUP[extension.to_s]
|
154
177
|
end
|
155
178
|
|
156
|
-
# Registers an alias that's not used on
|
157
|
-
# rendering different HTML versions depending on
|
179
|
+
# Registers an alias that's not used on MIME type lookup, but can be referenced
|
180
|
+
# directly. Especially useful for rendering different HTML versions depending on
|
181
|
+
# the user agent, like an iPhone.
|
158
182
|
def register_alias(string, symbol, extension_synonyms = [])
|
159
183
|
register(string, symbol, [], extension_synonyms, true)
|
160
184
|
end
|
161
185
|
|
162
186
|
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
|
163
|
-
|
187
|
+
new_mime = Type.new(string, symbol, mime_type_synonyms)
|
164
188
|
|
165
|
-
new_mime = Mime.const_get(symbol.upcase)
|
166
189
|
SET << new_mime
|
167
190
|
|
168
|
-
([string] + mime_type_synonyms).each { |str| LOOKUP[str] =
|
169
|
-
([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] =
|
191
|
+
([string] + mime_type_synonyms).each { |str| LOOKUP[str] = new_mime } unless skip_lookup
|
192
|
+
([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] = new_mime }
|
170
193
|
|
171
194
|
@register_callbacks.each do |callback|
|
172
195
|
callback.call(new_mime)
|
173
196
|
end
|
197
|
+
new_mime
|
174
198
|
end
|
175
199
|
|
176
200
|
def parse(accept_header)
|
177
|
-
if !accept_header.include?(
|
178
|
-
|
179
|
-
|
201
|
+
if !accept_header.include?(",")
|
202
|
+
if (index = accept_header.index(PARAMETER_SEPARATOR_REGEXP))
|
203
|
+
accept_header = accept_header[0, index].strip
|
204
|
+
end
|
205
|
+
return [] if accept_header.blank?
|
206
|
+
parse_trailing_star(accept_header) || Array(Mime::Type.lookup(accept_header))
|
180
207
|
else
|
181
|
-
list, index =
|
182
|
-
accept_header.
|
208
|
+
list, index = [], 0
|
209
|
+
accept_header.scan(ACCEPT_HEADER_REGEXP).each do |header|
|
183
210
|
params, q = header.split(PARAMETER_SEPARATOR_REGEXP)
|
184
|
-
if params.present?
|
185
|
-
params.strip!
|
186
211
|
|
187
|
-
|
212
|
+
next unless params
|
213
|
+
params.strip!
|
214
|
+
next if params.empty?
|
215
|
+
|
216
|
+
params = parse_trailing_star(params) || [params]
|
188
217
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
end
|
218
|
+
params.each do |m|
|
219
|
+
list << AcceptItem.new(index, m.to_s, q)
|
220
|
+
index += 1
|
193
221
|
end
|
194
222
|
end
|
195
|
-
|
223
|
+
AcceptList.sort! list
|
196
224
|
end
|
197
225
|
end
|
198
226
|
|
@@ -200,34 +228,43 @@ module Mime
|
|
200
228
|
parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
|
201
229
|
end
|
202
230
|
|
203
|
-
# For an input of
|
204
|
-
# Mime
|
231
|
+
# For an input of `'text'`, returns `[Mime[:json], Mime[:xml], Mime[:ics],
|
232
|
+
# Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]]`.
|
205
233
|
#
|
206
|
-
# For an input of
|
207
|
-
# Mime
|
208
|
-
def parse_data_with_trailing_star(
|
209
|
-
Mime::SET.select { |m| m
|
234
|
+
# For an input of `'application'`, returns `[Mime[:html], Mime[:js], Mime[:xml],
|
235
|
+
# Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]]`.
|
236
|
+
def parse_data_with_trailing_star(type)
|
237
|
+
Mime::SET.select { |m| m.match?(type) }
|
210
238
|
end
|
211
239
|
|
212
240
|
# This method is opposite of register method.
|
213
241
|
#
|
214
|
-
#
|
242
|
+
# To unregister a MIME type:
|
215
243
|
#
|
216
|
-
#
|
244
|
+
# Mime::Type.unregister(:mobile)
|
217
245
|
def unregister(symbol)
|
218
|
-
symbol = symbol.
|
219
|
-
mime = Mime
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
EXTENSION_LOOKUP.delete_if { |_,v| v.eql?(mime) }
|
246
|
+
symbol = symbol.downcase
|
247
|
+
if mime = Mime[symbol]
|
248
|
+
SET.delete_if { |v| v.eql?(mime) }
|
249
|
+
LOOKUP.delete_if { |_, v| v.eql?(mime) }
|
250
|
+
EXTENSION_LOOKUP.delete_if { |_, v| v.eql?(mime) }
|
251
|
+
end
|
225
252
|
end
|
226
253
|
end
|
227
254
|
|
228
255
|
attr_reader :hash
|
229
256
|
|
257
|
+
MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
|
258
|
+
MIME_PARAMETER_VALUE = "(?:#{MIME_NAME}|\"[^\"\r\\\\]*\")"
|
259
|
+
MIME_PARAMETER = "\s*;\s*#{MIME_NAME}(?:=#{MIME_PARAMETER_VALUE})?"
|
260
|
+
MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>#{MIME_PARAMETER})*\s*)\z/
|
261
|
+
|
262
|
+
class InvalidMimeType < StandardError; end
|
263
|
+
|
230
264
|
def initialize(string, symbol = nil, synonyms = [])
|
265
|
+
unless MIME_REGEXP.match?(string)
|
266
|
+
raise InvalidMimeType, "#{string.inspect} is not a valid MIME type"
|
267
|
+
end
|
231
268
|
@symbol, @synonyms = symbol, synonyms
|
232
269
|
@string = string
|
233
270
|
@hash = [@string, @synonyms, @symbol].hash
|
@@ -246,7 +283,7 @@ module Mime
|
|
246
283
|
end
|
247
284
|
|
248
285
|
def ref
|
249
|
-
|
286
|
+
symbol || to_s
|
250
287
|
end
|
251
288
|
|
252
289
|
def ===(list)
|
@@ -258,7 +295,7 @@ module Mime
|
|
258
295
|
end
|
259
296
|
|
260
297
|
def ==(mime_type)
|
261
|
-
return false
|
298
|
+
return false unless mime_type
|
262
299
|
(@synonyms + [ self ]).any? do |synonym|
|
263
300
|
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
|
264
301
|
end
|
@@ -272,40 +309,59 @@ module Mime
|
|
272
309
|
end
|
273
310
|
|
274
311
|
def =~(mime_type)
|
275
|
-
return false
|
312
|
+
return false unless mime_type
|
276
313
|
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
|
277
|
-
|
278
|
-
|
279
|
-
|
314
|
+
@synonyms.any? { |synonym| synonym.to_s =~ regexp } || @string =~ regexp
|
315
|
+
end
|
316
|
+
|
317
|
+
def match?(mime_type)
|
318
|
+
return false unless mime_type
|
319
|
+
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
|
320
|
+
@synonyms.any? { |synonym| synonym.to_s.match?(regexp) } || @string.match?(regexp)
|
280
321
|
end
|
281
322
|
|
282
323
|
def html?
|
283
|
-
|
324
|
+
(symbol == :html) || @string.include?("html")
|
284
325
|
end
|
285
326
|
|
327
|
+
def all?; false; end
|
286
328
|
|
287
329
|
protected
|
288
|
-
|
289
|
-
attr_reader :string, :synonyms
|
330
|
+
attr_reader :string, :synonyms
|
290
331
|
|
291
332
|
private
|
333
|
+
def to_ary; end
|
334
|
+
def to_a; end
|
292
335
|
|
293
|
-
|
294
|
-
|
336
|
+
def method_missing(method, ...)
|
337
|
+
if method.end_with?("?")
|
338
|
+
method[0..-2].downcase.to_sym == to_sym
|
339
|
+
else
|
340
|
+
super
|
341
|
+
end
|
342
|
+
end
|
295
343
|
|
296
|
-
|
297
|
-
|
298
|
-
method[0..-2].downcase.to_sym == to_sym
|
299
|
-
else
|
300
|
-
super
|
344
|
+
def respond_to_missing?(method, include_private = false)
|
345
|
+
method.end_with?("?") || super
|
301
346
|
end
|
302
|
-
|
347
|
+
end
|
303
348
|
|
304
|
-
|
305
|
-
|
349
|
+
class AllType < Type
|
350
|
+
include Singleton
|
351
|
+
|
352
|
+
def initialize
|
353
|
+
super "*/*", nil
|
306
354
|
end
|
355
|
+
|
356
|
+
def all?; true; end
|
357
|
+
def html?; true; end
|
307
358
|
end
|
308
359
|
|
360
|
+
# ALL isn't a real MIME type, so we don't register it for lookup with the other
|
361
|
+
# concrete types. It's a wildcard match that we use for `respond_to` negotiation
|
362
|
+
# internals.
|
363
|
+
ALL = AllType.instance
|
364
|
+
|
309
365
|
class NullType
|
310
366
|
include Singleton
|
311
367
|
|
@@ -313,17 +369,21 @@ module Mime
|
|
313
369
|
true
|
314
370
|
end
|
315
371
|
|
316
|
-
def
|
317
|
-
|
318
|
-
def respond_to_missing?(method, include_private = false)
|
319
|
-
method.to_s.ends_with? '?'
|
372
|
+
def to_s
|
373
|
+
""
|
320
374
|
end
|
321
375
|
|
376
|
+
def ref; end
|
377
|
+
|
322
378
|
private
|
323
|
-
|
324
|
-
|
325
|
-
|
379
|
+
def respond_to_missing?(method, _)
|
380
|
+
method.end_with?("?")
|
381
|
+
end
|
382
|
+
|
383
|
+
def method_missing(method, ...)
|
384
|
+
false if method.end_with?("?")
|
385
|
+
end
|
326
386
|
end
|
327
387
|
end
|
328
388
|
|
329
|
-
require
|
389
|
+
require "action_dispatch/http/mime_types"
|
@@ -1,5 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Build list of Mime types for HTTP responses
|
2
|
-
#
|
4
|
+
# https://www.iana.org/assignments/media-types/
|
5
|
+
|
6
|
+
# :markup: markdown
|
3
7
|
|
4
8
|
Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
|
5
9
|
Mime::Type.register "text/plain", :text, [], %w(txt)
|
@@ -8,29 +12,43 @@ Mime::Type.register "text/css", :css
|
|
8
12
|
Mime::Type.register "text/calendar", :ics
|
9
13
|
Mime::Type.register "text/csv", :csv
|
10
14
|
Mime::Type.register "text/vcard", :vcf
|
15
|
+
Mime::Type.register "text/vtt", :vtt, %w(vtt)
|
11
16
|
|
12
17
|
Mime::Type.register "image/png", :png, [], %w(png)
|
13
18
|
Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe pjpeg)
|
14
19
|
Mime::Type.register "image/gif", :gif, [], %w(gif)
|
15
20
|
Mime::Type.register "image/bmp", :bmp, [], %w(bmp)
|
16
21
|
Mime::Type.register "image/tiff", :tiff, [], %w(tif tiff)
|
22
|
+
Mime::Type.register "image/svg+xml", :svg
|
23
|
+
Mime::Type.register "image/webp", :webp, [], %w(webp)
|
17
24
|
|
18
25
|
Mime::Type.register "video/mpeg", :mpeg, [], %w(mpg mpeg mpe)
|
19
26
|
|
27
|
+
Mime::Type.register "audio/mpeg", :mp3, [], %w(mp1 mp2 mp3)
|
28
|
+
Mime::Type.register "audio/ogg", :ogg, [], %w(oga ogg spx opus)
|
29
|
+
Mime::Type.register "audio/aac", :m4a, %w( audio/mp4 ), %w(m4a mpg4 aac)
|
30
|
+
|
31
|
+
Mime::Type.register "video/webm", :webm, [], %w(webm)
|
32
|
+
Mime::Type.register "video/mp4", :mp4, [], %w(mp4 m4v)
|
33
|
+
|
34
|
+
Mime::Type.register "font/otf", :otf, [], %w(otf)
|
35
|
+
Mime::Type.register "font/ttf", :ttf, [], %w(ttf)
|
36
|
+
Mime::Type.register "font/woff", :woff, [], %w(woff)
|
37
|
+
Mime::Type.register "font/woff2", :woff2, [], %w(woff2)
|
38
|
+
|
20
39
|
Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml )
|
21
40
|
Mime::Type.register "application/rss+xml", :rss
|
22
41
|
Mime::Type.register "application/atom+xml", :atom
|
23
|
-
Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml )
|
42
|
+
Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml ), %w(yml yaml)
|
24
43
|
|
25
44
|
Mime::Type.register "multipart/form-data", :multipart_form
|
26
45
|
Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
|
27
46
|
|
28
|
-
#
|
47
|
+
# https://www.ietf.org/rfc/rfc4627.txt
|
29
48
|
# http://www.json.org/JSONRequest.html
|
30
|
-
|
49
|
+
# https://www.ietf.org/rfc/rfc7807.txt
|
50
|
+
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest application/problem+json )
|
31
51
|
|
32
52
|
Mime::Type.register "application/pdf", :pdf, [], %w(pdf)
|
33
53
|
Mime::Type.register "application/zip", :zip, [], %w(zip)
|
34
|
-
|
35
|
-
# Create Mime::ALL but do not add it to the SET.
|
36
|
-
Mime::ALL = Mime::Type.new("*/*", :all, [])
|
54
|
+
Mime::Type.register "application/gzip", :gzip, %w(application/x-gzip), %w(gz)
|