Fixes issue with multipart forms being submitted as x-www-form-urlencoded when they contain an empty file field

This commit is contained in:
Jonas Nicklas 2010-12-06 01:22:59 -06:00 committed by Ryan Kinderman
parent b022ca9926
commit 29898295dc
4 changed files with 55 additions and 8 deletions

View File

@ -97,6 +97,21 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
end
class Form < Node
# This only needs to inherit from Rack::Test::UploadedFile because Rack::Test checks for
# the class specifically when determing whether to consturct the request as multipart.
# That check should be based solely on the form element's 'enctype' attribute value,
# which should probably be provided to Rack::Test in its non-GET request methods.
class NilUploadedFile < Rack::Test::UploadedFile
def initialize
@empty_file = Tempfile.new("nil_uploaded_file")
@empty_file.close
end
def original_filename; ""; end
def content_type; "application/octet-stream"; end
def path; @empty_file.path; end
end
def params(button)
params = {}
@ -122,14 +137,17 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
end
end
native.xpath(".//input[not(@disabled) and @type='file']").map do |input|
unless input['value'].to_s.empty?
if multipart?
content_type = MIME::Types.type_for(input['value'].to_s).first.to_s
file = Rack::Test::UploadedFile.new(input['value'].to_s, content_type)
merge_param!(params, input['name'].to_s, file)
else
merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s))
end
if multipart?
file = \
if (value = input['value']).to_s.empty?
NilUploadedFile.new
else
content_type = MIME::Types.type_for(value).first.to_s
Rack::Test::UploadedFile.new(value, content_type)
end
merge_param!(params, input['name'].to_s, file)
else
merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s))
end
end
merge_param!(params, button[:name], button[:value] || "") if button[:name]

View File

@ -77,6 +77,14 @@ class TestApp < Sinatra::Base
'<pre id="results">' + params[:form].to_yaml + '</pre>'
end
post '/upload_empty' do
if params[:form][:file].nil?
'Successfully ignored empty file field.'
else
'Something went wrong.'
end
end
post '/upload' do
begin
buffer = []

View File

@ -250,6 +250,17 @@
<p>
</form>
<form action="/upload_empty" method="post" enctype="multipart/form-data">
<p>
<label for="form_file_name">File Name</label>
<input type="file" name="form[file]" id="form_file"/>
</p>
<p>
<input type="submit" value="Upload Empty"/>
<p>
</form>
<form action="/upload" method="post" enctype="multipart/form-data">
<p>
<label for="form_file_name">File Name</label>

View File

@ -26,6 +26,16 @@ describe Capybara::Session do
end
end
describe "#attach_file" do
context "with multipart form" do
it "should submit an empty form-data section if no file is submitted" do
@session.visit("/form")
@session.click_button("Upload Empty")
@session.body.should include('Successfully ignored empty file field.')
end
end
end
it_should_behave_like "session"
it_should_behave_like "session without javascript support"
it_should_behave_like "session with headers support"