Request paramaters being shared across independent requests #2902

Closed
ruckus opened this Issue Sep 6, 2011 · 5 comments

Comments

Projects
None yet
3 participants

ruckus commented Sep 6, 2011

I first saw this issue with trying the various Rails 3.1 release candidates and I can verify its still happening in Rails 3.1 proper

In my integration tests I am seeing parameters, specifically File uploads, from one test request leak into other requests. Basically:

post photos_path, {:foo => :bar}, headers 
assert_response :success
# do something else
post users_path, {:baz => :alice}, headers 
assert_response :success

In the 2nd POST I can still see still data from the first POST deep in the Rack env variable.

I've traced it down to this line in actionpack-3.1.0/lib/action_dispatch/testing/integration.rb:284

env.reverse_merge!(default_env)

If I replace it with

env = default_env.merge(env)

then all is well.

ruckus commented Sep 7, 2011

I narrowed down the problem. Leakage from File uploads is reproducible via:

  1. Make a dummy endpoint that responds to a POST request - doesnt matter what the response is, just make it an HTTP 200

  2. Put two different files in test/fixtures/files, e.g. test/fixtures/files/alice.jpg and test/fixtures/files/bob.jpg

  3. Upload each of these to the dummy endpoint:

    params1 = {
      :photo => fixture_file_upload("/files/alice.jpg")
    }

    post v1_dummy_path, params1
    assert_response :success

    params2 = {
      :photo => fixture_file_upload("/files/bob.jpg")
    }
    post v1_dummy_path, params2
    assert_response :success

If you watch the test.log you will see the params log output still have a reference to the alice.jpg file even in the upload for bob.jpg

Started POST "/v1/dummy-request" for 127.0.0.1 at 2011-09-07 13:21:22 -0700
  Processing by V1::DummyController#dummy as HTML
  Parameters: {"photo"=>#<ActionDispatch::Http::UploadedFile:0x007feb08acfaa8 @original_filename="alice.jpg", @content_type="", @headers="Content-Disposition: form-data; name=\"photo\"; filename=\"alice.jpg\"\r\nContent-Type: \r\nContent-Length: 49564\r\n", @tempfile=#<File:/var/folders/wv/z833ztwd14z00hgn4m8148_80000gn/T/RackMultipart20110907-1951-198bzzp>>}
Instantiation Breakdown: Total: 3 | UserSession: 1 | UserDevice: 1 | User: 1
Completed 200 OK in 4ms (Views: 1.6ms | ActiveRecord: 0.0ms)


Started POST "/v1/dummy-request" for 127.0.0.1 at 2011-09-07 13:21:22 -0700
  Processing by V1::DummyController#dummy as HTML
  Parameters: {"photo"=>#<ActionDispatch::Http::UploadedFile:0x007feb08a48e68 @original_filename="alice.jpg", @content_type="", @headers="Content-Disposition: form-data; name=\"photo\"; filename=\"alice.jpg\"\r\nContent-Type: \r\nContent-Length: 49564\r\n", @tempfile=#<File:/var/folders/wv/z833ztwd14z00hgn4m8148_80000gn/T/RackMultipart20110907-1951-112iszf>>}
Instantiation Breakdown: Total: 0
Completed 200 OK in 0ms (Views: 0.2ms | ActiveRecord: 0.0ms)

ruckus commented Sep 7, 2011

Further information:

So it only seems to be happening if a 3rd parameter to the post() is happening, e.g. the headers parameter.

Thus, the above test lines are incorrect and in fact need to be something like:

headers = {'X-Hello' => 'World'}

params1 = {
 :photo => fixture_file_upload("/files/alice.jpg")
}

    post v1_dummy_path, params1, headers
    assert_response :success

    params2 = {
      :photo => fixture_file_upload("/files/bob.jpg")
    }
    post v1_dummy_path, params2, headers
    assert_response :success

yields

Started POST "/dummy" for 127.0.0.1 at 2011-09-07 13:43:04 -0700
  Processing by DummyController#dummy as HTML
  Parameters: {"photo"=>#<ActionDispatch::Http::UploadedFile:0x007fa09d0632c8 @original_filename="alice.jpg", @content_type="", @headers="Content-Disposition: form-data; name=\"photo\"; filename=\"alice.jpg\"\r\nContent-Type: \r\nContent-Length: 1442\r\n", @tempfile=#<File:/var/folders/wv/z833ztwd14z00hgn4m8148_80000gn/T/RackMultipart20110907-3631-7ti25t>>}
Rendered text template (0.0ms)
Completed 200 OK in 10ms (Views: 10.1ms | ActiveRecord: 0.0ms)


Started POST "/dummy" for 127.0.0.1 at 2011-09-07 13:43:04 -0700
  Processing by DummyController#dummy as HTML
  Parameters: {"photo"=>#<ActionDispatch::Http::UploadedFile:0x007fa09bbb2f40 @original_filename="alice.jpg", @content_type="", @headers="Content-Disposition: form-data; name=\"photo\"; filename=\"alice.jpg\"\r\nContent-Type: \r\nContent-Length: 1442\r\n", @tempfile=#<File:/var/folders/wv/z833ztwd14z00hgn4m8148_80000gn/T/RackMultipart20110907-3631-ynkuzd>>}
Rendered text template (0.0ms)
Completed 200 OK in 1ms (Views: 0.4ms | ActiveRecord: 0.0ms)

ruckus commented Sep 7, 2011

I've also discovered that if I dup() all of my headers then it skirts the issue, as the object reference is broken.

E.g. this works

headers = {'X-Hello' => 'World'}

params1 = {
  :photo => fixture_file_upload("/files/alice.jpg")
}

 post v1_dummy_path, params1, headers.dup
 assert_response :success

 params2 = {
   :photo => fixture_file_upload("/files/bob.jpg")
}
post v1_dummy_path, params2, headers.dup
assert_response :success

@ruckus Thanks for your work so far. Can you wrap all this up into some failing test cases. Seems you've already done most of the work, I just don't want to mess it up if I try to do it myself. Can you confirm this a problem on 3.2?

@ghost ghost assigned pixeltrix May 8, 2012

Owner

pixeltrix commented May 20, 2012

Fixed in this commit: 3de95fd

@pixeltrix pixeltrix closed this May 20, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment