HTTP Request returns 200 OK but no content in response

pacifier21 picture pacifier21 · Apr 29, 2014 · Viewed 30.5k times · Source

In developing a particular web site, I have an intermittent issue when loading the site in Firefox (haven't been able to compare in IE or Chrome). The site loads several javascript files, css stylesheets, images, etc. Occasionally, one or more of the files fail to load properly. The response indicates a status of 200 OK, but the content-length indicates 0. This happens on different files at different times. When it is a javascript file that fails to load, the site does not function properly, but may still display content. When it happens to be the index.html file that fails to load, Firefox displays an empty page with the following html:

<html>
<head></head>
<body><pre></pre></body>
</html>

(I believe this comes from Firefox as the default "empty" page view)

It appears that previous successful loads may be fetched properly from the browser cache, and the response status is 304 Not Modified. After a failure, the next time the resource is requested we see a response status of 200 OK, with subsequent requests again responding with 304's.

Here are examples of the request/response headers as reported by Firebug:


General Success Case: (Response Status: 304 Not Modified, Content-length: 288)

Request Headers:

Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en/q=0.5
Connection: keep-alive
Cookie: JSESSIONID=<shouldn't matter>
Host: ???.???.???.???:8442
If-Modified-Since: Tue, 29 Apr 2014 13:18:26 GMT
If-None-Match: W/"228-1398777506000"
Referrer: https://???.???.???.???:8442/mySite/
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20131023 Firefox/17.0 

Response Headers:

Cache-Control: no-cache
Date: Tue, 29 Apr 2014 13:36:35 GMT
Etag: W/"288-1398777506000"
Expires: Thu, 01 Jan 1970 00:00:00 GMT-00:00
Pragma: No-cache
Server: Apache-Coyote/1.1 

Response Headers From Cache:

Accept-Ranges: bytes
Cache-Control: no-cache
Content-Length: 288
Content-Type: text/javascript
Date: Tue, 29 Apr 2014 13:36:35 GMT
Etag: W/"288-1398777506000"
Expires: Thu, 01 Jan 1970 00:00:00 GMT-00:00
Last-Modified: Tue, 29 Apr 2014 13:18:26 GMT
Pragma: No-cache
Server: Apache-Coyote/1.1 

The Cache tab in Firebug indicates the following:

Data Size: 288
Device: disk
Expires: Wed Dec 31 1969 18:00:00 GMT-06:00 (CST)
Fetch Count: 81
Last Fetched: Tue Apr 29 2014 08:28:35 GMT-05:00 (CDT)
Last Modified: Tue Apr 29 2014 08:28:35 GMT-05:00 (CDT) 

Failed Case: (Response Status: 200 OK, Content-length: 0)

Request Headers:

Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en/q=0.5
Connection: keep-alive
Cookie: JSESSIONID=<same as above>
Host: ???.???.???.???:8442
If-Modified-Since: Tue, 29 Apr 2014 13:18:26 GMT
If-None-Match: W/"228-1398777506000"
Referrer: https://???.???.???.???:8442/mySite/
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20131023 Firefox/17.0 

Response Headers:

Content-Length: 0
Date: Tue, 29 Apr 2014 13:36:28 GMT
Server: Apache-Coyote/1.1 

The Cache tab in Firebug indicates the following:

Data Size: 
Device: disk
Expires: Wed Dec 31 1969 18:00:00 GMT-06:00 (CST)
Fetch Count: 83
Last Fetched: Tue Apr 29 2014 08:28:42 GMT-05:00 (CDT)
Last Modified: Tue Apr 29 2014 08:28:42 GMT-05:00 (CDT) 

Next Success Case: (Response Status: 200 OK, Content-length: 288)

Request Headers:

Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en/q=0.5
Connection: keep-alive
Cookie: JSESSIONID=<same as above>
Host: ???.???.???.???:8442
Referrer: https://???.???.???.???:8442/mySite/
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20131023 Firefox/17.0 

Response Headers:

Accept-Ranges: bytes
Cache-Control: no-cache
Content-Length: 288
Content-Type: text/javascript
Date: Tue, 29 Apr 2014 13:37:03 GMT
Etag: W/"288-1398777506000"
Expires: Thu, 01 Jan 1970 00:00:00 GMT-00:00
Last-Modified: Tue, 29 Apr 2014 13:18:26 GMT
Pragma: No-cache
Server: Apache-Coyote/1.1 

The Cache tab in Firebug indicates the following:

Data Size: 288
Device: disk
Expires: Wed Dec 31 1969 18:00:00 GMT-06:00 (CST)
Fetch Count: 85
Last Fetched: Tue Apr 29 2014 08:28:54 GMT-05:00 (CDT)
Last Modified: Tue Apr 29 2014 08:28:53 GMT-05:00 (CDT) 

We are hosting the site in JBoss-EAP v6.1, and I have tried this in Firefox 10, 17 and 24 with the same results. I understand there are newer versions available (not to mention different browsers), but they aren't necessarily an option for us. I'm hoping the solution is a simple configuration change, but in my attempts at searching for this issue I have not seen anyone having the same problem, so it may not be so simple. I appreciate any suggestions. Also, please let me know if I need to provide more information (e.g., web.xml, jboss.conf, etc)

Other products in the mix:

  • Require.js v2.1.2
  • Java 1.6
  • CAS 3.2.1
  • Atmosphere 2.1.3

Update: I have essentially ruled out the possibility of a cache issue. I implemented a cache busting module load process as suggested in the RequireJS API page, and I still see the problem. This time, however, instead of all of the 304 status codes, they are all 200's.


Update 2: I downloaded the source for JBossWeb 7.2.0.Final and worked through debugging this issue. Apparently there is a class called org.apache.coyote.http11.Http11ConnectionHandler that maintains a pool of Http11Processor instances, each with its own Request and Response objects. When a request is completed, the Http11Processor is "recycled" and put back into the pool.

It appears that there may be a threading issue in the recycling logic because the Response.recycle is supposed to set the "committed" to false, but my (conditional) breakpoint immediately after call to response.recycle() stops with response.committed == true. This is what causes the failed responses later on. When a Http11Processor that contains an already committed Response object, the Response can not be used to return any information. It simply responds with Status: 200, Content-Length: 0.

This seems to be happening when I close a website that has an Atmosphere connection that uses Server Side Events. Am I using the Atmosphere connection improperly? Is there special cleanup logic I should be implementing?

Answer

pacifier21 picture pacifier21 · May 14, 2014

After a lot of investigation and debugging, I found out that the Atmosphere library was being allowed to manipulate a Response object that had been recycled and getting used for a later request. The affected Response was given a status of 200, content-length of 0, and it was committed such that no other modifications could be made. The unlucky request thread that is given this "corrupted" Response instance is unable to be used to provide the actual content.

To prevent this modification from affecting the JBoss server, I added the following to the jboss.properties file:

org.apache.catalina.connector.RECYCLE_FACADES=true

Another option is to use a Security Manager. (See the Security section of this page, and the advice offered in the last few paragraphs of this page)

This apparently prevents recycling of requests and responses, so we always get a fresh Response instance for each request.