Skip to content

Commit

Permalink
Make all prerenders go via prefetching first (#359)
Browse files Browse the repository at this point in the history
This allows deduplicating a good amount of the No-Vary-Search handling that both needed to do, and eliminates the entire "prerender records" concept.

Fixes #320 by properly specifying Sec-Purpose for prerenders.
  • Loading branch information
domenic authored Feb 3, 2025
1 parent 24b2405 commit 3f24fad
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 75 deletions.
33 changes: 20 additions & 13 deletions prefetch.bs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ A <dfn export>prefetch record</dfn> is a [=struct=] with the following [=struct/
* <dfn export for="prefetch record">label</dfn>, a [=string=]

<div class="note">This is intended for use by a specification or [=implementation-defined=] feature to identify which prefetches it created. It might also associate other data with this struct.</div>
* <dfn export for="prefetch record">prerendering traversable</dfn>, a [=prerendering traversable=], "`to be created`", or null (null by default)
* <dfn export for="prefetch record">state</dfn>, which is "`ongoing`" (the default), "`completed`", or "`canceled`"
<div class="note">"`canceled`" indicates that the prefetch was aborted by the author or user, or terminated by the user agent.</div>
* <dfn export for="prefetch record">fetch controller</dfn>, a [=fetch controller=] (a new [=fetch controller=] by default)
Expand Down Expand Up @@ -533,10 +534,11 @@ Modify the [=snapshot source snapshot params=] algorithm to set the return value
1. If |prefetchRecord| was given, then:
1. Let |purpose| be a [=structured header/List=] containing the [=structured header/Token=] `prefetch`.
1. If |prefetchRecord|'s [=prefetch record/anonymization policy=] [=prefetch IP anonymization policy/requires anonymity=] for |request|, then:
1. Add a parameter whose key is <a for="Sec-Purpose prefetch" lt="anonymous-client-ip">"`anonymous-client-ip`"</a> and whose value is true to the `prefetch` token in |purpose|.
1. Add a parameter whose key is "<a for="Sec-Purpose prefetch">`anonymous-client-ip`</a>" and whose value is true to the `prefetch` token in |purpose|.
1. The user agent must use a [=connection=] which anonymizes the client IP address (e.g., using a proxy) when fetching |request|, or set |response| to a [=network error=] and [=iteration/break=].

<p class="issue">At the moment, how IP anonymization is achieved is handwaved. This will probably be done in an [=implementation-defined=] manner using some kind of proxy or relay. Ideally this would be plumbed down to [=obtain a connection=], and possibly even the mechanism could be further standardized.</p>
1. If |prefetchRecord|'s [=prefetch record/prerendering traversable=] is not null, then add a parameter whose key is "<a for="Sec-Purpose prefetch">`prerender`</a>" and whose value is true to the `prefetch` token in |purpose|.
1. [=header list/Set a structured field value=] given (<a http-header>`` `Sec-Purpose` ``</a>, |purpose|) in |request|'s [=request/header list=].

<div class="note">
Expand Down Expand Up @@ -662,13 +664,13 @@ This section contains patches to [[NAVIGATION-TIMING]].
The <dfn>list of sufficiently strict speculative navigation referrer policies</dfn> is a list containing the following: "", "`strict-origin-when-cross-origin`", "`strict-origin`", "`same-origin`", "`no-referrer`".

<div algorithm>
To <dfn export>prefetch</dfn> given a {{Document}} document and a [=prefetch record=] |prefetchRecord|, perform the following steps.
To <dfn export>prefetch</dfn> given a {{Document}} |document| and a [=prefetch record=] |prefetchRecord|, perform the following steps.

1. Let |sourceSnapshotParams| be the result of [=snapshotting source snapshot params=] given |document|.
1. Let |targetSnapshotParams| be the result of [=snapshotting target snapshot params=] given |document|'s [=node navigable=].
1. Set |prefetchRecord|'s [=prefetch record/source partition key=] to the result of [=determining the network partition key=] given |document|'s [=relevant settings object=].
1. [=Assert=]: |prefetchRecord|'s [=prefetch record/URL=]'s [=url/scheme=] is an [=HTTP(S) scheme=].
1. [=list/Append=] |prefetchRecord| to |document|'s [=Document/prefetch records=]
1. [=list/Append=] |prefetchRecord| to |document|'s [=Document/prefetch records=].
1. Set |prefetchRecord|'s [=prefetch record/start time=] to the [=current high resolution time=] for the [=relevant global object=] of |document|.
1. Set |prefetchRecord|'s [=prefetch record/sandboxing flag set=] to the result of [=determining the creation sandboxing flags=] for |document|'s [=Document/browsing context=] given |document|'s [=node navigable=]'s [=navigable/container=].
1. Let |referrerPolicy| be |prefetchRecord|'s [=prefetch record/referrer policy=] if |prefetchRecord|'s [=prefetch record/referrer policy=] is not the empty string, and |document|'s [=Document/policy container=]'s [=policy container/referrer policy=] otherwise.
Expand Down Expand Up @@ -768,19 +770,13 @@ The <dfn>list of sufficiently strict speculative navigation referrer policies</d

The <dfn http-header>`` `Sec-Purpose` ``</dfn> HTTP request header specifies that the request serves one or more purposes other than requesting the resource for immediate use by the user.

The header field is an [[RFC9651]] Structured Header whose value must be a [=structured header/List=]. Its ABNF is:
The header field is an [[RFC9651]] Structured Header whose value must be a [=structured header/List=].

```
Sec-Purpose = sf-list
```
It may contain an [=structured header/Item=] member which is the [=structured header/Token=] `prefetch`. If so, this indicates the request's purpose is to download a resource it is anticipated will be fetched shortly.

It may contain an [=structured header/Item=] member which is the [=structured header/Token=] "`prefetch`". If so, this indicates the request's purpose is to download a resource it is anticipated will be fetched shortly.
The following parameters are defined for the `prefetch` token:

<div class="issue">TODO: Are there normative implications of this that should be specified here?</div>

The following parameters are defined for the "`prefetch`" token:

* A parameter whose key is <dfn for="Sec-Purpose prefetch" lt="anonymous-client-ip">"`anonymous-client-ip`"</dfn>.
* A parameter whose key is "<dfn for="Sec-Purpose prefetch">`anonymous-client-ip`</dfn>".

If present with a value other than boolean false (`` `?0` `` in the field value), this parameter indicates that the prefetch request is being made using an anonymous client IP. Consequently, servers should not rely on it matching, or sharing a geographic location or network operator with, the client's IP address from which a non-prefetch request would have been made.

Expand All @@ -792,6 +788,17 @@ The following parameters are defined for the "`prefetch`" token:
This specification conforms to this advice; the [=prefetch=] algorithm does not emit non-boolean values.
</div>

* A parameter whose key is "<dfn for="Sec-Purpose prefetch">`prerender`</dfn>".

If present with a value other than boolean false (`` `?0` `` in the field value), this parameter indicates that the prefetch request is being made in anticipation of a prerender.

<div class="note">
A future specification might define assign more specific meaning to non-boolean values. For now, they are treated the same as true. Implementations are advised not to emit such values.

This specification conforms to this advice; the [=prefetch=] algorithm does not emit non-boolean values.
</div>


<h2 id="security-considerations">Security considerations</h2>

See <a href="speculation-rules.html#security-considerations">Security considerations (Speculation Rules)</a>.
Expand Down
Loading

0 comments on commit 3f24fad

Please sign in to comment.