Search code examples
phpsessionhttp2slim-3

php session lost using http2 preload


I'm experiencing a problem using HTTP/2 push preload with the php session: when I open a page that use a preload header feature, the session is lost/reset. The application code is open source, here is where I set the Link header: 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}");
...

request

raw request headers

As you can see in the pictures the HTTP/2 push is actually working, but the "pushed" resource is resetting the session (the "raw" request in this case is an image, served by PHP). Why is that happening?


Solution

  • In Apache HTTP/2 module only certain headers are copied on pushed request.

    The full list of headers is listed 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.

    Note how it explicitly calls out that cookies will not be sent. Therefore there is no session and so your PHP app is setting a new one.

    HTTP/2 push is intended to send safe, cacheable resources and Apache has chosen to interpret this has non-authenticated resources. Therefore unless you can serve your pushed resource without requiring cookies, you should not push it.

    You can use the preload header with the nopush attribute to avoid pushing it, but still have the browser request it with high priority. As the browser is requesting it, it will send the appropriate cookies and all should work. It may not be quiet as fast as push but it’s often good enough. Additionally as browsers are aware of their cache, using preload instead of push is often recommended anyway. Push is complicated to get right - and not just because of the issue you’ve spotted here.