views:

372

answers:

4

I'm trying to load-test a Rails application using JMeter. A critical part of the application involves a form that includes both text inputs and file uploads. It works fine in a browser, but when I try to post that page in JMeter, Rails is saving all of the parts of the multipart form as temp files, which causes things to break when it's looking for a string and gets a tempfile instead.

It appears that the difference is that, from a browser, the piece of the multipart request that contains a text input looks like this:

-----------------------------7d93b4186074c
Content-Disposition: form-data; name="field_name"

test
-----------------------------7d93b4186074c

while from JMeter it looks like this:

-----------------------------7d159c1302d0y0
Content-Disposition: form-data; name="field_name"
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

test
-----------------------------7d159c1302d0y0

So apparently Rails sees the former and interprets it as a plain text value and treats it as a string, but sees the latter and saves it to a temp file.

I have not been able to find a setting to convince JMeter not to send the additional headers in the multipart form for non-file fields.

Is there a way to convince Rails to ignore those headers and treat the text/plain text as strings instead of text files? Or a quick way to put a filter in front of my controller that will strip the extra headers?

Alternately, is there a better tool to load-test a Rails application that includes file upload?

A: 

There may be a better way, but I ended up adding a quick filter to turn the text/plain tempfiles into strings within the parameter hash:

  def change_text_files_to_strings
    params.each_pair do |key, value|
      params[key] = value.read if (value.class.to_s=='Tempfile' && value.content_type.start_with?('text/plain') )
    end
  end

By the way, it turns out that jmeter is correct here, and rails incorrect: according to RFC 2388, each item in a multipart request should have a content type (not just files), so Rails really shouldn't be using the presence of a content-type header to determine whether it's a file. Ah well.

JacobM
A: 

I also used the solution above as ColdFusion was sending similar headers (minus the Content-Transfer-Encoding) with each piece of form data. I wonder if there's a better way.

EDIT: Anyone know if this has been fixed in Rails 3?

Groovetrain
A: 

I have exact the same problem, but I haven't authorized to modify the rails application. That's the biggest problem that I have right now :(

Koji
+1  A: 

So, I have customized JMeter's multipart request posting part in the source code to put out the request that rails understand. The change is easy as shown below but to create compiling Java/JMeter environment took time. :(

Anyways, now I can successfully upload a file by multipart post via JMeter.


in src/protocol/http/org/apache/jmeter/protocol/http/sampler/PostWriter.java

writeStartFileMultipart()
//writeln(out, "Content-Transfer-Encoding: binary"); // $NON-NLS-1$

writeFormMultipart()
/*****
writeln(out, "Content-Type: text/plain; charset=" + charSet); // $NON-NLS-1$
writeln(out, "Content-Transfer-Encoding: 8bit"); // $NON-NLS-1$
*****/

P.S.

A tip tip to create the build environment for 2.4 is

  1. to comment out the 3rd party libraries check in build.xml file.

  2. copy lib/xstream-1.3.1.jar from binary archive into lib/ directory

Koji
Ain't open-source great!
JacobM