mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Sync 'rails/rails/master'
This commit is contained in:
@@ -59,16 +59,14 @@ module ActionController
|
||||
autoload :MiddlewareStack, 'action_controller/middleware_stack'
|
||||
autoload :MimeResponds, 'action_controller/mime_responds'
|
||||
autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes'
|
||||
autoload :Request, 'action_controller/request'
|
||||
autoload :RequestParser, 'action_controller/request_parser'
|
||||
autoload :UrlEncodedPairParser, 'action_controller/url_encoded_pair_parser'
|
||||
autoload :UploadedStringIO, 'action_controller/uploaded_file'
|
||||
autoload :UploadedTempfile, 'action_controller/uploaded_file'
|
||||
autoload :RecordIdentifier, 'action_controller/record_identifier'
|
||||
autoload :Response, 'action_controller/response'
|
||||
autoload :Request, 'action_controller/request'
|
||||
autoload :RequestForgeryProtection, 'action_controller/request_forgery_protection'
|
||||
autoload :RequestParser, 'action_controller/request_parser'
|
||||
autoload :Rescue, 'action_controller/rescue'
|
||||
autoload :Resources, 'action_controller/resources'
|
||||
autoload :Response, 'action_controller/response'
|
||||
autoload :RewindableInput, 'action_controller/rewindable_input'
|
||||
autoload :Routing, 'action_controller/routing'
|
||||
autoload :SessionManagement, 'action_controller/session_management'
|
||||
autoload :StatusCodes, 'action_controller/status_codes'
|
||||
@@ -76,6 +74,9 @@ module ActionController
|
||||
autoload :TestCase, 'action_controller/test_case'
|
||||
autoload :TestProcess, 'action_controller/test_process'
|
||||
autoload :Translation, 'action_controller/translation'
|
||||
autoload :UploadedStringIO, 'action_controller/uploaded_file'
|
||||
autoload :UploadedTempfile, 'action_controller/uploaded_file'
|
||||
autoload :UrlEncodedPairParser, 'action_controller/url_encoded_pair_parser'
|
||||
autoload :UrlRewriter, 'action_controller/url_rewriter'
|
||||
autoload :UrlWriter, 'action_controller/url_rewriter'
|
||||
autoload :VerbPiggybacking, 'action_controller/verb_piggybacking'
|
||||
|
||||
@@ -18,4 +18,5 @@ use "ActiveRecord::QueryCache", :if => lambda { defined?(ActiveRecord) }
|
||||
)
|
||||
end
|
||||
|
||||
use ActionController::RewindableInput
|
||||
use ActionController::VerbPiggybacking
|
||||
|
||||
40
actionpack/lib/action_controller/rewindable_input.rb
Normal file
40
actionpack/lib/action_controller/rewindable_input.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
module ActionController
|
||||
class RewindableInput
|
||||
class RewindableIO < ActiveSupport::BasicObject
|
||||
def initialize(io)
|
||||
@io = io
|
||||
end
|
||||
|
||||
def read(*args)
|
||||
read_original_io
|
||||
@io.read(*args)
|
||||
end
|
||||
|
||||
def rewind
|
||||
read_original_io
|
||||
@io.rewind
|
||||
end
|
||||
|
||||
def method_missing(method, *args, &block)
|
||||
@io.send(method, *args, &block)
|
||||
end
|
||||
|
||||
private
|
||||
def read_original_io
|
||||
unless @str
|
||||
@str = @io.read
|
||||
@io = StringIO.new(@str)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
env['rack.input'] = RewindableIO.new(env['rack.input'])
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -123,14 +123,14 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest
|
||||
InputWrapper = Rack::Lint::InputWrapper
|
||||
|
||||
test "parses unwindable stream" do
|
||||
InputWrapper.any_instance.expects(:rewind).raises(Errno::ESPIPE)
|
||||
InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE)
|
||||
params = parse_multipart('large_text_file')
|
||||
assert_equal %w(file foo), params.keys.sort
|
||||
assert_equal 'bar', params['foo']
|
||||
end
|
||||
|
||||
test "uploads and reads file with unwindable input" do
|
||||
InputWrapper.any_instance.expects(:rewind).raises(Errno::ESPIPE)
|
||||
InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE)
|
||||
|
||||
with_test_routing do
|
||||
post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain")
|
||||
@@ -138,6 +138,26 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test "passes through rack middleware and uploads file" do
|
||||
with_muck_middleware do
|
||||
with_test_routing do
|
||||
post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain")
|
||||
assert_equal "File: Hello", response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "passes through rack middleware and uploads file with unwindable input" do
|
||||
InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE)
|
||||
|
||||
with_muck_middleware do
|
||||
with_test_routing do
|
||||
post '/read', :uploaded_data => fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain")
|
||||
assert_equal "File: Hello", response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def fixture(name)
|
||||
File.open(File.join(FIXTURE_PATH, name), 'rb') do |file|
|
||||
@@ -164,4 +184,25 @@ class MultipartParamsParsingTest < ActionController::IntegrationTest
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
class MuckMiddleware
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
req = Rack::Request.new(env)
|
||||
req.params # Parse params
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
def with_muck_middleware
|
||||
original_middleware = ActionController::Dispatcher.middleware
|
||||
middleware = original_middleware.dup
|
||||
middleware.use MuckMiddleware
|
||||
ActionController::Dispatcher.middleware = middleware
|
||||
yield
|
||||
ActionController::Dispatcher.middleware = original_middleware
|
||||
end
|
||||
end
|
||||
|
||||
@@ -150,8 +150,45 @@ class UrlEncodedParamsParsingTest < ActionController::IntegrationTest
|
||||
assert_parses expected, query
|
||||
end
|
||||
|
||||
test "passes through rack middleware and parses params" do
|
||||
with_muck_middleware do
|
||||
assert_parses({ "a" => { "b" => "c" } }, "a[b]=c")
|
||||
end
|
||||
end
|
||||
|
||||
# The lint wrapper is used in integration tests
|
||||
# instead of a normal StringIO class
|
||||
InputWrapper = Rack::Lint::InputWrapper
|
||||
|
||||
test "passes through rack middleware and parses params with unwindable input" do
|
||||
InputWrapper.any_instance.stubs(:rewind).raises(Errno::ESPIPE)
|
||||
with_muck_middleware do
|
||||
assert_parses({ "a" => { "b" => "c" } }, "a[b]=c")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
class MuckMiddleware
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
req = Rack::Request.new(env)
|
||||
req.params # Parse params
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
def with_muck_middleware
|
||||
original_middleware = ActionController::Dispatcher.middleware
|
||||
middleware = original_middleware.dup
|
||||
middleware.use MuckMiddleware
|
||||
ActionController::Dispatcher.middleware = middleware
|
||||
yield
|
||||
ActionController::Dispatcher.middleware = original_middleware
|
||||
end
|
||||
|
||||
def with_test_routing
|
||||
with_routing do |set|
|
||||
set.draw do |map|
|
||||
|
||||
Reference in New Issue
Block a user