Skip to content

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

Open
marcandre opened this Issue Jul 18, 2012 · 12 comments

5 participants

@marcandre

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

@jferris
thoughtbot, inc. member
jferris commented Jul 19, 2012

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 (jnicklas/capybara#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.

@marcandre

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.

@jferris
thoughtbot, inc. member
jferris commented Jul 19, 2012

@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.

@marcandre

There is a failing test at the end...

@jferris
thoughtbot, inc. member
jferris commented Jul 19, 2012

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

@marcandre

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

@mhoran
mhoran commented Jul 3, 2014

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 mhoran closed this Jul 3, 2014
@delphaber

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

@jferris
thoughtbot, inc. member
jferris commented Nov 30, 2015

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

@delphaber

@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!

@jferris jferris added a commit that referenced this issue Dec 9, 2015
@jferris jferris wip: Missing status on empty failed AJAX requests
If a request returns a non-200, empty response, the XHR object will have
a status of 0 with no headers.

Status: failing test

Reproduces issue reported in #359.
d6c72bc
@jferris
thoughtbot, inc. member
jferris commented Dec 9, 2015

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

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

@jferris jferris reopened this Dec 9, 2015
@raymondberg

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.