@@ -194,8 +194,76 @@ lt="authentication entry">authentication entries</a> (for HTTP authentication).
194
194
195
195
<dt> <dfn for="fetch params">task destination</dfn> (default null)
196
196
<dd> Null, a <a for=/>global object</a> , or a <a for=/>parallel queue</a> .
197
+ <dt> <dfn for="fetch params">timing info</dfn>
198
+ <dd> A <a for=/>fetch timing info</a> .
199
+ <dt> <dfn for="fetch params">redirect timing info list</dfn> (default an empty list)
200
+ <dd> A list of <a for=/>redirect timing info</a>
197
201
</dl>
198
202
203
+ <p> A <dfn export>fetch timing info</dfn> is a <a for=/>struct</a> used to maintain timing
204
+ information later required by the resource timing and navigation timing specs. It has the following
205
+ <a for=struct>items</a> :
206
+ <dl>
207
+ <dt> <dfn export for="fetch timing info">fetch start time</dfn> (default zero)
208
+ <dt> <dfn export for="fetch timing info">worker start time</dfn> (default zero)
209
+ <dt> <dfn export for="fetch timing info">request start time</dfn> (default zero)
210
+ <dt> <dfn export for="fetch timing info">response start time</dfn> (default zero)
211
+ <dt> <dfn export for="fetch timing info">response end time</dfn> (default zero)
212
+ <dd> A <a for=/>DOMHighResTimeStamp</a> .
213
+ <dt> <dfn export for="fetch timing info">encoded body size</dfn> (default zero)
214
+ <dt> <dfn export for="fetch timing info">decoded body size</dfn> (default zero)
215
+ <dd> A number.
216
+ <dt> <dfn export for="fetch timing info">connection timing info</dfn> (default null)
217
+ <dd> Null or a <a for=/>connection timing info</a> .
218
+ </dl>
219
+
220
+ <p> A <dfn export>redirect timing info</dfn> is a <a for=/>struct</a> used to maintain timing
221
+ information about a redirect.
222
+ <a for=struct>items</a> :
223
+ <dl>
224
+ <dt> <dfn export for="redirect timing info">redirect location URL</dfn>
225
+ <dd> A URL.
226
+ <dt> <dfn export for="redirect timing info">timing info</dfn>
227
+ <dd> A <a for=/>fetch timing info</a> .
228
+ </dl>
229
+
230
+ <p> A <dfn export>connection timing info</dfn> is a <a for=/>struct</a> used to maintain timing
231
+ information pertaining to the process of obtaining a connection. It has the following
232
+ <a for=struct>items</a> :
233
+ <dl>
234
+ <dt> <dfn export for="connection timing info">domain lookup start time</dfn> (default zero)
235
+ <dt> <dfn export for="connection timing info">domain lookup end time</dfn> (default zero)
236
+ <dt> <dfn export for="connection timing info">connection start time</dfn> (default zero)
237
+ <dt> <dfn export for="connection timing info">connection end time</dfn> (default zero)
238
+ <dt> <dfn export for="connection timing info">secure connection start time</dfn> (default zero)
239
+ <dd> A <a for=/>DOMHighResTimeStamp</a>
240
+ <dt> <dfn export for="connection timing info">alpn negotiated protocol</dfn> (default empty string)
241
+ <dd> A string.
242
+ </dl>
243
+
244
+ <p> <dfn data-cite="hr-time-2#dom-domhighrestimestamp">DOMHighResTimeStamp</dfn> and
245
+ <dfn data-cite="hr-time-2#dfn-unsafe-shared-current-time">unsafe shared current time</dfn> </code>
246
+ are defined in [[HR-TIME]] .
247
+
248
+ <p class=note> Note that timestamps in this spec are usually unsafe, and are meant to be coarsened
249
+ and normalized to a <a for=/>global object</a> prior to being exposed.
250
+
251
+ <p> To <dfn>clamp connection timing to fetch timing</dfn> , given <a for=/>connection timing info</a>
252
+ <var> timingInfo</var> and <a for=/>DOMHighResTimeStamp</a> <var> defaultStartTime</var> , run these
253
+ steps:
254
+ <ol>
255
+ <li><p> If <var> timingInfo</var> 's <a for="connection timing info">connection start time</a> is
256
+ greater than <var> defaultStartTime</var> , then return <var> timingInfo</var> .
257
+
258
+ <li><p> Otherwise, return a new <a for=/>connection timing info</a> , with
259
+ <a for="connection timing info">domain lookup start time</a> set to <var> defaultStartTime</var> ,
260
+ <a for="connection timing info">domain lookup end time</a> set to <var> defaultStartTime</var> ,
261
+ <a for="connection timing info">connection start time</a> set to <var> defaultStartTime</var> ,
262
+ <a for="connection timing info">connection end time</a> set to <var> defaultStartTime</var> ,
263
+ <a for="connection timing info">secure connection start time</a> set to
264
+ <var> defaultStartTime</var> , and <a for="connection timing info">alpn negotiated protocol</a>
265
+ set to <var> timingInfo</var> 's <a for="connection timing info">alpn negotiated protocol</a> .
266
+
199
267
<p> To <dfn>queue a fetch task</dfn> , given an algorithm <var> algorithm</var> , a
200
268
<a for=/>global object</a> or a <a for=/>parallel queue</a> <var> taskDestination</var> , run these
201
269
steps:
@@ -1926,6 +1994,14 @@ description of the attack.
1926
1994
<dfn for=response id=concept-response-timing-allow-passed>timing allow passed flag</dfn> , which is
1927
1995
initially unset.
1928
1996
1997
+ <p> A <a for=/>response</a> can have an associated
1998
+ <dfn export for=response id=concept-response-timing-info>timing info</dfn> , which is Null or a
1999
+ <a for=/>fetch timing info</a> , initially set to null.
2000
+
2001
+ <p> A <a for=/>response</a> has an associated
2002
+ <dfn export for=response id=concept-response-redirect-timing-info-list>redirect timing info list</dfn> ,
2003
+ which is initially set to an empty <a for=/>list</a> .
2004
+
1929
2005
<p class=note> This is used so that the caller to a fetch can determine if sensitive timing data is
1930
2006
allowed on the resource fetched by looking at the flag of the response returned. Because the flag on
1931
2007
the response of a redirect has to be set if it was set for previous responses in the redirect chain,
@@ -2148,6 +2224,9 @@ unset or <a for=request>keepalive</a> is false, <a lt=terminated for=fetch>termi
2148
2224
identified by a <b> key</b> (a <a>network partition key</a> ), an <b> origin</b> (an
2149
2225
<a for=/>origin</a> ), and <b> credentials</b> (a boolean).
2150
2226
2227
+ <p> Each <a>connection</a> has an associated <a for=/>connection timing info</a>
2228
+ <dfn for=connection>timingInfo</dfn> .
2229
+
2151
2230
<p> To <dfn export id=concept-connection-obtain>obtain a connection</dfn> , given a <var> key</var> ,
2152
2231
<var> origin</var> , <var> credentials</var> , an optional boolean <var> forceNew</var> (default false),
2153
2232
an optional boolean <dfn export for="obtain a connection"><var>http3Only</var></dfn> (default
@@ -2179,8 +2258,9 @@ false), and an optional boolean <dfn export for="obtain a connection"><var>dedic
2179
2258
<ol>
2180
2259
<li>
2181
2260
<p> Set <var> connection</var> to the result of establishing an HTTP connection to
2182
- <var> origin</var> . [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]]
2183
- [[!TLS]]
2261
+ <var> origin</var> , following the requirements for
2262
+ <a>recording <var>connection</var> timing info</a> .
2263
+ [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]] [[!TLS]]
2184
2264
2185
2265
<p> If <var> http3Only</var> is true, then establish an HTTP/3 connection. [[!HTTP3]]
2186
2266
@@ -2219,6 +2299,88 @@ clearly stipulates that <a>connections</a> are keyed on
2219
2299
<!-- See https://github.com/whatwg/fetch/issues/114#issuecomment-143500095 for when we make
2220
2300
WebSocket saner -->
2221
2301
2302
+ <p> The requirements for <dfn>recording connection timing info</dfn> given a <var> connection</var>
2303
+ and its <a for=/>connection timing info</a> <var> timingInfo</var> , are as follows:
2304
+ <ul>
2305
+ <li><p><var> timingInfo</var> 's <a for="connection timing info">domain lookup start time</a>
2306
+ SHOULD be the <a for=/>unsafe shared current time</a> immediately before starting the domain
2307
+ lookup, or beginning retrieval of the information from cache.
2308
+
2309
+ <li><p><var> timingInfo</var> 's <a for="connection timing info">domain lookup end time</a> SHOULD
2310
+ be the <a for=/>unsafe shared current time</a> immediately after finishing the domain lookup, or
2311
+ retrieving the information from cache.
2312
+
2313
+ <li><p><var> timingInfo</var> 's <a for="connection timing info">connection start time</a> SHOULD
2314
+ be the <a for=/>unsafe shared current time</a> immediately before establishing the connection to
2315
+ the server or proxy.
2316
+
2317
+ <li><p><var> timingInfo</var> 's <a for="connection timing info">connection end time</a> SHOULD be
2318
+ the <a for=/>unsafe shared current time</a> immediately after establishing the connection to the
2319
+ server or proxy, as follows:
2320
+ <ul>
2321
+ <li><p> The returned time MUST include the time interval to establish the transport
2322
+ connection, as well as other time intervals such as SOCKS authentication. It
2323
+ MUST include the time interval to complete enough of the TLS handshake to
2324
+ request the resource.
2325
+
2326
+ <li><p> If the user agent used TLS False Start [[RFC7918]] for this connection,
2327
+ this interval MUST NOT include the time needed to receive the server's
2328
+ Finished message.
2329
+
2330
+ <li><p> If the user agent sends the request with early data [[RFC8470]] without
2331
+ waiting for the full handshare to complete, this interval MUST NOT include
2332
+ the time needed to receive the server's ServerHello message.
2333
+
2334
+ <li><p> If the user agent waits for full handshake completion to send the
2335
+ request, this interval includes the full TLS handshake even if other
2336
+ requests were sent using early data on <var> connection</var> .
2337
+ </ul>
2338
+
2339
+ <p class=note> Example: Suppose the user agent establishes an HTTP/2 connection
2340
+ over TLS 1.3 to send a GET request and a POST request. It sends the ClientHello
2341
+ at time <code> t1</code> and then sends the GET request with early data. The
2342
+ POST request is not safe [[HTTP-SEMANTICS]] (section 4.2.1), so the user agent waits
2343
+ to complete the handshake at time <code> t2</code> before sending it. Although
2344
+ both requests used the same connection, the GET request reports a connectEnd
2345
+ value of <code> t1</code> , while the POST request reports a connectEnd value for
2346
+ <code> t2</code> .
2347
+
2348
+ <li><p> If a secure transport is used, set <var> timingInfo</var> 's
2349
+ <a for="connection timing info">secure connection start time</a> to the result of calling
2350
+ <a for=/>unsafe shared current time</a> immmediately before starting the handshake process to
2351
+ secure <var> connection</var> . [[!TLS]]
2352
+
2353
+ <li><p> Set <var> timingInfo</var> 's <a for="connection timing info">alpn negotiated protocol</a>
2354
+ to the <var> connection</var> 's ALPN Protocol ID as specified in [[RFC7301]] , with the
2355
+ following caveats:
2356
+ <ul>
2357
+ <li><p> When a proxy is configured, if a tunnel connection is established then this attribute
2358
+ MUST return the ALPN Protocol ID of the tunneled protocol, otherwise it MUST return the ALPN
2359
+ Protocol ID of the first hop to the proxy.
2360
+
2361
+ <li><p> Octets in the ALPN protocol MUST NOT be percent-encoded if they are valid token
2362
+ characters except "%", and when using percent-encoding, uppercase hex digits MUST be used.
2363
+
2364
+ <li><p> Formally registered ALPN protocol IDs are documented by <a href=
2365
+ "https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids">
2366
+ IANA</a> .
2367
+
2368
+ <li><p> In case the user agent is using an experimental, non-registered protocol, the user
2369
+ agent MUST use the ALPN negotiated value if any. If ALPN was not used for protocol
2370
+ negotiations, the user agent MAY use another descriptive string.
2371
+
2372
+ <p class="note"> The "h3" ALPN ID is defined for the final version
2373
+ of the HTTP/3 protocol in the
2374
+ <a href="https://tools.ietf.org/html/draft-ietf-quic-http-17#section-10.1">HTTP/3
2375
+ Internet Draft</a> .
2376
+
2377
+ <p class="note"> Note that <a for="connection timing info">alpn negotiated protocol</a> is
2378
+ intended to identify the network protocol in use for the fetch regardless of how it was
2379
+ actually negotiated; that is, even if ALPN is not used to negotiate the network protocol,
2380
+ this attribute still uses the ALPN Protocol IDs to indicate the protocol in use.
2381
+ </ul>
2382
+ </ul>
2383
+ </ol>
2222
2384
2223
2385
<h3 id=network-partition-keys>Network partition keys</h3>
2224
2386
@@ -3362,6 +3524,7 @@ the request.
3362
3524
3363
3525
<li><p> Let <var> fetchParams</var> be a new <a for=/>fetch params</a> whose
3364
3526
<a for="fetch params">request</a> is <var> request</var> ,
3527
+ <a for="fetch params">timing info</a> is a new <a for=/>fetch timing info</a> ,
3365
3528
<a for="fetch params">process request body</a> is <var> processRequestBody</var> ,
3366
3529
<a for="fetch params">process request end-of-body</a> is <var> processRequestEndOfBody</var> ,
3367
3530
<a for="fetch params">process response</a> is <var> processResponse</var> ,
@@ -3450,6 +3613,10 @@ steps:
3450
3613
3451
3614
<li><p> Let <var> response</var> be null.
3452
3615
3616
+ <li><p> Set <var> fetchParams</var> 's <a for="fetch params">timing info</a> be a new
3617
+ <a for=/>fetch timing info</a> with its <a for="fetch timing info">fetch start time</a> set to the
3618
+ <a for=/>unsafe shared current time</a> .
3619
+
3453
3620
<li><p> If <var> request</var> 's <a>local-URLs-only flag</a> is set and <var>request</var>' s
3454
3621
<a for=request>current URL</a> is not <a lt="is local">local</a> , then set <var> response</var> to a
3455
3622
<a>network error</a> .
@@ -3746,6 +3913,8 @@ steps:
3746
3913
<a for=/>response</a> <var> response</var> , run these steps:
3747
3914
3748
3915
<ol>
3916
+ <li><p> <a for=/>Finalize timing info</a> with <var> fetchParams</var> and <var> response</var> .
3917
+
3749
3918
<li><p> If <var> fetchParams</var> 's <a for="fetch params">process response</a> is non-null, then
3750
3919
<a>queue a fetch task</a> to run <var> fetchParams</var> 's
3751
3920
<a for="fetch params">process response</a> given <var> response</var> , with <var> fetchParams</var> 's
@@ -3779,6 +3948,32 @@ steps:
3779
3948
<!-- This is really bad and needs to be handled differently at some point. -->
3780
3949
</ol>
3781
3950
3951
+ <p> To <dfn>finalize timing info</dfn> , given <a for=/>fetch params</a> <var> fetchParams</var> and
3952
+ <a for=/>response</a> <var> response</var> , perform the following steps:
3953
+ <ol>
3954
+ <li><p> Let <var> timingInfo</var> be <var> fetchParams</var> 's
3955
+ <a for="fetch params">timing info</a> .
3956
+
3957
+ <li><p> Let <var> startTime</var> be <var> timingInfo</var> 's
3958
+ <a for="fetch timing info">fetch start time</a> .
3959
+
3960
+ <li><p> Let <var> redirectTimings</var> be <var> fetchParams</var> 's
3961
+ <a for="fetch params">redirect timing info list</a> .
3962
+
3963
+ <li><p> If <var> redirectTimings</var> is not empty, then set <var> startTime</var> to
3964
+ <a for="fetch params">redirect timing info list</a> first item's
3965
+ <a for="redirect timing info">timing info</a> 's <A for="fetch timing info">fetch start time</a> .
3966
+
3967
+ <li><p> If <var> response</var> 's <a for=response>timing allow passed flag</a> is set, then set
3968
+ <var> response</var> 's <a for=response>timing info</a> to <var>fetchParams</var>' s
3969
+ <a for="fetch params">timing info</a> to <var> timingInfo</var> and <var> response</var> 's
3970
+ <a for=response>redirect timing info list</a> to <var> redirectTimings</var> .
3971
+
3972
+ <li><p> Otherwise, set <var> response</var> 's <a for=response>timing info</a> to a new
3973
+ <a for=/>fetch timing info</a> , with its <a for="fetch timing info">fetch start time</a>
3974
+ set to <var> startTime</var> .
3975
+ </ol>
3976
+
3782
3977
3783
3978
<h3 id=scheme-fetch oldids=basic-fetch>Scheme fetch</h3>
3784
3979
@@ -3902,20 +4097,28 @@ these steps:
3902
4097
3903
4098
<li><p> Let <var> actualResponse</var> be null.
3904
4099
4100
+ <li><p> Let <var> timingInfo</var> be <var> fetchParams</var> 's <a for="fetch params">timing info</a>
4101
+
3905
4102
<li>
3906
4103
<p> If <var> request</var> 's <a>service-workers mode</a> is "<code> all</code> ", then:
3907
4104
3908
4105
<ol>
3909
4106
<li><p> Let <var> requestForServiceWorker</var> be a <a for=request>clone</a> of
3910
4107
<var> request</var> .
3911
4108
4109
+ <li><p> Set <var> fetchParams</var> 's <a for="fetch params">timing info</a>' s
4110
+ <a for="fetch timing info">worker start time</a> to the <a for=/>unsafe shared current time</a> .
4111
+
3912
4112
<li><p> Set <var> response</var> to the result of invoking <a for=/>handle fetch</a> for
3913
4113
<var> requestForServiceWorker</var> . [[!HTML]] [[!SW]]
3914
4114
3915
4115
<li>
3916
4116
<p> If <var> response</var> is not null, then:
3917
4117
3918
4118
<ol>
4119
+ <li><p> Set <var> fetchParams</var> 's <a for="fetch params">timing info</a>' s
4120
+ <a for="fetch timing info">response start time</a> to the <a for=/>unsafe shared current time</a> .
4121
+
3919
4122
<li> If <var> request</var> 's <a for=request>body</a> is non-null, then
3920
4123
<a for=ReadableStream>cancel</a> <var> request</var> 's <a for=request>body</a> with undefined.
3921
4124
@@ -3946,6 +4149,9 @@ these steps:
3946
4149
</ol>
3947
4150
</ol>
3948
4151
4152
+ <p> Otheriwse, set <var> fetchParams</var> 's <a for="fetch params">timing info</a>' s
4153
+ <a for="fetch timing info">worker start time</a> to the zero.
4154
+
3949
4155
<li>
3950
4156
<p> If <var> response</var> is null, then:
3951
4157
@@ -4133,6 +4339,14 @@ run these steps:
4133
4339
<p class="note no-backref"><var> request</var> 's <a for=request>body</a>' s <a for=body>source</a> 's
4134
4340
nullity has already been checked.
4135
4341
4342
+ <li><p> Let <var> redirectInfo</var> be a new <a for=/>redirect timing info</a> with its
4343
+ <a for="redirect timing info">redirect location URL</a> set to <var> locationURL</var> and its
4344
+ <a for="redirect timing info">timing info</a> set to <var> fetchParams</var> 's
4345
+ <a for="fetch params">timing info</a> .
4346
+
4347
+ <li><p> Append <var> redirectInfo</var> to <var> fetchParams</var> 's
4348
+ <a for="fetch params">redirect timing info list</a> .
4349
+
4136
4350
<li><p> <a for=list>Append</a> <var> locationURL</var> to <var> request</var> 's
4137
4351
<a for=request>URL list</a> .
4138
4352
@@ -4720,6 +4934,8 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
4720
4934
4721
4935
<li><p> Let <var> response</var> be null.
4722
4936
4937
+ <li><p> Let <var> timingInfo</var> be <var> fetchParams</var> 's <a for="fetch params">timing info</a> .
4938
+
4723
4939
<li><p> Let <var> httpCache</var> be the result of <a>determining the HTTP cache partition</a> , given
4724
4940
<var> httpRequest</var> .
4725
4941
@@ -4745,6 +4961,11 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
4745
4961
<var> includeCredentials</var> , and <var> forceNewConnection</var> .
4746
4962
</dl>
4747
4963
4964
+ <li> Set <var> timingInfo</var> 's <a for="fetch timing info">connection timing info</a> to the
4965
+ result of calling <a>clamp connection timing to fetch timing</a> with <var> connection</var> 's
4966
+ <a for=connection>timingInfo</a> and <var> timingInfo</var> 's
4967
+ <a for="fetch timing info">fetch start time</a> .
4968
+
4748
4969
<li>
4749
4970
<p> Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a> :
4750
4971
@@ -4758,13 +4979,21 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
4758
4979
`<code> Transfer-Encoding</code> `/`<code> chunked</code> ` to <var> request</var> 's
4759
4980
<a for=request>header list</a> .
4760
4981
4982
+ <li> Set <var> timingInfo</var> 's <a for="fetch timing info">request start time</a> to
4983
+ <a for=/>unsafe shared current time</a> .
4984
+
4761
4985
<li>
4762
4986
<p> Set <var> response</var> to the result of making an HTTP request over <var> connection</var>
4763
4987
using <var> request</var> with the following caveats:
4764
4988
4765
4989
<ul>
4766
4990
<li><p> Follow the relevant requirements from HTTP. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]]
4767
4991
4992
+ <li><p> Set <var> timingInfo</var> 's <a for="fetch timing info">response start time</a> to
4993
+ the <a for=/>unsafe shared current time</a> immediately after the user agent's HTTP parser
4994
+ receives the first byte of the response (e.g. frame header bytes for HTTP/2, or response
4995
+ status line for HTTP/1.x).
4996
+
4768
4997
<li><p> Wait until all the <a for=/>headers</a> are transmitted.
4769
4998
4770
4999
<li>
@@ -4943,13 +5172,19 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
4943
5172
<li><p> Let <var> codings</var> be the result of <a>extracting header list values</a> given
4944
5173
`<code> Content-Encoding</code> ` and <var> response</var> 's <a for=response>header list</a> .
4945
5174
5175
+ <li><p> Increase <var> timingInfo</var> 's <a for="fetch timing info">encoded body size</a>
5176
+ by <var> bytes</var> 's <a for="byte sequence">length</a> .
5177
+
4946
5178
<li>
4947
5179
<p> Set <var> bytes</var> to the result of <a lt="handle content codings">handling content
4948
5180
codings</a> given <var> codings</var> and <var> bytes</var> .
4949
5181
4950
5182
<p class="note no-backref"> This makes the `<code> Content-Length</code> ` <a for=/>header</a>
4951
5183
unreliable to the extent that it was reliable to begin with.
4952
5184
5185
+ <li><p> Increase <var> timingInfo</var> 's <a for="fetch timing info">decoded body size</a> by
5186
+ <var> bytes</var> 's <a for="byte sequence">length</a> .
5187
+
4953
5188
<li><p> If <var> bytes</var> is failure, then <a lt=terminated for=fetch>terminate</a> the
4954
5189
ongoing fetch.
4955
5190
@@ -4965,7 +5200,7 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
4965
5200
4966
5201
<li><p> Otherwise, if the bytes transmission for <var> response</var> 's message body is done
4967
5202
normally and <var> stream</var> is <a for=ReadableStream>readable</a> , then
4968
- <a for=ReadableStream>close</a> <var> stream</var> and abort these in-parallel steps.
5203
+ <a for=ReadableStream>close</a> <var> stream</var> , and abort these in-parallel steps.
4969
5204
</ol>
4970
5205
</ol>
4971
5206
0 commit comments