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.

Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +890 -384
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/base.rb +28 -38
  6. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +51 -11
  7. data/lib/abstract_controller/caching.rb +62 -0
  8. data/lib/abstract_controller/callbacks.rb +54 -19
  9. data/lib/abstract_controller/collector.rb +4 -9
  10. data/lib/abstract_controller/error.rb +4 -0
  11. data/lib/abstract_controller/helpers.rb +4 -3
  12. data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
  13. data/lib/abstract_controller/rendering.rb +28 -18
  14. data/lib/abstract_controller/translation.rb +8 -7
  15. data/lib/abstract_controller.rb +6 -2
  16. data/lib/action_controller/api/api_rendering.rb +14 -0
  17. data/lib/action_controller/api.rb +147 -0
  18. data/lib/action_controller/base.rb +14 -11
  19. data/lib/action_controller/caching.rb +13 -58
  20. data/lib/action_controller/form_builder.rb +48 -0
  21. data/lib/action_controller/log_subscriber.rb +3 -10
  22. data/lib/action_controller/metal/basic_implicit_render.rb +11 -0
  23. data/lib/action_controller/metal/conditional_get.rb +106 -34
  24. data/lib/action_controller/metal/cookies.rb +1 -3
  25. data/lib/action_controller/metal/data_streaming.rb +14 -34
  26. data/lib/action_controller/metal/etag_with_template_digest.rb +8 -2
  27. data/lib/action_controller/metal/exceptions.rb +11 -6
  28. data/lib/action_controller/metal/force_ssl.rb +11 -11
  29. data/lib/action_controller/metal/head.rb +14 -8
  30. data/lib/action_controller/metal/helpers.rb +15 -6
  31. data/lib/action_controller/metal/http_authentication.rb +44 -35
  32. data/lib/action_controller/metal/implicit_render.rb +61 -6
  33. data/lib/action_controller/metal/instrumentation.rb +5 -5
  34. data/lib/action_controller/metal/live.rb +71 -88
  35. data/lib/action_controller/metal/mime_responds.rb +27 -42
  36. data/lib/action_controller/metal/params_wrapper.rb +9 -9
  37. data/lib/action_controller/metal/redirecting.rb +32 -9
  38. data/lib/action_controller/metal/renderers.rb +83 -40
  39. data/lib/action_controller/metal/rendering.rb +38 -6
  40. data/lib/action_controller/metal/request_forgery_protection.rb +126 -48
  41. data/lib/action_controller/metal/rescue.rb +3 -12
  42. data/lib/action_controller/metal/streaming.rb +4 -4
  43. data/lib/action_controller/metal/strong_parameters.rb +527 -134
  44. data/lib/action_controller/metal/testing.rb +1 -12
  45. data/lib/action_controller/metal/url_for.rb +12 -5
  46. data/lib/action_controller/metal.rb +88 -63
  47. data/lib/action_controller/railtie.rb +11 -7
  48. data/lib/action_controller/renderer.rb +113 -0
  49. data/lib/action_controller/template_assertions.rb +9 -0
  50. data/lib/action_controller/test_case.rb +311 -374
  51. data/lib/action_controller.rb +12 -9
  52. data/lib/action_dispatch/http/cache.rb +73 -34
  53. data/lib/action_dispatch/http/filter_parameters.rb +16 -12
  54. data/lib/action_dispatch/http/filter_redirect.rb +7 -8
  55. data/lib/action_dispatch/http/headers.rb +45 -14
  56. data/lib/action_dispatch/http/mime_negotiation.rb +42 -23
  57. data/lib/action_dispatch/http/mime_type.rb +126 -90
  58. data/lib/action_dispatch/http/mime_types.rb +3 -4
  59. data/lib/action_dispatch/http/parameter_filter.rb +19 -9
  60. data/lib/action_dispatch/http/parameters.rb +70 -40
  61. data/lib/action_dispatch/http/request.rb +144 -89
  62. data/lib/action_dispatch/http/response.rb +215 -102
  63. data/lib/action_dispatch/http/upload.rb +6 -2
  64. data/lib/action_dispatch/http/url.rb +117 -8
  65. data/lib/action_dispatch/journey/formatter.rb +47 -30
  66. data/lib/action_dispatch/journey/gtg/transition_table.rb +1 -1
  67. data/lib/action_dispatch/journey/nfa/dot.rb +0 -2
  68. data/lib/action_dispatch/journey/nfa/transition_table.rb +1 -46
  69. data/lib/action_dispatch/journey/nodes/node.rb +14 -4
  70. data/lib/action_dispatch/journey/parser.rb +2 -0
  71. data/lib/action_dispatch/journey/parser_extras.rb +8 -2
  72. data/lib/action_dispatch/journey/path/pattern.rb +38 -42
  73. data/lib/action_dispatch/journey/route.rb +88 -26
  74. data/lib/action_dispatch/journey/router/utils.rb +5 -5
  75. data/lib/action_dispatch/journey/router.rb +8 -10
  76. data/lib/action_dispatch/journey/routes.rb +14 -15
  77. data/lib/action_dispatch/journey/visitors.rb +89 -44
  78. data/lib/action_dispatch/middleware/callbacks.rb +10 -1
  79. data/lib/action_dispatch/middleware/cookies.rb +188 -134
  80. data/lib/action_dispatch/middleware/debug_exceptions.rb +128 -49
  81. data/lib/action_dispatch/middleware/debug_locks.rb +122 -0
  82. data/lib/action_dispatch/middleware/exception_wrapper.rb +21 -21
  83. data/lib/action_dispatch/middleware/executor.rb +19 -0
  84. data/lib/action_dispatch/middleware/flash.rb +66 -45
  85. data/lib/action_dispatch/middleware/params_parser.rb +32 -46
  86. data/lib/action_dispatch/middleware/public_exceptions.rb +2 -2
  87. data/lib/action_dispatch/middleware/reloader.rb +14 -58
  88. data/lib/action_dispatch/middleware/remote_ip.rb +29 -19
  89. data/lib/action_dispatch/middleware/request_id.rb +11 -6
  90. data/lib/action_dispatch/middleware/session/abstract_store.rb +23 -11
  91. data/lib/action_dispatch/middleware/session/cache_store.rb +9 -6
  92. data/lib/action_dispatch/middleware/session/cookie_store.rb +30 -24
  93. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +4 -0
  94. data/lib/action_dispatch/middleware/show_exceptions.rb +11 -9
  95. data/lib/action_dispatch/middleware/ssl.rb +124 -36
  96. data/lib/action_dispatch/middleware/stack.rb +44 -40
  97. data/lib/action_dispatch/middleware/static.rb +51 -35
  98. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
  99. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  100. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
  101. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  102. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  103. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +59 -63
  104. data/lib/action_dispatch/railtie.rb +2 -2
  105. data/lib/action_dispatch/request/session.rb +69 -33
  106. data/lib/action_dispatch/request/utils.rb +51 -19
  107. data/lib/action_dispatch/routing/inspector.rb +32 -43
  108. data/lib/action_dispatch/routing/mapper.rb +515 -348
  109. data/lib/action_dispatch/routing/polymorphic_routes.rb +8 -14
  110. data/lib/action_dispatch/routing/redirection.rb +5 -4
  111. data/lib/action_dispatch/routing/route_set.rb +148 -240
  112. data/lib/action_dispatch/routing/url_for.rb +27 -10
  113. data/lib/action_dispatch/routing.rb +17 -13
  114. data/lib/action_dispatch/testing/assertion_response.rb +45 -0
  115. data/lib/action_dispatch/testing/assertions/response.rb +38 -20
  116. data/lib/action_dispatch/testing/assertions/routing.rb +16 -12
  117. data/lib/action_dispatch/testing/assertions.rb +1 -1
  118. data/lib/action_dispatch/testing/integration.rb +377 -149
  119. data/lib/action_dispatch/testing/request_encoder.rb +53 -0
  120. data/lib/action_dispatch/testing/test_process.rb +24 -20
  121. data/lib/action_dispatch/testing/test_request.rb +22 -31
  122. data/lib/action_dispatch/testing/test_response.rb +12 -4
  123. data/lib/action_dispatch.rb +4 -1
  124. data/lib/action_pack/gem_version.rb +4 -4
  125. data/lib/action_pack.rb +1 -1
  126. metadata +32 -34
  127. data/lib/action_controller/metal/hide_actions.rb +0 -40
  128. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  129. data/lib/action_controller/middleware.rb +0 -39
  130. data/lib/action_controller/model_naming.rb +0 -12
  131. data/lib/action_dispatch/journey/backwards.rb +0 -5
  132. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  133. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  134. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  135. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
  136. /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
- attr_writer :sending_file
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
- # Sets the HTTP response's content MIME type. For example, in the controller
55
- # you could write this:
56
- #
57
- # response.content_type = "text/plain"
58
- #
59
- # If a character set has been defined for this response (see charset=) then
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
- @response.sending!
97
- x = @buf.each(&block)
98
- @response.sent!
99
- x
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 = [], options = {})
161
+ def initialize(status = 200, header = {}, body = [])
119
162
  super()
120
163
 
121
- default_headers = options.fetch(:default_headers, self.class.default_headers)
122
- header = merge_default_headers(header, default_headers)
164
+ @header = Header.new(self, header)
123
165
 
124
- self.body, self.header, self.status = body, header, status
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
- @content_type = content_type.to_s
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
- strings = []
220
- each { |part| strings << part.to_s }
221
- strings.join
302
+ @stream.body
222
303
  end
223
304
 
224
- EMPTY = " "
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
- def body_parts
240
- parts = []
241
- @stream.each { |x| parts << x }
242
- parts
243
- end
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
- def set_cookie(key, value)
246
- ::Rack::Utils.set_cookie_header!(header, key, value)
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
- def delete_cookie(key, value={})
250
- ::Rack::Utils.delete_cookie_header!(header, key, value)
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
- # The location header we'll be responding with.
254
- def location
255
- headers[LOCATION]
350
+ def reset_body!
351
+ @stream = build_buffer(self, [])
256
352
  end
257
- alias_method :redirect_url, :location
258
353
 
259
- # Sets the location header we'll be responding with.
260
- def location=(url)
261
- headers[LOCATION] = url
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 explict splatting:
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 = self[SET_COOKIE]
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
- end
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
- def merge_default_headers(original, default)
328
- default.respond_to?(:merge) ? default.merge(original) : original
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!(headers)
340
- return if headers[CONTENT_TYPE].present?
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
- type = @content_type.to_s.dup
346
- type << "; charset=#{@charset}" if append_charset?
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 rack_response(status, header)
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
- @original_filename = hash[:filename]
31
- if @original_filename
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