From 99d395b79dd6496d04e1321586bcde5bb9f10cf0 Mon Sep 17 00:00:00 2001 From: "bjarne@runitsoft.com" Date: Mon, 24 Aug 2009 10:32:18 -0400 Subject: [PATCH] Bug 510359 - Cached "Vary: Cookie" responses are improperly revalidated/reused r=biesi --- netwerk/protocol/http/src/nsHttpChannel.cpp | 13 ++-- netwerk/test/unit/test_bug510359.js | 80 +++++++++++++++++++++ 2 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 netwerk/test/unit/test_bug510359.js diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index 87c4aadf6be5..a5b29d8d707b 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -2106,6 +2106,7 @@ nsHttpChannel::CheckCache() } PRBool doValidation = PR_FALSE; + PRBool canAddImsHeader = PR_TRUE; // Be optimistic: assume that we won't need to do validation mRequestHead.ClearHeader(nsHttp::If_Modified_Since); @@ -2146,6 +2147,7 @@ nsHttpChannel::CheckCache() else if (ResponseWouldVary()) { LOG(("Validating based on Vary headers returning TRUE\n")); + canAddImsHeader = PR_FALSE; doValidation = PR_TRUE; } @@ -2229,10 +2231,13 @@ nsHttpChannel::CheckCache() mRequestHead.Method() == nsHttp::Head)) { const char *val; // Add If-Modified-Since header if a Last-Modified was given - val = mCachedResponseHead->PeekHeader(nsHttp::Last_Modified); - if (val) - mRequestHead.SetHeader(nsHttp::If_Modified_Since, - nsDependentCString(val)); + // and we are allowed to do this (see bugs 510359 and 269303) + if (canAddImsHeader) { + val = mCachedResponseHead->PeekHeader(nsHttp::Last_Modified); + if (val) + mRequestHead.SetHeader(nsHttp::If_Modified_Since, + nsDependentCString(val)); + } // Add If-None-Match header if an ETag was given in the response val = mCachedResponseHead->PeekHeader(nsHttp::ETag); if (val) diff --git a/netwerk/test/unit/test_bug510359.js b/netwerk/test/unit/test_bug510359.js new file mode 100644 index 000000000000..5946c1f23dc1 --- /dev/null +++ b/netwerk/test/unit/test_bug510359.js @@ -0,0 +1,80 @@ +do_load_httpd_js(); + +var httpserver = new nsHttpServer(); +var index = 0; +var tests = [ + { url : "/bug510359", server : "0", expected : "0"}, + { url : "/bug510359", server : "1", expected : "1"}, +]; + +function getCacheService() { + return Components.classes["@mozilla.org/network/cache-service;1"] + .getService(Components.interfaces.nsICacheService); +} + +function setupChannel(suffix, value) { + var ios = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService); + var chan = ios.newChannel("http://localhost:4444" + suffix, "", null); + var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel); + httpChan.requestMethod = "GET"; + httpChan.setRequestHeader("x-request", value, false); + return httpChan; +} + +function triggerNextTest() { + var channel = setupChannel(tests[index].url, tests[index].server); + channel.asyncOpen(new ChannelListener(checkValueAndTrigger, null), null); +} + +function checkValueAndTrigger(request, data, ctx) { + do_check_eq(tests[index].expected, data); + + if (index < tests.length - 1) { + index++; + triggerNextTest(); + } else { + do_test_finished(); + httpserver.stop(); + } +} + +function run_test() { + httpserver.registerPathHandler("/bug510359", handler); + httpserver.start(4444); + + // clear cache + getCacheService().evictEntries( + Components.interfaces.nsICache.STORE_ANYWHERE); + triggerNextTest(); + + do_test_pending(); +} + +function handler(metadata, response) { + try { + var IMS = metadata.getHeader("If-Modified-Since"); + response.setStatusLine(metadata.httpVersion, 500, "Failed"); + var msg = "Client should not set If-Modified-Since header"; + response.bodyOutputStream.write(msg, msg.length); + } catch(ex) { + response.setStatusLine(metadata.httpVersion, 200, "Ok"); + response.setHeader("Content-Type", "text/plain", false); + response.setHeader("Last-Modified", getDateString(-1), false); + response.setHeader("Vary", "Cookie", false); + var body = metadata.getHeader("x-request"); + response.bodyOutputStream.write(body, body.length); + } +} + +function getDateString(yearDelta) { + var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', + 'Sep', 'Oct', 'Nov', 'Dec' ]; + var days = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]; + + var d = new Date(); + return days[d.getUTCDay()] + ", " + d.getUTCDate() + " " + + months[d.getUTCMonth()] + " " + (d.getUTCFullYear() + yearDelta) + + " " + d.getUTCHours() + ":" + d.getUTCMinutes() + ":" + + d.getUTCSeconds() + " UTC"; +}