Skip to content

Commit

Permalink
Use the frame Accept header for prefetches.
Browse files Browse the repository at this point in the history
Special-casing prefetches makes it so that `Vary: Accept`
makes the browser erroneously reject the prefetched response.

This was previously unspecified,
See whatwg/fetch#1485

Bug: 626081
Change-Id: I2c99f4f1abd2556fdf456d877588b346a22fd677
  • Loading branch information
noamr authored and chromium-wpt-export-bot committed Dec 13, 2022
1 parent c29a034 commit 6dfeba4
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 0 deletions.
26 changes: 26 additions & 0 deletions preload/prefetch-accept.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<title>Ensures that prefetch works with documents</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="resources/prefetch-helper.js"></script>
<body>
<script>

promise_test(async t => {
const {href, uid} = await prefetch({
file: "prefetch-exec.html",
type: "text/html",
origin: document.origin});
const popup = window.open(href + "&cache_bust=" + token());
const remoteContext = new RemoteContext(uid);
t.add_cleanup(() => popup.close());
await remoteContext.execute_script(() => "OK");
const results = await get_prefetch_info(href);
assert_equals(results.length, 2);
assert_equals(results[0].headers.accept, results[1].headers.accept);
}, "Document prefetch should send the exact Accept header as navigation")

</script>
</body>
9 changes: 9 additions & 0 deletions preload/resources/prefetch-exec.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Message BC</title>
<script src="/common/dispatcher/dispatcher.js"></script>
<script>
"use strict";
const params = new URLSearchParams(location.search);
window.executor = new Executor(params.get("key"));
</script>
23 changes: 23 additions & 0 deletions preload/resources/prefetch-helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
async function get_prefetch_info(href) {
const response = await fetch(`${href}&mode=info`, {mode: "cors"});
return await response.json();
}

async function prefetch(p = {}, t) {
const link = document.createElement("link");
link.rel = "prefetch";
link.as = p.as;
if (p.crossOrigin)
link.setAttribute("crossorigin", p.crossOrigin);
const uid = token();
const params = new URLSearchParams();
params.set("key", uid);
for (const key in p)
params.set(key, p[key]);
const origin = p.origin || '';
link.href = `${origin}/preload/resources/prefetch-info.py?${params.toString()}`;
document.head.appendChild(link);
while (!(await get_prefetch_info(link.href)).length) { }
return {href: link.href, uid};
}

37 changes: 37 additions & 0 deletions preload/resources/prefetch-info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os
from wptserve.utils import isomorphic_encode
from json import dumps, loads

def main(request, response):
key = request.GET.first(b"key").decode("utf8")
mode = request.GET.first(b"mode", "content")
status = int(request.GET.first(b"status", b"200"))
stash = request.server.stash
cors = request.GET.first(b"cors", "true")
if cors == "true" or mode == b"info":
response.headers.set(b"Access-Control-Allow-Origin", b"*")

response.status = status
with stash.lock:
requests = loads(stash.take(key) or '[]')
if mode == b"info":
response.headers.set(b"Content-Type", "application/json")
json_reqs = dumps(requests)
response.content = json_reqs
stash.put(key, json_reqs)
return
else:
headers = {}
for header in request.headers:
headers[header.decode("utf8")] = request.headers[header].decode("utf8")
path = request.url
requests.append({"headers": headers, "url": request.url})
stash.put(key, dumps(requests))

response.headers.set(b"Content-Type", request.GET.first(b"type", "text/plain"))
response.headers.set(b"Cache-Control", request.GET.first(b"cache-control", b"max-age: 604800"))
if b"file" in request.GET:
path = os.path.join(os.path.dirname(isomorphic_encode(__file__)), request.GET.first(b"file"));
response.content = open(path, mode=u'rb').read()
else:
return request.GET.first(b"content", "123")

0 comments on commit 6dfeba4

Please sign in to comment.