actionpack 4.2.11.3 → 5.0.7.2
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 +4 -4
- data/CHANGELOG.md +890 -384
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/abstract_controller/base.rb +28 -38
- data/lib/{action_controller → abstract_controller}/caching/fragments.rb +51 -11
- data/lib/abstract_controller/caching.rb +62 -0
- data/lib/abstract_controller/callbacks.rb +54 -19
- data/lib/abstract_controller/collector.rb +4 -9
- data/lib/abstract_controller/error.rb +4 -0
- data/lib/abstract_controller/helpers.rb +4 -3
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
- data/lib/abstract_controller/rendering.rb +28 -18
- data/lib/abstract_controller/translation.rb +8 -7
- data/lib/abstract_controller.rb +6 -2
- data/lib/action_controller/api/api_rendering.rb +14 -0
- data/lib/action_controller/api.rb +147 -0
- data/lib/action_controller/base.rb +14 -11
- data/lib/action_controller/caching.rb +13 -58
- data/lib/action_controller/form_builder.rb +48 -0
- data/lib/action_controller/log_subscriber.rb +3 -10
- data/lib/action_controller/metal/basic_implicit_render.rb +11 -0
- data/lib/action_controller/metal/conditional_get.rb +106 -34
- data/lib/action_controller/metal/cookies.rb +1 -3
- data/lib/action_controller/metal/data_streaming.rb +14 -34
- data/lib/action_controller/metal/etag_with_template_digest.rb +8 -2
- data/lib/action_controller/metal/exceptions.rb +11 -6
- data/lib/action_controller/metal/force_ssl.rb +11 -11
- data/lib/action_controller/metal/head.rb +14 -8
- data/lib/action_controller/metal/helpers.rb +15 -6
- data/lib/action_controller/metal/http_authentication.rb +44 -35
- data/lib/action_controller/metal/implicit_render.rb +61 -6
- data/lib/action_controller/metal/instrumentation.rb +5 -5
- data/lib/action_controller/metal/live.rb +71 -88
- data/lib/action_controller/metal/mime_responds.rb +27 -42
- data/lib/action_controller/metal/params_wrapper.rb +9 -9
- data/lib/action_controller/metal/redirecting.rb +32 -9
- data/lib/action_controller/metal/renderers.rb +83 -40
- data/lib/action_controller/metal/rendering.rb +38 -6
- data/lib/action_controller/metal/request_forgery_protection.rb +126 -48
- data/lib/action_controller/metal/rescue.rb +3 -12
- data/lib/action_controller/metal/streaming.rb +4 -4
- data/lib/action_controller/metal/strong_parameters.rb +527 -134
- data/lib/action_controller/metal/testing.rb +1 -12
- data/lib/action_controller/metal/url_for.rb +12 -5
- data/lib/action_controller/metal.rb +88 -63
- data/lib/action_controller/railtie.rb +11 -7
- data/lib/action_controller/renderer.rb +113 -0
- data/lib/action_controller/template_assertions.rb +9 -0
- data/lib/action_controller/test_case.rb +311 -374
- data/lib/action_controller.rb +12 -9
- data/lib/action_dispatch/http/cache.rb +73 -34
- data/lib/action_dispatch/http/filter_parameters.rb +16 -12
- data/lib/action_dispatch/http/filter_redirect.rb +7 -8
- data/lib/action_dispatch/http/headers.rb +45 -14
- data/lib/action_dispatch/http/mime_negotiation.rb +42 -23
- data/lib/action_dispatch/http/mime_type.rb +126 -90
- data/lib/action_dispatch/http/mime_types.rb +3 -4
- data/lib/action_dispatch/http/parameter_filter.rb +19 -9
- data/lib/action_dispatch/http/parameters.rb +70 -40
- data/lib/action_dispatch/http/request.rb +144 -89
- data/lib/action_dispatch/http/response.rb +215 -102
- data/lib/action_dispatch/http/upload.rb +6 -2
- data/lib/action_dispatch/http/url.rb +117 -8
- data/lib/action_dispatch/journey/formatter.rb +47 -30
- data/lib/action_dispatch/journey/gtg/transition_table.rb +1 -1
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -2
- data/lib/action_dispatch/journey/nfa/transition_table.rb +1 -46
- data/lib/action_dispatch/journey/nodes/node.rb +14 -4
- data/lib/action_dispatch/journey/parser.rb +2 -0
- data/lib/action_dispatch/journey/parser_extras.rb +8 -2
- data/lib/action_dispatch/journey/path/pattern.rb +38 -42
- data/lib/action_dispatch/journey/route.rb +88 -26
- data/lib/action_dispatch/journey/router/utils.rb +5 -5
- data/lib/action_dispatch/journey/router.rb +8 -10
- data/lib/action_dispatch/journey/routes.rb +14 -15
- data/lib/action_dispatch/journey/visitors.rb +89 -44
- data/lib/action_dispatch/middleware/callbacks.rb +10 -1
- data/lib/action_dispatch/middleware/cookies.rb +188 -134
- data/lib/action_dispatch/middleware/debug_exceptions.rb +128 -49
- data/lib/action_dispatch/middleware/debug_locks.rb +122 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +21 -21
- data/lib/action_dispatch/middleware/executor.rb +19 -0
- data/lib/action_dispatch/middleware/flash.rb +66 -45
- data/lib/action_dispatch/middleware/params_parser.rb +32 -46
- data/lib/action_dispatch/middleware/public_exceptions.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +14 -58
- data/lib/action_dispatch/middleware/remote_ip.rb +29 -19
- data/lib/action_dispatch/middleware/request_id.rb +11 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +23 -11
- data/lib/action_dispatch/middleware/session/cache_store.rb +9 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +30 -24
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +4 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +11 -9
- data/lib/action_dispatch/middleware/ssl.rb +124 -36
- data/lib/action_dispatch/middleware/stack.rb +44 -40
- data/lib/action_dispatch/middleware/static.rb +51 -35
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +59 -63
- data/lib/action_dispatch/railtie.rb +2 -2
- data/lib/action_dispatch/request/session.rb +69 -33
- data/lib/action_dispatch/request/utils.rb +51 -19
- data/lib/action_dispatch/routing/inspector.rb +32 -43
- data/lib/action_dispatch/routing/mapper.rb +515 -348
- data/lib/action_dispatch/routing/polymorphic_routes.rb +8 -14
- data/lib/action_dispatch/routing/redirection.rb +5 -4
- data/lib/action_dispatch/routing/route_set.rb +148 -240
- data/lib/action_dispatch/routing/url_for.rb +27 -10
- data/lib/action_dispatch/routing.rb +17 -13
- data/lib/action_dispatch/testing/assertion_response.rb +45 -0
- data/lib/action_dispatch/testing/assertions/response.rb +38 -20
- data/lib/action_dispatch/testing/assertions/routing.rb +16 -12
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/integration.rb +377 -149
- data/lib/action_dispatch/testing/request_encoder.rb +53 -0
- data/lib/action_dispatch/testing/test_process.rb +24 -20
- data/lib/action_dispatch/testing/test_request.rb +22 -31
- data/lib/action_dispatch/testing/test_response.rb +12 -4
- data/lib/action_dispatch.rb +4 -1
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack.rb +1 -1
- metadata +32 -34
- 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/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/router/strexp.rb +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
- /data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
-
require 'active_support/core_ext/string/filters'
|
3
|
-
require 'active_support/deprecation'
|
4
2
|
require 'action_dispatch/http/filter_redirect'
|
3
|
+
require 'action_dispatch/http/cache'
|
5
4
|
require 'monitor'
|
6
5
|
|
7
6
|
module ActionDispatch # :nodoc:
|
@@ -34,46 +33,62 @@ module ActionDispatch # :nodoc:
|
|
34
33
|
# end
|
35
34
|
# end
|
36
35
|
class Response
|
36
|
+
class Header < DelegateClass(Hash) # :nodoc:
|
37
|
+
def initialize(response, header)
|
38
|
+
@response = response
|
39
|
+
super(header)
|
40
|
+
end
|
41
|
+
|
42
|
+
def []=(k,v)
|
43
|
+
if @response.sending? || @response.sent?
|
44
|
+
raise ActionDispatch::IllegalStateError, 'header already sent'
|
45
|
+
end
|
46
|
+
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
def merge(other)
|
51
|
+
self.class.new @response, __getobj__.merge(other)
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_hash
|
55
|
+
__getobj__.dup
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
37
59
|
# The request that the response is responding to.
|
38
60
|
attr_accessor :request
|
39
61
|
|
40
62
|
# The HTTP status code.
|
41
63
|
attr_reader :status
|
42
64
|
|
43
|
-
|
65
|
+
# Get headers for this response.
|
66
|
+
attr_reader :header
|
44
67
|
|
45
|
-
# Get and set headers for this response.
|
46
|
-
attr_accessor :header
|
47
|
-
|
48
|
-
alias_method :headers=, :header=
|
49
68
|
alias_method :headers, :header
|
50
69
|
|
51
70
|
delegate :[], :[]=, :to => :@header
|
52
|
-
delegate :each, :to => :@stream
|
53
71
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# the character set information will also be included in the content type
|
61
|
-
# information.
|
62
|
-
attr_reader :content_type
|
63
|
-
|
64
|
-
# The charset of the response. HTML wants to know the encoding of the
|
65
|
-
# content you're giving them, so we need to send that along.
|
66
|
-
attr_accessor :charset
|
72
|
+
def each(&block)
|
73
|
+
sending!
|
74
|
+
x = @stream.each(&block)
|
75
|
+
sent!
|
76
|
+
x
|
77
|
+
end
|
67
78
|
|
68
79
|
CONTENT_TYPE = "Content-Type".freeze
|
69
80
|
SET_COOKIE = "Set-Cookie".freeze
|
70
81
|
LOCATION = "Location".freeze
|
71
|
-
NO_CONTENT_CODES = [204, 304]
|
82
|
+
NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304]
|
72
83
|
|
73
84
|
cattr_accessor(:default_charset) { "utf-8" }
|
74
85
|
cattr_accessor(:default_headers)
|
75
86
|
|
76
87
|
include Rack::Response::Helpers
|
88
|
+
# Aliasing these off because AD::Http::Cache::Response defines them
|
89
|
+
alias :_cache_control :cache_control
|
90
|
+
alias :_cache_control= :cache_control=
|
91
|
+
|
77
92
|
include ActionDispatch::Http::FilterRedirect
|
78
93
|
include ActionDispatch::Http::Cache::Response
|
79
94
|
include MonitorMixin
|
@@ -83,20 +98,33 @@ module ActionDispatch # :nodoc:
|
|
83
98
|
@response = response
|
84
99
|
@buf = buf
|
85
100
|
@closed = false
|
101
|
+
@str_body = nil
|
102
|
+
end
|
103
|
+
|
104
|
+
def body
|
105
|
+
@str_body ||= begin
|
106
|
+
buf = ''
|
107
|
+
each { |chunk| buf << chunk }
|
108
|
+
buf
|
109
|
+
end
|
86
110
|
end
|
87
111
|
|
88
112
|
def write(string)
|
89
113
|
raise IOError, "closed stream" if closed?
|
90
114
|
|
115
|
+
@str_body = nil
|
91
116
|
@response.commit!
|
92
117
|
@buf.push string
|
93
118
|
end
|
94
119
|
|
95
120
|
def each(&block)
|
96
|
-
@
|
97
|
-
|
98
|
-
|
99
|
-
|
121
|
+
if @str_body
|
122
|
+
return enum_for(:each) unless block_given?
|
123
|
+
|
124
|
+
yield @str_body
|
125
|
+
else
|
126
|
+
each_chunk(&block)
|
127
|
+
end
|
100
128
|
end
|
101
129
|
|
102
130
|
def abort
|
@@ -110,39 +138,48 @@ module ActionDispatch # :nodoc:
|
|
110
138
|
def closed?
|
111
139
|
@closed
|
112
140
|
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def each_chunk(&block)
|
145
|
+
@buf.each(&block) # extract into own method
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.create(status = 200, header = {}, body = [], default_headers: self.default_headers)
|
150
|
+
header = merge_default_headers(header, default_headers)
|
151
|
+
new status, header, body
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.merge_default_headers(original, default)
|
155
|
+
default.respond_to?(:merge) ? default.merge(original) : original
|
113
156
|
end
|
114
157
|
|
115
158
|
# The underlying body, as a streamable object.
|
116
159
|
attr_reader :stream
|
117
160
|
|
118
|
-
def initialize(status = 200, header = {}, body = []
|
161
|
+
def initialize(status = 200, header = {}, body = [])
|
119
162
|
super()
|
120
163
|
|
121
|
-
|
122
|
-
header = merge_default_headers(header, default_headers)
|
164
|
+
@header = Header.new(self, header)
|
123
165
|
|
124
|
-
self.body, self.
|
166
|
+
self.body, self.status = body, status
|
125
167
|
|
126
|
-
@sending_file = false
|
127
|
-
@blank = false
|
128
168
|
@cv = new_cond
|
129
169
|
@committed = false
|
130
170
|
@sending = false
|
131
171
|
@sent = false
|
132
|
-
@content_type = nil
|
133
|
-
@charset = nil
|
134
|
-
|
135
|
-
if content_type = self[CONTENT_TYPE]
|
136
|
-
type, charset = content_type.split(/;\s*charset=/)
|
137
|
-
@content_type = Mime::Type.lookup(type)
|
138
|
-
@charset = charset || self.class.default_charset
|
139
|
-
end
|
140
172
|
|
141
173
|
prepare_cache_control!
|
142
174
|
|
143
175
|
yield self if block_given?
|
144
176
|
end
|
145
177
|
|
178
|
+
def has_header?(key); headers.key? key; end
|
179
|
+
def get_header(key); headers[key]; end
|
180
|
+
def set_header(key, v); headers[key] = v; end
|
181
|
+
def delete_header(key); headers.delete key; end
|
182
|
+
|
146
183
|
def await_commit
|
147
184
|
synchronize do
|
148
185
|
@cv.wait_until { @committed }
|
@@ -187,7 +224,53 @@ module ActionDispatch # :nodoc:
|
|
187
224
|
|
188
225
|
# Sets the HTTP content type.
|
189
226
|
def content_type=(content_type)
|
190
|
-
|
227
|
+
return unless content_type
|
228
|
+
new_header_info = parse_content_type(content_type.to_s)
|
229
|
+
prev_header_info = parsed_content_type_header
|
230
|
+
charset = new_header_info.charset || prev_header_info.charset
|
231
|
+
charset ||= self.class.default_charset unless prev_header_info.mime_type
|
232
|
+
set_content_type new_header_info.mime_type, charset
|
233
|
+
end
|
234
|
+
|
235
|
+
# Sets the HTTP response's content MIME type. For example, in the controller
|
236
|
+
# you could write this:
|
237
|
+
#
|
238
|
+
# response.content_type = "text/plain"
|
239
|
+
#
|
240
|
+
# If a character set has been defined for this response (see charset=) then
|
241
|
+
# the character set information will also be included in the content type
|
242
|
+
# information.
|
243
|
+
|
244
|
+
def content_type
|
245
|
+
parsed_content_type_header.mime_type
|
246
|
+
end
|
247
|
+
|
248
|
+
def sending_file=(v)
|
249
|
+
if true == v
|
250
|
+
self.charset = false
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
# Sets the HTTP character set. In case of nil parameter
|
255
|
+
# it sets the charset to utf-8.
|
256
|
+
#
|
257
|
+
# response.charset = 'utf-16' # => 'utf-16'
|
258
|
+
# response.charset = nil # => 'utf-8'
|
259
|
+
def charset=(charset)
|
260
|
+
header_info = parsed_content_type_header
|
261
|
+
if false == charset
|
262
|
+
set_header CONTENT_TYPE, header_info.mime_type
|
263
|
+
else
|
264
|
+
content_type = header_info.mime_type
|
265
|
+
set_content_type content_type, charset || self.class.default_charset
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# The charset of the response. HTML wants to know the encoding of the
|
270
|
+
# content you're giving them, so we need to send that along.
|
271
|
+
def charset
|
272
|
+
header_info = parsed_content_type_header
|
273
|
+
header_info.charset || self.class.default_charset
|
191
274
|
end
|
192
275
|
|
193
276
|
# The response code of the request.
|
@@ -216,17 +299,15 @@ module ActionDispatch # :nodoc:
|
|
216
299
|
# Returns the content of the response as a string. This contains the contents
|
217
300
|
# of any calls to <tt>render</tt>.
|
218
301
|
def body
|
219
|
-
|
220
|
-
each { |part| strings << part.to_s }
|
221
|
-
strings.join
|
302
|
+
@stream.body
|
222
303
|
end
|
223
304
|
|
224
|
-
|
305
|
+
def write(string)
|
306
|
+
@stream.write string
|
307
|
+
end
|
225
308
|
|
226
309
|
# Allows you to manually set or override the response body.
|
227
310
|
def body=(body)
|
228
|
-
@blank = true if body == EMPTY
|
229
|
-
|
230
311
|
if body.respond_to?(:to_path)
|
231
312
|
@stream = body
|
232
313
|
else
|
@@ -236,31 +317,49 @@ module ActionDispatch # :nodoc:
|
|
236
317
|
end
|
237
318
|
end
|
238
319
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
320
|
+
# Avoid having to pass an open file handle as the response body.
|
321
|
+
# Rack::Sendfile will usually intercept the response and uses
|
322
|
+
# the path directly, so there is no reason to open the file.
|
323
|
+
class FileBody #:nodoc:
|
324
|
+
attr_reader :to_path
|
244
325
|
|
245
|
-
|
246
|
-
|
326
|
+
def initialize(path)
|
327
|
+
@to_path = path
|
328
|
+
end
|
329
|
+
|
330
|
+
def body
|
331
|
+
File.binread(to_path)
|
332
|
+
end
|
333
|
+
|
334
|
+
# Stream the file's contents if Rack::Sendfile isn't present.
|
335
|
+
def each
|
336
|
+
File.open(to_path, 'rb') do |file|
|
337
|
+
while chunk = file.read(16384)
|
338
|
+
yield chunk
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
247
342
|
end
|
248
343
|
|
249
|
-
|
250
|
-
|
344
|
+
# Send the file stored at +path+ as the response body.
|
345
|
+
def send_file(path)
|
346
|
+
commit!
|
347
|
+
@stream = FileBody.new(path)
|
251
348
|
end
|
252
349
|
|
253
|
-
|
254
|
-
|
255
|
-
headers[LOCATION]
|
350
|
+
def reset_body!
|
351
|
+
@stream = build_buffer(self, [])
|
256
352
|
end
|
257
|
-
alias_method :redirect_url, :location
|
258
353
|
|
259
|
-
|
260
|
-
|
261
|
-
|
354
|
+
def body_parts
|
355
|
+
parts = []
|
356
|
+
@stream.each { |x| parts << x }
|
357
|
+
parts
|
262
358
|
end
|
263
359
|
|
360
|
+
# The location header we'll be responding with.
|
361
|
+
alias_method :redirect_url, :location
|
362
|
+
|
264
363
|
def close
|
265
364
|
stream.close if stream.respond_to?(:close)
|
266
365
|
end
|
@@ -277,34 +376,21 @@ module ActionDispatch # :nodoc:
|
|
277
376
|
end
|
278
377
|
|
279
378
|
# Turns the Response into a Rack-compatible array of the status, headers,
|
280
|
-
# and body. Allows
|
379
|
+
# and body. Allows explicit splatting:
|
281
380
|
#
|
282
381
|
# status, headers, body = *response
|
283
382
|
def to_a
|
383
|
+
commit!
|
284
384
|
rack_response @status, @header.to_hash
|
285
385
|
end
|
286
386
|
alias prepare! to_a
|
287
387
|
|
288
|
-
# Be super clear that a response object is not an Array. Defining this
|
289
|
-
# would make implicit splatting work, but it also makes adding responses
|
290
|
-
# as arrays work, and "flattening" responses, cascading to the rack body!
|
291
|
-
# Not sensible behavior.
|
292
|
-
def to_ary
|
293
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
294
|
-
`ActionDispatch::Response#to_ary` no longer performs implicit conversion
|
295
|
-
to an array. Please use `response.to_a` instead, or a splat like `status,
|
296
|
-
headers, body = *response`.
|
297
|
-
MSG
|
298
|
-
|
299
|
-
to_a
|
300
|
-
end
|
301
|
-
|
302
388
|
# Returns the response cookies, converted to a Hash of (name => value) pairs
|
303
389
|
#
|
304
390
|
# assert_equal 'AuthorOfNewPage', r.cookies['author']
|
305
391
|
def cookies
|
306
392
|
cookies = {}
|
307
|
-
if header =
|
393
|
+
if header = get_header(SET_COOKIE)
|
308
394
|
header = header.split("\n") if header.respond_to?(:to_str)
|
309
395
|
header.each do |cookie|
|
310
396
|
if pair = cookie.split(';').first
|
@@ -318,14 +404,48 @@ module ActionDispatch # :nodoc:
|
|
318
404
|
|
319
405
|
private
|
320
406
|
|
407
|
+
ContentTypeHeader = Struct.new :mime_type, :charset
|
408
|
+
NullContentTypeHeader = ContentTypeHeader.new nil, nil
|
409
|
+
|
410
|
+
def parse_content_type(content_type)
|
411
|
+
if content_type
|
412
|
+
type, charset = content_type.split(/;\s*charset=/)
|
413
|
+
type = nil if type && type.empty?
|
414
|
+
ContentTypeHeader.new(type, charset)
|
415
|
+
else
|
416
|
+
NullContentTypeHeader
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
# Small internal convenience method to get the parsed version of the current
|
421
|
+
# content type header.
|
422
|
+
def parsed_content_type_header
|
423
|
+
parse_content_type(get_header(CONTENT_TYPE))
|
424
|
+
end
|
425
|
+
|
426
|
+
def set_content_type(content_type, charset)
|
427
|
+
type = (content_type || '').dup
|
428
|
+
type << "; charset=#{charset}" if charset
|
429
|
+
set_header CONTENT_TYPE, type
|
430
|
+
end
|
431
|
+
|
321
432
|
def before_committed
|
433
|
+
return if committed?
|
434
|
+
assign_default_content_type_and_charset!
|
435
|
+
handle_conditional_get!
|
436
|
+
handle_no_content!
|
322
437
|
end
|
323
438
|
|
324
439
|
def before_sending
|
325
|
-
|
440
|
+
# Normally we've already committed by now, but it's possible
|
441
|
+
# (e.g., if the controller action tries to read back its own
|
442
|
+
# response) to get here before that. In that case, we must force
|
443
|
+
# an "early" commit: we're about to freeze the headers, so this is
|
444
|
+
# our last chance.
|
445
|
+
commit! unless committed?
|
326
446
|
|
327
|
-
|
328
|
-
|
447
|
+
headers.freeze
|
448
|
+
request.commit_cookie_jar! unless committed?
|
329
449
|
end
|
330
450
|
|
331
451
|
def build_buffer(response, body)
|
@@ -336,20 +456,12 @@ module ActionDispatch # :nodoc:
|
|
336
456
|
body.respond_to?(:each) ? body : [body]
|
337
457
|
end
|
338
458
|
|
339
|
-
def assign_default_content_type_and_charset!
|
340
|
-
return if
|
341
|
-
|
342
|
-
@content_type ||= Mime::HTML
|
343
|
-
@charset ||= self.class.default_charset unless @charset == false
|
459
|
+
def assign_default_content_type_and_charset!
|
460
|
+
return if content_type
|
344
461
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
headers[CONTENT_TYPE] = type
|
349
|
-
end
|
350
|
-
|
351
|
-
def append_charset?
|
352
|
-
!@sending_file && @charset != false
|
462
|
+
ct = parsed_content_type_header
|
463
|
+
set_content_type(ct.mime_type || Mime[:html].to_s,
|
464
|
+
ct.charset || self.class.default_charset)
|
353
465
|
end
|
354
466
|
|
355
467
|
class RackBody
|
@@ -388,14 +500,15 @@ module ActionDispatch # :nodoc:
|
|
388
500
|
end
|
389
501
|
end
|
390
502
|
|
391
|
-
def
|
392
|
-
assign_default_content_type_and_charset!(header)
|
393
|
-
handle_conditional_get!
|
394
|
-
|
395
|
-
header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join)
|
396
|
-
|
503
|
+
def handle_no_content!
|
397
504
|
if NO_CONTENT_CODES.include?(@status)
|
398
|
-
header.delete CONTENT_TYPE
|
505
|
+
@header.delete CONTENT_TYPE
|
506
|
+
@header.delete 'Content-Length'
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
def rack_response(status, header)
|
511
|
+
if NO_CONTENT_CODES.include?(status)
|
399
512
|
[status, header, []]
|
400
513
|
else
|
401
514
|
[status, header, RackBody.new(self)]
|
@@ -27,14 +27,18 @@ module ActionDispatch
|
|
27
27
|
@tempfile = hash[:tempfile]
|
28
28
|
raise(ArgumentError, ':tempfile is required') unless @tempfile
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
if hash[:filename]
|
31
|
+
@original_filename = hash[:filename].dup
|
32
|
+
|
32
33
|
begin
|
33
34
|
@original_filename.encode!(Encoding::UTF_8)
|
34
35
|
rescue EncodingError
|
35
36
|
@original_filename.force_encoding(Encoding::UTF_8)
|
36
37
|
end
|
38
|
+
else
|
39
|
+
@original_filename = nil
|
37
40
|
end
|
41
|
+
|
38
42
|
@content_type = hash[:type]
|
39
43
|
@headers = hash[:head]
|
40
44
|
end
|