Browse files

Add tests for multipart uploads. Also ensure multipart parser tries t…

…o rewind the input stream.
  • Loading branch information...
1 parent d6fa6af commit 3513f4fd106eaf8259bd1b16def343cce95d66ec @josh josh committed Jan 13, 2009
Showing with 65 additions and 1 deletion.
  1. +7 −1 lib/rack/request.rb
  2. +7 −0 lib/rack/utils.rb
  3. +10 −0 test/multipart/text_file
  4. +41 −0 test/spec_rack_utils.rb
View
8 lib/rack/request.rb
@@ -121,7 +121,13 @@ def POST
Utils::Multipart.parse_multipart(env)
@env["rack.request.form_vars"] = @env["rack.input"].read
@env["rack.request.form_hash"] = Utils.parse_query(@env["rack.request.form_vars"])
- @env["rack.input"].rewind if @env["rack.input"].respond_to?(:rewind)
+
+ begin
+ @env["rack.input"].rewind if @env["rack.input"].respond_to?(:rewind)
+ rescue Errno::ESPIPE
+ # Handles exceptions raised by input streams that cannot be rewound
+ # such as when using plain CGI under Apache
+ end
end
@env["rack.request.form_hash"]
else
View
7 lib/rack/utils.rb
@@ -311,6 +311,13 @@ def self.parse_multipart(env)
break if buf.empty? || content_length == -1
}
+ begin
+ input.rewind if input.respond_to?(:rewind)
+ rescue Errno::ESPIPE
+ # Handles exceptions raised by input streams that cannot be rewound
+ # such as when using plain CGI under Apache
+ end
+
params
end
end
View
10 test/multipart/text_file
@@ -0,0 +1,10 @@
+--AaB03x
+Content-Disposition: form-data; name="submit-name"
+
+Larry
+--AaB03x
+Content-Disposition: form-data; name="files"; filename="file1.txt"
+Content-Type: text/plain
+
+contents
+--AaB03x--
View
41 test/spec_rack_utils.rb
@@ -150,3 +150,44 @@ def context env, app=@app; app.call(env); end
r4.body.should.equal r5.body
end
end
+
+context "Rack::Utils::Multipart" do
+ specify "should return nil if content type is not multipart" do
+ env = Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded')
+ Rack::Utils::Multipart.parse_multipart(env).should.equal nil
+ end
+
+ specify "should parse multipart upload with text file" do
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:text_file))
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ params["files"][:type].should.equal "text/plain"
+ params["files"][:filename].should.equal "file1.txt"
+ params["files"][:head].should.equal "Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\n"
+ params["files"][:name].should.equal "files"
+ params["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "rewinds input after parsing upload" do
+ options = multipart_fixture(:text_file)
+ input = options[:input]
+ env = Rack::MockRequest.env_for("/", options)
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ input.read.length.should.equal 197
+ end
+
+ private
+ def multipart_fixture(name)
+ file = File.join(File.dirname(__FILE__), "multipart", name.to_s)
+ data = File.read(file)
+
+ type = "multipart/form-data; boundary=AaB03x"
+ length = data.length.to_s
+
+ { "CONTENT_TYPE" => type,
+ "CONTENT_LENGTH" => length,
+ :input => StringIO.new(data) }
+ end
+end

0 comments on commit 3513f4f

Please sign in to comment.