php session 使用 http2 预加载丢失

php session lost using http2 preload

我在使用 HTTP/2 推送预加载和 php session 时遇到问题:当我打开一个使用预加载 header 功能的页面时,session 是 lost/reset。应用代码是开源的,这里我设置了Linkheader: https://github.com/SergiX44/XBackBone/blob/master/app/Controllers/UploadController.php#L107

...
$url = urlFor("/$args[userCode]/$args[mediaCode]/raw");
$response = $response->withHeader('Link', "<{$url}>; rel=preload; as={$type}");
...

正如您在图片中看到的那样,HTTP/2 推送实际上在工作,但是 "pushed" 资源正在重置 session(本例中的 "raw" 请求是一张图片,由 PHP 提供)。为什么会这样?

在 Apache HTTP/2 模块中 only certain headers are copied on pushed request

header 的完整列表已列出 in the Apache documentation

Apache will look at the original request (the one that triggered the PUSH) and copy the following headers over to PUSH requests: user-agent, accept, accept-encoding, accept-language, cache-control.

All other headers are ignored. Cookies will also not be copied over. PUSHing resources that require a cookie to be present will not work. This can be a matter of debate. But unless this is more clearly discussed with browser, let's err on the side of caution and not expose cookie where they might oridinarily not be visible.

请注意它是如何明确指出不会发送 cookie 的。因此没有 session,因此您的 PHP 应用正在设置一个新应用。

HTTP/2 推送旨在发送安全的、可缓存的资源,Apache 已选择将其解释为具有 non-authenticated 资源。因此,除非您可以在不需要 cookie 的情况下提供您推送的资源,否则您不应该推送它。

您可以使用 preload header 和 nopush 属性来避免推送它,但仍然让浏览器以高优先级请求它。当浏览器请求它时,它会发送适当的 cookie,一切都应该有效。它可能不像推送那么快,但通常已经足够好了。此外,由于浏览器知道它们的缓存,因此通常建议使用预加载而不是推送。 Push is complicated to get right - 不仅仅是因为您在这里发现的问题。