Bug 56881 - mod_cache can send a 304 to unconditional req when handling a contradiction on revalidation
Summary: mod_cache can send a 304 to unconditional req when handling a contradiction o...
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_cache (show other bugs)
Version: 2.4.10
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-08-22 14:46 UTC by Eric Covener
Modified: 2015-01-23 10:15 UTC (History)
0 users



Attachments
loglevel trace8 (4.59 KB, text/plain)
2014-08-22 14:58 UTC, Eric Covener
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Eric Covener 2014-08-22 14:46:46 UTC
I am seeing that even though this snippet below unsets the conditional headers, something about r->status being 304 at the start of the internal redirect causes the 304 to be returned

I set r->status to 333 as a stupid test right after unsetting conditionals and could see the 333 being traced as a response code in the same path -- so the 304 is not due to the r->headers_in but some lingering r->status.


    if (reason && r->status == HTTP_NOT_MODIFIED && cache->stale_handle) {

        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02473)
                "cache: %s responded with an uncacheable 304, "
                "retrying the request. Reason: %s",
                r->unparsed_uri, reason);

        /* we've got a cache conditional miss! tell anyone who cares */
        cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_MISS,
                apr_psprintf(r->pool,
                        "conditional cache miss: 304 was uncacheable, entity removed: %s",
                        reason));

        /* remove the cached entity immediately, we might cache it again */
        ap_remove_output_filter(cache->remove_url_filter);
        cache_remove_url(cache, r);

        /* let someone else attempt to cache */
        cache_remove_lock(conf, cache, r, NULL);

        /* remove this filter from the chain */
        ap_remove_output_filter(f);

        /* retry without the conditionals */
        apr_table_unset(r->headers_in, "If-Match");
        apr_table_unset(r->headers_in, "If-Modified-Since");
        apr_table_unset(r->headers_in, "If-None-Match");
        apr_table_unset(r->headers_in, "If-Range");
        apr_table_unset(r->headers_in, "If-Unmodified-Since");

        ap_internal_redirect(r->unparsed_uri, r);

        return APR_SUCCESS;
Comment 1 Eric Covener 2014-08-22 14:49:41 UTC
FWIW: In my case the contradiction is intersting too.  

I am caching a recently created static file that gets a weak etag at startup, then when it expires, httpd generates the same etag but without the W/ prefix.
Comment 2 Eric Covener 2014-08-22 14:58:55 UTC
Created attachment 31937 [details]
loglevel trace8

debug + a little added trace of the client that gets a 304 to unconditional request.  Before the expiration, the static file got a weak etag, and now it does not have the weak prefix (not traced but clear from logs)
Comment 3 Eric Covener 2014-08-22 15:16:53 UTC
It looks like r->status = HTTP_OK before the internal redirect does the trick.

I confirmed the internal redirect could actually return different contents then the state cache thing, and even non-success after this, although I still can't see who short-circuits over r->status != HTTP_OK.
Comment 4 Yann Ylavic 2015-01-23 10:15:17 UTC
Fixed in 2.4.11 with r1627745.