Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server pushed resources in ResourceTiming #53

Closed
igrigorik opened this issue May 2, 2016 · 24 comments
Closed

Server pushed resources in ResourceTiming #53

igrigorik opened this issue May 2, 2016 · 24 comments
Milestone

Comments

@igrigorik
Copy link
Member

HTTP/2 allows the server to "push" resources to the client. We should figure out if and how these should be exposed via ResourceTiming.

@igrigorik igrigorik added this to the V2 milestone May 2, 2016
@yoavweiss
Copy link
Contributor

+1 to figuring this out and exposing it. Maybe a F2F session?

@igrigorik
Copy link
Member Author

FWIW, I think we'd need to solve whatwg/fetch#65, whatwg/fetch#51 first.

@igrigorik igrigorik modified the milestones: Level 3, Level 2 Jun 29, 2016
@MattMenke2
Copy link

Current behavior, for reference, is that we're too cowardly to send values that go backwards in time, so we make sure no value is before requestStart (FetcherStart? The time the URLRequest was created). This currently applies mostly to sockets create before the request using preconnect / late binding.

@n8schloss
Copy link

We're starting to use HTTP/2 push across our video products now and will hopefully be expanding on their use in the coming months so this kind of info is increasingly important for our product teams. If possiable I'd love to talk about this at the next f2f :)

It'd be cool if we could make some progress on or at least talk about this issue before whatwg/fetch#65 and whatwg/fetch#51 are totally resolved.

@igrigorik
Copy link
Member Author

Cloudflare enabled h2 push via Link: preload, so we can use that as a demo: https://blog.cloudflare.com/announcing-support-for-http-2-server-push-2/

They also provide a diagnostics header to indicate what got pushed. E.g..

cf-h2-pushed:</assets/css/screen.css?v=fafa9a0235>,</content/images/2016/04/T...he_hill-_-3854246685-.jpg>,</content/images/2016/04/http2-server-push-2.png>,</content/images/2016/04/S...016-04-26-at-15-07-53.png>,</content/images/2016/04/S...016-04-26-at-15-08-59.png>,</content/images/2016/04/S...016-04-26-at-17-25-15.png>,</content/images/2016/04/S...016-04-26-at-17-25-42.png>,</content/images/2016/04/Capture3.PNG>,</content/images/2016/04/Capture1.PNG>,</assets/js/jquery.fitvids.js?v=fafa9a0235>

Looking up one of those resources via RT in Chrome yields:
image

What's missing in the above report; what do you want to know about such resources beyond what's already there?

@DanielBaulig
Copy link

DanielBaulig commented Oct 27, 2016

What we would like to know is the fact that the server has pushed the resource. Maybe the initiatorType should not be "link", but "push"? Or an additional field would expose the fact that this was pushed.

It would probably also be helpful to know when the push started, ended, etc. I believe the current data only exposes when the user-land request started and the user-land response started and ended. For pushed resources it's also of interest when the push promise was received and fulfilled.

@yoavweiss
Copy link
Contributor

yoavweiss commented Oct 28, 2016

From what I can tell, these numbers report when the resource was read by the renderer, rather than when the resource was actually pushed and read from the socket by the networking stack.

This may be an implementation issue, but it's currently not properly defined what these numbers should be.

Also, what do we do with resources pushed in one nav and read from the push cache over another nav? AFAICT, that's possible for consecutive pages that use the same H2 connection. Would they have negative numbers? Should we define their timings as 0?

@MattMenke2
Copy link

Actually, the times represent when the browser process received the request. We're too cowardly to return times prior to when the browser received, which could result in negative times, and times out of order. Preconnect means connection times could be too early. With push, most times could be before navigationStart (I'm not quite sure about fetchStart. If we're talking about the fetch API, fetchStart would still only happen once the renderer issues the request, so it could be after most other events. If we're talking about when we start receiving data, that would be another time entirely. Note that, per spec, fetchStart is when the "fetch process" starts, and that links directly to fetch API, implying the former interpretation.

@yoavweiss
Copy link
Contributor

Actually, the times represent when the browser process received the request.

Fair enough, but that's still after the renderer initiated the request for the resource, and therefore still significantly after the time these resources were received by the net stack.

Going to https://mygreatjobs.de/jobs/en/jobboard in Canary, I see:

  • First CSS was pushed way before the HTML response started arriving
  • performance.timing.responseStart-performance.timing.fetchStart (so HTML's TTFB) => 1544
  • performance.getEntriesByType("resource")[0].fetchStart is significantly after that time (I see 1748), even though the waterfall shows this resource arriving shortly after connection establishment (~500ms)

@MattMenke2
Copy link

I assume fetchStart is set by the renderer, when it requests the resource. The navigation timing API makes it sound like this is when the fetch API starts, which requires checking with things like service worker, which we can't do (Or at least don't do) with push. I think requestStart is actually the more interesting value here - it currently is when the URLRequest is created, but with push, perhaps it shouldn't be, though requestStart is currently also recorded before we talk to ServiceWorker, so switching it to when the resource was pushed would be inconsistent there.

@igrigorik
Copy link
Member Author

Going to https://mygreatjobs.de/jobs/en/jobboard in Canary, I see.. (snip)

Ok, I'll bite.. This is a bit of pathological example, but it's also a good one to discuss because it highlights all of the major corner cases -- three of them, for a single file:

  1. There is the PUSH'ed response initiated by h2o, which is delivered prior to the DATA packets of the HTML response.
  2. There is the preload-initiated request by the browser, which "consumes" the PUSH'ed response and writes it out to the HTTP cache, and loads it into the memory cache.
    • h2o does not remove the rel=preload header, causing the browser to initiate the request once it processes the response headers.
  3. There is the <link rel=stylesheet> initiated request which (unfortunately) does not get matched with the preloaded response in the memory cache due to missing as=style and instead reads out the response from the HTTP cache.

Inspecting performance timeline in Chrome, I see two requests:

[
  {
    "name": "https:\/\/mygreatjobs.de\/jobs\/Greenjobs\/Greenjobs.css",
    "entryType": "resource",
    "startTime": 1767.055,
    "duration": 35.47,
    "initiatorType": "link",
    "workerStart": 0,
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 1767.055,
    "domainLookupStart": 1767.055,
    "domainLookupEnd": 1767.055,
    "connectStart": 1767.055,
    "connectEnd": 1767.055,
    "secureConnectionStart": 0,
    "requestStart": 1778.605,
    "responseStart": 1787.11,
    "responseEnd": 1802.525,
    "transferSize": 27747,
    "encodedBodySize": 27369,
    "decodedBodySize": 238162
  },
  {
    "name": "https:\/\/mygreatjobs.de\/jobs\/Greenjobs\/Greenjobs.css",
    "entryType": "resource",
    "startTime": 1811.435,
    "duration": 16.425,
    "initiatorType": "link",
    "workerStart": 0,
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 1811.435,
    "domainLookupStart": 1811.435,
    "domainLookupEnd": 1811.435,
    "connectStart": 1811.435,
    "connectEnd": 1811.435,
    "secureConnectionStart": 0,
    "requestStart": 1811.915,
    "responseStart": 1815.685,
    "responseEnd": 1827.86,
    "transferSize": 0,
    "encodedBodySize": 27369,
    "decodedBodySize": 238162
  }
]

The first RT entry corresponds to the request initiated by Link: rel=preload that consumes the push response - see (2). The second RT entry is the <link rel=stylesheet> request that reads data from cache. The notable omission here is the "push response"... However, before we declare that a RT bug, it's worth pointing out that we don't have platform on agreement on how and where push responses should be surfaced -- e.g. both FF and Chrome don't commit push responses to HTTP cache or provide any sort of callbacks to the application to infer that a resource was pushed. Related discussions that we need to address prior to tackling this in RT:

Here's the cleaned up netlog trace from Chrome for above flow:


t=1662 [st=  0] +SOCKET_POOL_CONNECT_JOB  [dt=353]
                 --> group_name = "ssl/mygreatjobs.de:443"
t=1662 [st=  0]   +SOCKET_POOL_CONNECT_JOB_CONNECT  [dt=353]
t=1662 [st=  0]     +HOST_RESOLVER_IMPL_REQUEST  [dt=257]
                     --> address_family = 0
                     --> allow_cached_response = true
                     --> host = "mygreatjobs.de:443"
                     --> is_speculative = false
t=1662 [st=  0]        HOST_RESOLVER_IMPL_IPV6_REACHABILITY_CHECK
                       --> cached = true
                       --> ipv6_available = true
t=1662 [st=  0]        HOST_RESOLVER_IMPL_CREATE_JOB
t=1662 [st=  0]        HOST_RESOLVER_IMPL_JOB_ATTACH
                       --> source_dependency = 920 (HOST_RESOLVER_IMPL_JOB)
t=1919 [st=257]     -HOST_RESOLVER_IMPL_REQUEST
t=2015 [st=353]      CONNECT_JOB_SET_SOCKET
                     --> source_dependency = 977 (SOCKET)
t=2015 [st=353]   -SOCKET_POOL_CONNECT_JOB_CONNECT
t=2015 [st=353] -SOCKET_POOL_CONNECT_JOB


--- h2o pushes critical resources ahead of HTML resposne

t= 2561 [st= 129]    HTTP2_SESSION_RECV_PUSH_PROMISE
                     :path: /jobs/Greenjobs/Greenjobs.css
                     --> promised_stream_id = 2
t= 2561 [st= 129]    HTTP2_SESSION_RECV_HEADERS
                     --> fin = false
                     --> :status: 200
                         content-length: 27369
                     --> stream_id = 2                     
t= 2563 [st= 131]    HTTP2_SESSION_RECV_DATA
                     --> fin = false
                     --> size = 4996
                     --> stream_id = 2                     
t= 2657 [st= 225]    HTTP2_SESSION_RECV_DATA
                     --> fin = false
                     --> size = 274
                     --> stream_id = 2
t= 2755 [st= 323]    HTTP2_SESSION_RECV_DATA
                     --> fin = false
                     --> size = 1246
                     --> stream_id = 2
t= 2756 [st= 324]    HTTP2_SESSION_RECV_DATA
                     --> fin = true
                     --> size = 0
                     --> stream_id = 2

--- HTML response headers + body arrives

t= 3426 [st= 994]    HTTP2_SESSION_RECV_HEADERS
                     --> fin = false
                     --> :status: 200
                     --> stream_id = 1
t= 3428 [st= 996]    HTTP2_SESSION_RECV_DATA
                     --> fin = false
                     --> size = 417
                     --> stream_id = 1
t= 3442 [st=1010]    HTTP2_STREAM_ADOPTED_PUSH_STREAM
                     --> stream_id = 2
                     --> url = "https://mygreatjobs.de/jobs/Greenjobs/Greenjobs.css"                     

--- Link header initiated fetch

987: URL_REQUEST
https://mygreatjobs.de/jobs/Greenjobs/Greenjobs.css
Start Time: 2016-11-02 09:43:07.792

t=3430 [st= 0] +REQUEST_ALIVE  [dt=36]
t=3431 [st= 1]    URL_REQUEST_DELEGATE  [dt=0]
t=3431 [st= 1]   +URL_REQUEST_START_JOB  [dt=19]
                  --> load_flags = 33024 (MAYBE_USER_GESTURE | VERIFY_EV_CERT)
                  --> method = "GET"
                  --> priority = "MEDIUM"
                  --> url = "https://mygreatjobs.de/jobs/Greenjobs/Greenjobs.css"
t=3431 [st= 1]      URL_REQUEST_DELEGATE  [dt=0]
t=3431 [st= 1]      HTTP_CACHE_GET_BACKEND  [dt=0]
t=3431 [st= 1]      HTTP_CACHE_OPEN_ENTRY  [dt=6]
                    --> net_error = -2 (ERR_FAILED)
t=3437 [st= 7]      HTTP_CACHE_CREATE_ENTRY  [dt=1]
t=3438 [st= 8]      HTTP_CACHE_ADD_TO_ENTRY  [dt=0]
t=3438 [st= 8]     +HTTP_STREAM_REQUEST  [dt=4]
t=3438 [st= 8]        HTTP_STREAM_REQUEST_STARTED_JOB
                      --> source_dependency = 1039 (HTTP_STREAM_JOB)
t=3442 [st=12]        HTTP_STREAM_REQUEST_BOUND_TO_JOB
                      --> source_dependency = 1039 (HTTP_STREAM_JOB)
t=3442 [st=12]     -HTTP_STREAM_REQUEST
t=3442 [st=12]      HTTP_TRANSACTION_SEND_REQUEST  [dt=1]
t=3443 [st=13]     +HTTP_TRANSACTION_READ_HEADERS  [dt=0]
t=3443 [st=13]        HTTP_TRANSACTION_READ_RESPONSE_HEADERS
                      --> HTTP/1.1 200
                          status: 200
                          server: h2o/2.1.0-beta3
                          date: Wed, 02 Nov 2016 13:43:06 GMT
                          cache-control: max-age=31536000
                          content-type: text/css
                          last-modified: Thu, 17 Mar 2016 12:09:31 GMT
                          vary: accept-encoding
                          content-encoding: br
                          accept-ranges: bytes
                          strict-transport-security: max-age=31536000; includeSubDomains; preload
                          content-security-policy: default-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com data:; font-src 'self' https://fonts.gstatic.com
                          x-xss-protection: 1; mode=block
                          x-frame-options: SAMEORIGIN
                          x-content-type-options: nosniff
                          x-http2-push: pushed
                          content-length: 27369
t=3443 [st=13]     -HTTP_TRANSACTION_READ_HEADERS
t=3443 [st=13]      HTTP_CACHE_WRITE_INFO  [dt=5]
t=3448 [st=18]      HTTP_CACHE_WRITE_DATA  [dt=1]
t=3449 [st=19]      HTTP_CACHE_WRITE_INFO  [dt=1]
t=3450 [st=20]      URL_REQUEST_DELEGATE  [dt=0]
t=3450 [st=20]      URL_REQUEST_FILTERS_SET
                    --> filters = "BROTLI"
t=3450 [st=20]   -URL_REQUEST_START_JOB
t=3450 [st=20]    URL_REQUEST_DELEGATE  [dt=0]
t=3451 [st=21]    HTTP_TRANSACTION_READ_BODY  [dt=0]
t=3451 [st=21]    HTTP_CACHE_WRITE_DATA  [dt=3]
t=3454 [st=24]    URL_REQUEST_JOB_BYTES_READ
                  --> byte_count = 27369
t=3455 [st=25]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3455 [st=25]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3459 [st=29]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3462 [st=32]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3463 [st=33]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3465 [st=35]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3466 [st=36]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3466 [st=36]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 8786
t=3466 [st=36]    HTTP_TRANSACTION_READ_BODY  [dt=0]
t=3466 [st=36]    HTTP_CACHE_WRITE_DATA  [dt=0]
t=3466 [st=36] -REQUEST_ALIVE

--- <link> initiated request

t=3475 [st= 0] +REQUEST_ALIVE  [dt=16]
t=3475 [st= 0]    URL_REQUEST_DELEGATE  [dt=0]
t=3475 [st= 0]   +URL_REQUEST_START_JOB  [dt=4]
                  --> load_flags = 33024 (MAYBE_USER_GESTURE | VERIFY_EV_CERT)
                  --> method = "GET"
                  --> priority = "HIGHEST"
                  --> url = "https://mygreatjobs.de/jobs/Greenjobs/Greenjobs.css"
t=3475 [st= 0]      URL_REQUEST_DELEGATE  [dt=0]
t=3475 [st= 0]      HTTP_CACHE_GET_BACKEND  [dt=0]
t=3475 [st= 0]      HTTP_CACHE_OPEN_ENTRY  [dt=2]
t=3477 [st= 2]      HTTP_CACHE_ADD_TO_ENTRY  [dt=0]
t=3477 [st= 2]      HTTP_CACHE_READ_INFO  [dt=1]
t=3479 [st= 4]      URL_REQUEST_DELEGATE  [dt=0]
t=3479 [st= 4]      URL_REQUEST_FILTERS_SET
                    --> filters = "BROTLI"
t=3479 [st= 4]   -URL_REQUEST_START_JOB
t=3479 [st= 4]    URL_REQUEST_DELEGATE  [dt=0]
t=3479 [st= 4]    HTTP_CACHE_READ_DATA  [dt=6]
t=3485 [st=10]    URL_REQUEST_JOB_BYTES_READ
                  --> byte_count = 27369
t=3486 [st=11]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3486 [st=11]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3488 [st=13]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3491 [st=16]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3491 [st=16]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3491 [st=16]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3491 [st=16]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 32768
t=3491 [st=16]    URL_REQUEST_JOB_FILTERED_BYTES_READ
                  --> byte_count = 8786
t=3491 [st=16]    HTTP_CACHE_READ_DATA  [dt=0]
t=3491 [st=16] -REQUEST_ALIVE

In short, I believe the current Chrome behavior is correct. The two existing records reflect the two browser-initiated requests (one by preload other by rel=stylesheet), which I would expect to see. The remaining question is if and whether we ought to surface the push'ed response as the third RT entry in that set.

@yoavweiss
Copy link
Contributor

There is the initiated request which (unfortunately) does not get matched with the preloaded response in the memory cache due to missing as=style and instead reads out the response from the HTTP cache.

Yeah, this is a misconfiguration on the site's part. RT (and dev tools) are doing the right thing here and reporting it as a duplicate download. The main problem I see with these requests is that when running devtools with "disable cache", they are not being fetched from the HTTP cache, but getting double downloaded. In any case, this is out of scope for this discussion.

However, before we declare that a RT bug, it's worth pointing out that we don't have platform on agreement on how and where push responses should be surfaced -- e.g. both FF and Chrome don't commit push responses to HTTP cache or provide any sort of callbacks to the application to infer that a resource was pushed. Related discussions that we need to address prior to tackling this in RT:

https://groups.google.com/a/chromium.org/d/msg/loading-dev/GoONR_xSGJ4/eeIqD_XaAAAJ
whatwg/fetch#354

While I agree that above issues should be tackled and the observable behavior of these "push caches" should be properly defined, I don't think there's any cause to block exposing the times in which the push resources actually arrived on the network on defining their caches. IMO, these issues are orthogonal.

In short, I believe the current Chrome behavior is correct.

It is according to the current spec. It is also lacking info regarding the times resources were actually pushed, which I believe is the reason we're discussing it here :)

The remaining question is if and whether we ought to surface the push'ed response as the third RT entry in that set.

I don't think push should be exposed as a separate entry. Multiple entries indicate multiple fetches from the renderer's perspective. Push responses don't constitute multiple fetches.

I think we could have exposed the actual push times as separate attributes on the same resource entry, e.g. pushedResponseStart and pushedResponseEnd (and potentially pushPromiseStart), which may be smaller than fetchStart for the resource, but are truncated to 0 in case the push happened before current navigation started. For these cases, we may also need a deliveredByPush flag, to differentiate them from ones where there was no push.

@igrigorik
Copy link
Member Author

While I agree that above issues should be tackled and the observable behavior of these "push caches" should be properly defined, I don't think there's any cause to block exposing the times in which the push resources actually arrived on the network on defining their caches. IMO, these issues are orthogonal.

The question in my head is not whether it is committed to cache or not, but whether it is exposed to the developer at all as a first-class primitive. Current browser behavior seems to indicate "no". Personally, I don't think that's quiet right, but we should resolve that first.

I don't think push should be exposed as a separate entry. Multiple entries indicate multiple fetches from the renderer's perspective. Push responses don't constitute multiple fetches.

I think we could have exposed the actual push times as separate attributes on the same resource entry, e.g. pushedResponseStart and pushedResponseEnd (and potentially pushPromiseStart), which may be smaller than fetchStart for the resource, but are truncated to 0 in case the push happened before current navigation started. For these cases, we may also need a deliveredByPush flag, to differentiate them from ones where there was no push.

I would argue the opposite, actually.. We've already been burned by this and hence the various discussions on unbundling redirects, preflights, range-requests and the like -- i.e. #21. Following that same line of reasoning, a pushed response is a separate entity; a preload is separate from the request that consumed it, and so on. That said, I do agree that it's helpful to mark push'ed response as such: initiator = push, or some such.

@yoavweiss
Copy link
Contributor

The question in my head is not whether it is committed to cache or not, but whether it is exposed to the developer at all as a first-class primitive. Current browser behavior seems to indicate "no". Personally, I don't think that's quiet right, but we should resolve that first.

OK. I agree we need to decide on the principle question of "is it OK to expose the fact that H2 push happened to the platform?" before we can continue on either front.

We've already been burned by this and hence the various discussions on unbundling redirects, preflights, range-requests and the like -- i.e. #21. Following that same line of reasoning, a pushed response is a separate entity;

Seems like an overkill to me, but I could be convinced that it's the right thing for the sake of consistency...

a preload is separate from the request that consumed it

That is not currently true (unless the consuming request didn't match the preload, and hit cache/network).

@igrigorik
Copy link
Member Author

igrigorik commented Nov 3, 2016

a preload is separate from the request that consumed it
That is not currently true (unless the consuming request didn't match the preload, and hit cache/network).

You're right, and I still feel like that's a bug (demo here). Ideally, I'd prefer to see separate requests, one for preload, and one for each instance of consuming that said response, but that's a separate discussion, let's focus this on push.

@valour01
Copy link

A simple question, hope to get some comments if available @igrigorik @yoavweiss . For pushed resource, what does the requestStart attribute in the RT represent?
What I am confused now is that client will not send request to the server when server pushed the resource to the client, then is the value represent the time when push promise frames arriving at the client side? If not, what does it mean when the client will not send a request ? Maybe my understanding to the requestStart is not right. Many Thanks

@igrigorik
Copy link
Member Author

A simple question, hope to get some comments if available @igrigorik @yoavweiss . For pushed resource, what does the requestStart attribute in the RT represent?

As of today, in Chrome at least, that's the time when the request was initiated by the renderer for that resource; this timestamp has no relation to when the server initiated the push.

What I am confused now is that client will not send request to the server when server pushed the resource to the client, then is the value represent the time when push promise frames arriving at the client side? If not, what does it mean when the client will not send a request ? Maybe my understanding to the requestStart is not right.

The short answer is that it's not defined.. :-)

server ---> (client's push cache) <-- renderer request

Server pushes the response into the push cache. Renderer makes the request and if there is a yet to be fulfilled promise, may block until the server delivers said response. Defining how all of this is actually resolved via RT is what this thread is all about.

@valour01
Copy link

Server pushes the response into the push cache. Renderer makes the request and if there is a yet to be fulfilled promise, may block until the server delivers said response. Defining how all of this is actually resolved via RT is what this thread is all about.

I see. May I understand in this way. No matter server pushed the resource or not, client side will always initiate the request, the requestStart time is exactly the time before initiate the request. After initiating the request, the client will check whether there is a push promise frame indicating that the resource is going to be received, if so, client will not send the request but waiting for the response. If not, client may send request to the server for the resource. And there is no attribute in the RT specify something related to server push, right?

The time immediately before the user agent starts requesting the resource from the server, or from relevant application caches or from local resources, if the last non-redirected fetch of the resource passes the timing allow check algorithm.

This is the definition of requestStart. According to your explanation, does before the user agent starts requesting the resource represent the time when the render starts to initiate the request rather than the time for sending the request? Thanks a lot.

@igrigorik
Copy link
Member Author

May I understand in this way. No matter server pushed the resource or not, client side will always initiate the request, the requestStart time is exactly the time before initiate the request. After initiating the request, the client will check whether there is a push promise frame indicating that the resource is going to be received, if so, client will not send the request but waiting for the response. If not, client may send request to the server for the resource. And there is no attribute in the RT specify something related to server push, right?

Yep.

According to your explanation, does before the user agent starts requesting the resource represent the time when the render starts to initiate the request rather than the time for sending the request?

Yep.

@nbeloglazov
Copy link

I have a related question about transferSize field for server-pushed resources. If server sends a PUSH promise and browser cancels the stream because it has that resource in cache. Should transferSize show actual number of bytes transferred to the browsers even if the push was cancelled? It think it should as there is not other way to get that data. Server push might waste bandwidth if resource already in cache and it's important metric when deciding whether some resources should be server-pushed or not.

@igrigorik
Copy link
Member Author

@nbeloglazov no, I think these are orthogonal problems. If the resource came from cache, it should have a transferSize of zero. The fact that server push is not observable is a separate concern and needs a different mechanism.

@bluesmoon
Copy link

The issue for us with preload is that the initiatorType of scripts, images, fonts, is now link. I'm seeing this in live data. We can scan the DOM, but there's no way to determine from JavaScript that it was preloaded if this came from a response header.

@noamr
Copy link
Contributor

noamr commented Jul 18, 2022

Is HTTP2-push still a thing, or are we moving away from this to link headers and early hints?

@MattMenke2
Copy link

Chromium has dropped / is dropping support, and no other browser engine ever added support for it, I believe, so think we can probably close this.

@noamr noamr closed this as completed Jul 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants