Permalink
Browse files

[merb-core] Specs, very minor performance work

  * Body request parameters should now only be parsed once
  * The multipart request helper specs pass with the new Rack middleware
  * Add character set handling specs for multipart requests
    (discussion is pending)
  • Loading branch information...
ngollan committed Apr 12, 2011
1 parent d6939f5 commit 918fd9c2d0cbfe05deae1ac2a444ff1c5c9ead8b
@@ -28,18 +28,15 @@ class Request
# Initialize the request object.
#
- # @todo Fix docs.
- # #### Parameters
- # http_request<~params:~[], ~body:IO>::
- # An object like an HTTP Request.
+ # @param [Hash] A Rack-conformant request environment.
#
# @api private
- def initialize(rack_env)
+ def initialize(rack_env)
@env = rack_env
@body = rack_env[Merb::Const::RACK_INPUT]
@route_params = {}
end
-
+
# Memoizes the new request object into env["merb.request"] so we
# can memoize things into ivars in the request
#
@@ -272,6 +269,8 @@ def json_params
jobj = Mash.new
end
jobj.is_a?(Hash) ? jobj : { :inflated_object => jobj }
+ else
+ {}
end
end
end
@@ -283,6 +282,8 @@ def xml_params
@xml_params ||= begin
if Merb::Const::XML_MIME_TYPE_REGEXP.match(content_type)
Hash.from_xml(raw_post) rescue Mash.new
+ else
+ {}
end
end
end
@@ -299,9 +300,9 @@ def xml_params
def params
@params ||= begin
h = body_and_query_params.merge(route_params)
- h.merge!(multipart_params) if self.class.parse_multipart_params && multipart_params
- h.merge!(json_params) if self.class.parse_json_params && json_params
- h.merge!(xml_params) if self.class.parse_xml_params && xml_params
+ h.merge!(multipart_params) if self.class.parse_multipart_params
+ h.merge!(json_params) if self.class.parse_json_params
+ h.merge!(xml_params) if self.class.parse_xml_params
h
end
end
@@ -1,23 +1,31 @@
+# encoding: utf-8
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
+
+require 'base64'
+
startup_merb
module Merb::MultipartRequestSpecHelper
- def fake_file(read = nil, filename = 'sample.txt', path = 'sample.txt')
+ def fake_file(read = nil, filename = 'sample.txt', path = filename)
read ||= 'This is a text file with some small content in it.'
Struct.new(:read, :filename, :path).new(read, filename, path)
end
+
+ def fake_multipart_request(file)
+ m = Merb::Test::MultipartRequestHelper::Post.new(:file => file)
+ body, head = m.to_multipart
+ fake_request({:request_method => "POST", :content_type => head, :content_length => body.length}, :req => body)
+ end
end
describe Merb::Request do
include Merb::MultipartRequestSpecHelper
it "should handle file upload for multipart/form-data posts" do
file = fake_file
- m = Merb::Test::MultipartRequestHelper::Post.new(:file => file)
- body, head = m.to_multipart
- request = fake_request({:request_method => "POST",
- :content_type => head,
- :content_length => body.length}, :req => body)
+ request = fake_multipart_request(file)
+
request.params[:file].should_not be_nil
request.params[:file][:tempfile].class.should == Tempfile
request.params[:file][:content_type].should == 'text/plain'
@@ -31,6 +39,36 @@ def fake_file(read = nil, filename = 'sample.txt', path = 'sample.txt')
body.split('----------0xKhTmLbOuNdArY').size.should eql(5)
end
+ describe "character set handling" do
+ it "should be tested in a sane environment" do
+ "\xC3\xBE".should == "þ"
+ end
+
+ it "should support quoted-printable encoding for parameters" do
+ # straight from RFC 2047, Section 2
+ file = fake_file(nil, "=?iso-8859-1?q?this=20is=20some=20text?=")
+ request = fake_multipart_request(file)
+
+ request.params[:file][:filename].should == "this is some text"
+ end
+
+ it "should support base64 encoding for parameters" do
+ file = fake_file(nil, "=?iso-8859-1?b?#{Base64.encode64('this is some text').strip}?=")
+ request = fake_multipart_request(file)
+
+ request.params[:file][:filename].should == "this is some text"
+ end
+
+ it "should receive UTF-8 data from other encodings" do
+ # File name is Symbol "Thorn"
+ file = fake_file(nil, "=?iso-8859-1?q?=FE?=")
+ request = fake_multipart_request(file)
+
+ # Thorn in UTF-8
+ request.params[:file][:filename].should == "\xC3\xBE"
+ end
+ end
+
it "should correctly format multipart posts which contain an array as parameter" do
file = fake_file
file2 = fake_file("This is another text file", "sample2.txt", "sample2.txt")
@@ -54,25 +92,25 @@ def fake_file(read = nil, filename = 'sample.txt', path = 'sample.txt')
file = fake_file
m = Merb::Test::MultipartRequestHelper::Post.new :file => file
body, head = m.to_multipart
-
+
t = Tempfile.new("io")
t.write(body)
t.close
-
+
fd = IO.sysopen(t.path)
io = IO.for_fd(fd,"r")
request = Merb::Test::RequestHelper::FakeRequest.new({:request_method => "POST", :content_type => 'multipart/form-data, boundary=----------0xKhTmLbOuNdArY', :content_length => body.length},io)
- running {request.params}.should_not raise_error
+ running {request.params}.should_not raise_error
request.params[:file].should_not be_nil
request.params[:file][:tempfile].class.should == Tempfile
request.params[:file][:content_type].should == 'text/plain'
request.params[:file][:size].should == file.read.length
- end
-
+ end
+
it "should handle GET with a content_type but an empty body (happens in some browsers such as safari after redirect)" do
request = fake_request({:request_method => "GET", :content_type => 'multipart/form-data, boundary=----------0xKhTmLbOuNdArY', :content_length => 0}, :req => '')
- running {request.params}.should_not raise_error
+ running {request.params}.should_not raise_error
end
it "should handle multiple occurences of one parameter" do
@@ -43,62 +43,58 @@
end
describe "#multipart_post" do
- pending "needs proper spec code (Webrat)" do
- before(:each) do
- Merb::Router.prepare do
- resources :spec_helper_controller
- end
+ before(:each) do
+ Merb::Router.prepare do
+ resources :spec_helper_controller
end
+ end
- it "should post to the create action with params" do
- resp = multipart_post("/spec_helper_controller", :name => "Harry")
- JSON(resp.body.to_s)["name"].should == "Harry"
- end
+ it "should post to the create action with params" do
+ resp = multipart_post("/spec_helper_controller", :name => "Harry")
+ JSON(resp.body.to_s)["name"].should == "Harry"
+ end
- it "should upload a file to the action using multipart" do
- file_name = File.join(File.dirname(__FILE__), "multipart_upload_text_file.txt")
- File.open( file_name ) do |file|
- resp = multipart_post("/spec_helper_controller", :my_file => file)
- file_params = JSON(resp.body.to_s)["my_file"]
- file_params["content_type"].should == "text/plain"
- file_params["size"].should == File.size(file_name)
- file_params["tempfile"].should =~ /#<File:.*>/
- file_params["filename"].should == "multipart_upload_text_file.txt"
- end
+ it "should upload a file to the action using multipart" do
+ file_name = File.join(File.dirname(__FILE__), "multipart_upload_text_file.txt")
+ File.open( file_name ) do |file|
+ resp = multipart_post("/spec_helper_controller", :my_file => file)
+ file_params = JSON(resp.body.to_s)["my_file"]
+ file_params["content_type"].should == "text/plain"
+ file_params["size"].should == File.size(file_name)
+ file_params["tempfile"].should =~ /#<File:.*>/
+ file_params["filename"].should == "multipart_upload_text_file.txt"
end
end
end
describe "#multipart_put" do
- pending "needs proper spec code (Webrat)" do
- before(:each) do
- Merb::Router.prepare do
- resources :spec_helper_controller
- end
+ before(:each) do
+ Merb::Router.prepare do
+ resources :spec_helper_controller
end
+ end
- it "should put to the update action with multipart params" do
- Merb::Test::ControllerAssertionMock.should_receive(:called).with(:update)
- resp = multipart_put("/spec_helper_controller/my_id", :name => "Harry")
+ it "should put to the update action with multipart params" do
+ Merb::Test::ControllerAssertionMock.should_receive(:called).with(:update)
+ resp = multipart_put("/spec_helper_controller/my_id", :name => "Harry")
- params = JSON(resp.body.to_s).to_mash
- params[:name].should == "Harry"
- params[:id].should == "my_id"
- end
+ params = JSON(resp.body.to_s).to_mash
+ params[:name].should == "Harry"
+ params[:id].should == "my_id"
+ end
- it "should upload a file to the action using multipart" do
- Merb::Test::ControllerAssertionMock.should_receive(:called).with(:update)
- file_name = File.join(File.dirname(__FILE__), "multipart_upload_text_file.txt")
- File.open( file_name ) do |file|
- resp = multipart_put("/spec_helper_controller/my_id", :my_file => file)
- params = JSON(resp.body.to_s).to_mash
- params[:id].should == "my_id"
- file_params = params[:my_file]
- file_params[:content_type].should == "text/plain"
- file_params[:size].should == File.size(file_name)
- file_params[:tempfile].should =~ /#<File:.*>/
- file_params[:filename].should == "multipart_upload_text_file.txt"
- end
+ it "should upload a file to the action using multipart" do
+ Merb::Test::ControllerAssertionMock.should_receive(:called).with(:update)
+ file_name = File.join(File.dirname(__FILE__), "multipart_upload_text_file.txt")
+ File.open( file_name ) do |file|
+ resp = multipart_put("/spec_helper_controller/my_id", :my_file => file)
+ params = JSON(resp.body.to_s).to_mash
+ params[:id].should == "my_id"
+ file_params = params[:my_file]
+ file_params[:content_type].should == "text/plain"
+ file_params[:size].should == File.size(file_name)
+ file_params[:tempfile].should =~ /#<File:.*>/
+ file_params[:filename].should == "multipart_upload_text_file.txt"
end
end
end

0 comments on commit 918fd9c

Please sign in to comment.