1

I know that browsers can send RST_STREAM-frames to cancel serverpush.

Does it make sense to send Last-Modified or Etag headers inside the PUSH_PROMISE? Or is the validation of the to-be-pushed resources only based on their URI (as Simone Bordet answered to the following question two years ago)?

Does the browser cancel server push when a resource is in cache?

I couldn't find an exact answer to this question.

mzjn
  • 48,958
  • 13
  • 128
  • 248

2 Answers2

1

When a HTTP/2 server pushes a resource, it generates the PUSH_PROMISE frame to send to the client, and at the same time it creates a synthetic request that is processed as if the remote client sent it.

Remember that the PUSH_PROMISE frame represent the request that the client would make for that resource, not the response.

Typically, the content of the PUSH_PROMISE frame headers and the headers of the synthetic request are the same, but - depending on the implementations - it may not be the case.

Headers Last-Modified or ETag only make sense in responses, so it would not make sense to add them to a PUSH_PROMISE frame.

Whether it makes sense to add other request headers such as If-Modified-Since to the PUSH_PROMISE depends on whether the same headers are used for the synthetic request. If the same headers are used, as it's typically the case, then adding headers such as If-Modified-Since has only effects on the server-side processing: the server may generate a 304 Not Modified when processing the synthetic request.

However, it would be strange for a server to send a PUSH_PROMISE for a resource, followed by a 304. If the server knows that the client already has the resource cached, it may as well skip sending the PUSH_PROMISE.

Adding response headers such as Last-Modified to a PUSH_PROMISE frame does not make sense because a PUSH_PROMISE represents a request.

Adding conditional request headers such as If-Modified-Since normally requires the server to have some knowledge about what resources were previously served to the client: it has to know whether a resource has already been served so that sending a 304 to the client for a pushed resource will make the client use the resource already present in its cache.

sbordet
  • 16,856
  • 1
  • 50
  • 45
  • Ok, so there's nothing inside the `PUSH_PROMISE` (except the file's URI) that can help the browser to decide if it wants to accept or cancel a push? – Bodo Wissemann Jan 01 '18 at 08:22
1

After searching deeper i think i found the answer:

The pushBuilder's Api says to .lastModified():

Set the last modified date to be used for conditional pushes.

and to .etag():

Set the etag to be used for conditional pushes.

I misunderstood those explanations and thought, the specified values are sent to the browser inside the PUSH_PROMISE to help it decide whether to accept the pushed file or to cancel the stream (by sending RST_STREAM).

In fact, those values seem to tell the server, if it has to push sth. or not. By setting a file's last-modified-date as .lastModified(), i got the behavior Simone Bordet described in his comment above: a 304 was sent, even if the file didn't exist in my cache.

So now it's fully clear that it doesn't make sense to set these values without knowing exactly what's inside a client's cache.

Something like conditional headers inside a PUSH_PROMISE seem not to exist right now: I didn't find anything about that in the HTTP2-specs and while reading in chrome's issue-tracker, i found Tom Bergan commenting this on an open (02.01.2017) issue (https://bugs.chromium.org/p/chromium/issues/detail?id=232040#c62):

... I think a better way to handle this case is to convert the pushed response to a 304 when the pushed response matches the cached resource. There are two possible implementations:

  1. Don't cancel the push until after receiving the pushed response headers (since the response headers contain ETag and/or Last-Modified). If the pushed resource is already cached, the browser would convert the pushed response to a 304 and cancel the push. However, IMO, this waits too long to cancel the push.

  2. Add conditional headers like If-Match to the PUSH_PROMISE so the browser knows exactly which resource is being pushed. This is a good idea but it would need to be spec'd out before we could implement it. https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0522.html ...

So what i expected to be possible (help the browser to check a cached resource's validity by reading out some header-information sent in the PUSH_PROMISE) is not possible now, but eventually will be. Besides that, it seems that cache-digest will be implemented in browsers somewhere in the future, what will be even more effective, because unnecessary pushes can be avoided on the server. Chrome is already working on this, as can be seen here: https://docs.google.com/document/d/1HhmyzKUPuWcCs8wG_GLSu3mvptygXtO2mBl5xlmEB-4/edit#

Please correct me if i said anything wrong.