capybara-webkit icon indicating copy to clipboard operation
capybara-webkit copied to clipboard

No response headers when body is empty and status code is not 200

Open marcandre opened this issue 13 years ago • 14 comments

If an Ajax request is made and the response has:

  1. status code != 200 (e.g. == 404), and
  2. empty body Then the request headers in javascript are empty and the status code is 0.

If the body contains something (e.g. a single character) or the status code is 200, then things work as they should.

To reproduce:

# routes:
match '/test' => 'test#test' 

# test_controller.rb:
class TestController < ActionController::Base
  def test
    if params[:status]
      response.status = params[:status]
      render text: params[:content] || ''
    else
      render :inline => <<-EHTML
        <html><head>
          <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
        </head><body><script>
          var opt = {complete: function(xhr){
            jQuery('body').append(xhr.status + "|" + xhr.getAllResponseHeaders());
          }};
          jQuery.ajax('/test?status=200', opt);
          jQuery.ajax('/test?status=403&content=x', opt);
          jQuery.ajax('/test?status=404', opt);
        </script></body></html>
      EHTML
    end
  end
end

# spec:
visit '/test'
page.should have_content '200|Connection:'
page.should have_content '403|Connection:'
page.should have_content '404|Connection:'

The test fails with:

 Failure/Error: page.should have_content '404|Connection:'
   expected there to be content "404|Connection:" in "200|Connection: close X-Request-Id: 4a8610c53c3814aea253cc67718ce4e9 X-UA-Compatible: IE=Edge,chrome=1 X-Runtime: 0.028846 Server: thin 1.3.1 codename Triple Espresso Content-Type: text/html; charset=utf-8 Cache-Control: no-cache 0|403|Connection: close X-Request-Id: 01fe49609c2395c25acf87d50817aaad X-UA-Compatible: IE=Edge,chrome=1 X-Runtime: 0.002853 Server: thin 1.3.1 codename Triple Espresso Content-Type: text/html; charset=utf-8 Cache-Control: no-cache"

Response will vary, but notice the "0|" which indicated a status code of 0 (instead of 404) and no headers whatsoever.

The text shows correctly in Chrome, Firefox and Safari.

Using capybara-webkit (0.12.1) on OS X

marcandre avatar Jul 18 '12 05:07 marcandre

This is sort of complicated, but I think your application is actually returning a response code of 0.

The default setting for the Rails test environment is to raise exceptions instead of rescuing and displaying them (this is the config.action_dispatch.show_exceptions setting). This is useful in single-threaded test setups like controller specs and rack-test, but it means that the exception is sent to the application server (webrick or thin) on multithreaded setups like capybara-webkit and selenium. The invalid responses that result from these exceptions are interpreted by capybara-webkit as response code zero.

There's been some work in capybara (https://github.com/jnicklas/capybara/pull/660) to improve this situation. For now, I'd recommend turning show_exceptions to true or using @allow-rescue from cucumber-rails, which will allow capybara-webkit to actually see errors like 404s and 500s.

jferris avatar Jul 19 '12 01:07 jferris

Thanks for the reply, but have you looked at the code I submitted?

There are no exceptions involved. The status code 404 is generated by me, manually. It could be some other code, like 403.

Also, when tested in a real browser, things work as they should and you get the 403/404 or whatever status that was generated.

Finally, nothing in your explanation addresses why there is a difference between an empty body and a non empty one.

marcandre avatar Jul 19 '12 03:07 marcandre

@marcandre sorry, I missed that. I'll try to reproduce this when I can. If you get a chance to put together a failing test, that would help speed things up.

jferris avatar Jul 19 '12 03:07 jferris

There is a failing test at the end...

marcandre avatar Jul 19 '12 03:07 marcandre

@marcandre sorry - to be clear, I meant a failing spec in capybara-webkit.

jferris avatar Jul 19 '12 17:07 jferris

Hmmm, I don't have the time, and it should be much easier for someone who knows the codebase, based on my very simple example. Thanks

marcandre avatar Jul 19 '12 19:07 marcandre

We've long since reworked our connection handling code. Headers and status codes are handled completely differently, resolving this issue. Please reopen if you're still having issues in the latest version.

mhoran avatar Jul 03 '14 05:07 mhoran

Still happening with * capybara-webkit (1.7.1)

Resolved with

render json: { blacklisted: true }, status: :unprocessable_entity

instead of

head :unprocessable_entity

in my controller

delphaber avatar Nov 25 '15 17:11 delphaber

@delphaber is there a minimal test case you could put together to reproduce the issue?

jferris avatar Nov 30 '15 21:11 jferris

@jferris this is a demo that I just prepared with latest version of suspenders and angular. See the README.md for more information. I hope this could help!

delphaber avatar Dec 08 '15 09:12 delphaber

I managed to put together a failing test in d6c72bcd33fb9be77940eebe3b5149cb1fba13a1 that reproduces the issue.

I'm not sure if this is an issue in QtWebKit or related to how we handle requests.

jferris avatar Dec 09 '15 22:12 jferris

I love this; we're running into the same problem but with redirects. Would be great to get this resolved.

raymondberg avatar May 06 '16 16:05 raymondberg

Still affected on Capybara 2.17.0, but I'm not using capybara-webkit. Is this a Capybara issue?

mdesantis avatar Feb 03 '18 10:02 mdesantis

@mdesantis It's an issue with whatever driver you are using. If you're not using capybara-webkit then I'm guessing Poltergeist since PhantomJS (used by poltergeist) is built on the same era of QtWebkit as capybara-webkit builds against.

twalpole avatar Feb 04 '18 18:02 twalpole