mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1120715 - Part 5: Treat a default cache mode Request with a revalidation header as no-store; r=bkelly
This commit is contained in:
parent
440ae27065
commit
a014521971
@ -245,12 +245,6 @@ FetchDriver::HttpFetch()
|
||||
#endif
|
||||
chan->SetNotificationCallbacks(this);
|
||||
|
||||
// FIXME(nsm): Bug 1120715.
|
||||
// Step 3.4 "If request's cache mode is default and request's header list
|
||||
// contains a header named `If-Modified-Since`, `If-None-Match`,
|
||||
// `If-Unmodified-Since`, `If-Match`, or `If-Range`, set request's cache mode
|
||||
// to no-store."
|
||||
|
||||
// Step 3.5 begins "HTTP network or cache fetch".
|
||||
// HTTP network or cache fetch
|
||||
// ---------------------------
|
||||
@ -332,12 +326,11 @@ FetchDriver::HttpFetch()
|
||||
// dom/workers/ServiceWorkerManager.cpp
|
||||
internalChan->SetCorsMode(static_cast<uint32_t>(mRequest->Mode()));
|
||||
internalChan->SetRedirectMode(static_cast<uint32_t>(mRequest->GetRedirectMode()));
|
||||
mRequest->MaybeSkipCacheIfPerformingRevalidation();
|
||||
internalChan->SetFetchCacheMode(static_cast<uint32_t>(mRequest->GetCacheMode()));
|
||||
}
|
||||
|
||||
// Step 5. Proxy authentication will be handled by Necko.
|
||||
// FIXME(nsm): Bug 1120715.
|
||||
// Step 7-10. "If request's cache mode is neither no-store nor reload..."
|
||||
|
||||
// Continue setting up 'HTTPRequest'. Content-Type and body data.
|
||||
nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(chan);
|
||||
|
@ -174,6 +174,17 @@ InternalHeaders::IsSimpleHeader(const nsACString& aName, const nsACString& aValu
|
||||
nsContentUtils::IsAllowedNonCorsContentType(aValue));
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
InternalHeaders::IsRevalidationHeader(const nsACString& aName)
|
||||
{
|
||||
return aName.EqualsLiteral("if-modified-since") ||
|
||||
aName.EqualsLiteral("if-none-match") ||
|
||||
aName.EqualsLiteral("if-unmodified-since") ||
|
||||
aName.EqualsLiteral("if-match") ||
|
||||
aName.EqualsLiteral("if-range");
|
||||
}
|
||||
|
||||
//static
|
||||
bool
|
||||
InternalHeaders::IsInvalidName(const nsACString& aName, ErrorResult& aRv)
|
||||
@ -283,6 +294,18 @@ InternalHeaders::HasOnlySimpleHeaders() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
InternalHeaders::HasRevalidationHeaders() const
|
||||
{
|
||||
for (uint32_t i = 0; i < mList.Length(); ++i) {
|
||||
if (IsRevalidationHeader(mList[i].mName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<InternalHeaders>
|
||||
InternalHeaders::BasicHeaders(InternalHeaders* aHeaders)
|
||||
|
@ -99,6 +99,8 @@ public:
|
||||
|
||||
bool HasOnlySimpleHeaders() const;
|
||||
|
||||
bool HasRevalidationHeaders() const;
|
||||
|
||||
static already_AddRefed<InternalHeaders>
|
||||
BasicHeaders(InternalHeaders* aHeaders);
|
||||
|
||||
@ -142,6 +144,8 @@ private:
|
||||
|
||||
static bool IsSimpleHeader(const nsACString& aName,
|
||||
const nsACString& aValue);
|
||||
|
||||
static bool IsRevalidationHeader(const nsACString& aName);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -363,5 +363,14 @@ InternalRequest::MapChannelToRequestCredentials(nsIChannel* aChannel)
|
||||
return RequestCredentials::Same_origin;
|
||||
}
|
||||
|
||||
void
|
||||
InternalRequest::MaybeSkipCacheIfPerformingRevalidation()
|
||||
{
|
||||
if (mCacheMode == RequestCache::Default &&
|
||||
mHeaders->HasRevalidationHeaders()) {
|
||||
mCacheMode = RequestCache::No_store;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -425,6 +425,9 @@ public:
|
||||
bool
|
||||
IsClientRequest() const;
|
||||
|
||||
void
|
||||
MaybeSkipCacheIfPerformingRevalidation();
|
||||
|
||||
static RequestMode
|
||||
MapChannelToRequestMode(nsIChannel* aChannel);
|
||||
|
||||
|
@ -128,6 +128,166 @@
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-Modified-Since": new Date().toGMTString()}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-Modified-Since": new Date().toGMTString()}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-Modified-Since": new Date().toGMTString()}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-Modified-Since": new Date().toGMTString()}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-None-Match": '"foo"'}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-None-Match": '"foo"'}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-None-Match": '"foo"'}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-None-Match": '"foo"'}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-Unmodified-Since": new Date().toGMTString()}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-Unmodified-Since": new Date().toGMTString()}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-Unmodified-Since": new Date().toGMTString()}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-Unmodified-Since": new Date().toGMTString()}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Match header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-Match": '"foo"'}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Match header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-Match": '"foo"'}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Match header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-Match": '"foo"'}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Match header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-Match": '"foo"'}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Range header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-Range": '"foo"'}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Range header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{}, {"If-Range": '"foo"'}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [false, true],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Range header is treated similarly to "no-store"',
|
||||
state: "stale",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-Range": '"foo"'}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'RequestCache "default" mode with an If-Range header is treated similarly to "no-store"',
|
||||
state: "fresh",
|
||||
request_cache: ["default", "default"],
|
||||
request_headers: [{"If-Range": '"foo"'}, {}],
|
||||
expected_validation_headers: [false, false],
|
||||
expected_no_cache_headers: [true, false],
|
||||
},
|
||||
{
|
||||
name: 'Responses with the "Cache-Control: no-store" header are not stored in the cache',
|
||||
state: "stale",
|
||||
@ -201,10 +361,16 @@
|
||||
if ("cache_control" in info) {
|
||||
cache_control = "&cache_control=" + info.cache_control;
|
||||
}
|
||||
var ignore_request_headers = "";
|
||||
if ("request_headers" in info) {
|
||||
// Ignore the request headers that we send since they may be synthesized by the test.
|
||||
ignore_request_headers = "&ignore";
|
||||
}
|
||||
return "resources/cache.py?token=" + uuid +
|
||||
"&content=" + content +
|
||||
"&" + id + "=" + value +
|
||||
"&expires=" + dates[info.state] + vary + cache_control;
|
||||
"&expires=" + dates[info.state] +
|
||||
vary + cache_control + ignore_request_headers;
|
||||
}
|
||||
function server_state(uuid) {
|
||||
return fetch("resources/cache.py?querystate&token=" + uuid)
|
||||
@ -214,8 +380,12 @@
|
||||
return JSON.parse(text);
|
||||
});
|
||||
}
|
||||
function populate_cache(url, content, cache) {
|
||||
return fetch(url, {cache: cache})
|
||||
function populate_cache(url, content, info) {
|
||||
var init = {cache: info.request_cache[0]};
|
||||
if ("request_headers" in info) {
|
||||
init.headers = info.request_headers[0];
|
||||
}
|
||||
return fetch(url, init)
|
||||
.then(function(response) {
|
||||
assert_equals(response.status, 200);
|
||||
assert_equals(response.statusText, "OK");
|
||||
@ -231,11 +401,15 @@
|
||||
var content = Math.random().toString();
|
||||
var url = make_url(uuid, type, identifier, content, info);
|
||||
var fetch_functions = [function() {
|
||||
return populate_cache(url, content, info.request_cache[0]);
|
||||
return populate_cache(url, content, info);
|
||||
}];
|
||||
for (var i = 1; i < info.request_cache.length; ++i) {
|
||||
fetch_functions.push(function(idx) {
|
||||
return fetch(url, {cache: info.request_cache[idx]})
|
||||
var init = {cache: info.request_cache[idx]};
|
||||
if ("request_headers" in info) {
|
||||
init.headers = info.request_headers[idx];
|
||||
}
|
||||
return fetch(url, init)
|
||||
.then(function(response) {
|
||||
assert_equals(response.status, 200);
|
||||
assert_equals(response.statusText, "OK");
|
||||
|
@ -14,19 +14,21 @@ def main(request, response):
|
||||
ims = request.headers.get("If-Modified-Since", None)
|
||||
pragma = request.headers.get("Pragma", None)
|
||||
cache_control = request.headers.get("Cache-Control", None)
|
||||
ignore = "ignore" in request.GET
|
||||
|
||||
server_state = request.server.stash.take(token)
|
||||
if not server_state:
|
||||
server_state = []
|
||||
state = dict()
|
||||
if inm:
|
||||
state["If-None-Match"] = inm
|
||||
if ims:
|
||||
state["If-Modified-Since"] = ims
|
||||
if pragma:
|
||||
state["Pragma"] = pragma
|
||||
if cache_control:
|
||||
state["Cache-Control"] = cache_control
|
||||
if not ignore:
|
||||
if inm:
|
||||
state["If-None-Match"] = inm
|
||||
if ims:
|
||||
state["If-Modified-Since"] = ims
|
||||
if pragma:
|
||||
state["Pragma"] = pragma
|
||||
if cache_control:
|
||||
state["Cache-Control"] = cache_control
|
||||
server_state.append(state)
|
||||
request.server.stash.put(token, server_state)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user