Bug 32829

Summary: Blank page is displayed if server gives 304 status in response to unconditional request
Product: WebKit Reporter: Juti Noppornpitak <jnopporn>
Component: Page LoadingAssignee: Nobody <webkit-unassigned>
Severity: Major CC: anisimovandr, jnopporn, mrowe
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Mac (Intel)   
OS: OS X 10.6   

Description Juti Noppornpitak 2009-12-21 11:13:25 PST
Defected versions
* Safari: 4.0.4
* Webkit: 532.7+
* Google:

When the web server with caching feature enabled returns HTTP 304, the browser shows a blank page. When I use the web inspector, I found nothing in the response body which is normal as any web server gives nothing back on HTTP 304.

Before reproducing:
To quickly reproduce the problem, you will need to know how to write Python (http://python.org) and how to use Pylons web framework (http://pylonshq.com). On Mac OS X, to install it, open Terminal (Terminal.app) and type "sudo easy_install pylons".

How to reproduce:
0. Open the console or Terminal (or Terminal.app).
1. Create a Pylons application called "dummy_app" by running "paster create -t pylons dummy_app" w/o quotes in your console.
2. Run "cd dummy_app && paster serve --reload development.ini" w/o quotes in your console.
3. In your console, run "paster controller core" to create a controller called "core" with only one method "index" where the method "index" returns "Hello, World".
4. Then, open in both Firefox and Safari.
5. After successfully opening the page in both browsers, add response.status=304 before the return statement in "def index" in dummy_app/controllers/core.py to force the WSGI server to return HTTP 304.
6. Then, reload the page on both browsers.
X. Then, while I can see "Hello, World" displaying on Firefox, I see nothing on Safari.

Expected result:
I should be able to see what I see on Firefox.

Notes and educational guesses:
1. I tried to compare on Firefox 3.5, Safari 4 (latest stable), nightly-build Webkit and Google Chrome 4 beta for Mac. All Webkit-based browsers show me a blank page.
2. My educational guess is that Webkit does not properly handle HTTP 304.
3. There are several bugs reported previously like Bug 25786 (https://bugs.webkit.org/show_bug.cgi?id=25786) and Bug 22084 (https://bugs.webkit.org/show_bug.cgi?id=22084). They might be related to the problem. Or they might be caused by this problem.
4. The reproduction step is 100%. You will see the bug for sure.
Comment 1 Mark Rowe (bdash) 2009-12-21 23:06:51 PST
This sounds like the sort of behavior that would result if a web server returned a 304 Not Modified status in response to an unconditional GET.  Are you able to quickly confirm if this is what is happening before I spend a bunch of time installing all of the software you mentioned in your description?
Comment 2 Mark Rowe (bdash) 2009-12-21 23:10:17 PST
The most reliable way to confirm this would be to look at a tcpdump session of the request / response when performing step 6 in your instructions.  You can do that using something like “sudo tcpdump -n -s 0 -A -i lo0 port 5000” prior to reloading the page.
Comment 3 Mark Rowe (bdash) 2009-12-22 00:19:17 PST
I found a spare VM to install the software on and confirmed my suspicion.  The default response for /core/index includes the following headers instructing the browser to not cache the page:

Pragma: no-cache
Cache-control: no-cache

After tweaking the handler to force the 304 response and hitting reload I see Safari issue a request like so:

GET /core/index HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive

Note that there are no conditional headers such as If-None-Match or If-Modified-Since.  The server then responds with the 304 status and the browser is left with no content to display.  This is nothing other than buggy behavior on behalf of the web application.  You can only respond with 304 Not Modified to a conditional query.

If you modify the application to allow caching of the resource (remove the Pragma header, change Cache-Control to public) and expose cache validator information (add Last-Modified and/or ETag headers) you can see that a conditional GET will be issued in some situations.  Loading the URL in a new tab or window is one such situation.  Following a link to the URL from a web page is another.  Hitting the Reload button or pressing Cmd-R is not one of those situations, as we use the explicit user action as a hint that we should look more aggressively for new content.

Summary: the web application needs to send appropriate headers to permit caching, cache validators so that the browser can issue conditional requests, and only respond with “304 Not Modified” in response to a conditional request if all of the conditions in the request are satisfied.
Comment 4 Mark Rowe (bdash) 2009-12-22 00:22:22 PST
I’m marking this bug as INVALID due to this being the result of incorrect behavior by the web application.  The most I think we could consider doing in this situation is logging an error to the inspector console about the incorrect server-side behavior.  If you think this would be useful I would encourage you to write up a separate enhancement request about that.
Comment 5 Juti Noppornpitak 2009-12-23 07:56:06 PST
So, from what you say here, Webkit only strictly follows the instructions from the response headers. Also, from GUI of Webkit (incl. Safari and Google Chrome), if I enter a URL and press "return/enter," what I understand is that Webkit will assume that I want a fresh new copy or an latest updated copy of the content at the URL and Webkit will assume that the server respond the request by giving the requested content with HTTP 200.

Is my assumption correct?
Comment 6 Andrey Anisimov 2014-05-02 22:39:07 PDT
The bug is still there, happens in iOS 7.1.1 . The best description of the issue and the possible reason I found here: http://tech.vg.no/2013/10/02/ios7-bug-shows-white-page-when-getting-304-not-modified-from-server/ . 
In short, under certain circumstances like cancelled loading or connection error an empty page can be cached and then displayed on each 304 response.