PHPackages                             terminal42/header-replay-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. terminal42/header-replay-bundle

AbandonedArchivedSymfony-bundle[Caching](/categories/caching)

terminal42/header-replay-bundle
===============================

Send preflight requests for user context headers and replay them for reverse proxy support.

1.5.3(7y ago)8290.9k↓17.9%1MITPHPPHP ^5.6 | ^7.0

Since Jun 12Pushed 7y ago3 watchersCompare

[ Source](https://github.com/terminal42/header-replay-bundle)[ Packagist](https://packagist.org/packages/terminal42/header-replay-bundle)[ RSS](/packages/terminal42-header-replay-bundle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (8)Versions (18)Used By (0)

terminal42/header-replay-bundle
===============================

[](#terminal42header-replay-bundle)

[![](https://camo.githubusercontent.com/702bbf927abb40ece8b7efebc7580095fc763984f3011179b406e7a4f9f7479d/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f7465726d696e616c34322f6865616465722d7265706c61792d62756e646c652f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/terminal42/header-replay-bundle/)[![](https://camo.githubusercontent.com/5bb82c5929af525302817ce27701b1ce09971ca08f345b19ab72ca190916f9b5/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f7465726d696e616c34322f6865616465722d7265706c61792d62756e646c652f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://coveralls.io/github/terminal42/header-replay-bundle)

What is this?
-------------

[](#what-is-this)

Caching is a very important but also very hard task of any application. Reverse proxies help us to maintain a shared cache on (or in front of) your web server. They will cache the responses of your application based on the caching headers you set such as `Cache-Control` etc. A cache entry always relates to a certain URI. At some point, however, you'll find yourself trying to have different cache entries for the same URI (also think ESI requests here). This is where the `Vary` header comes into play. By setting `Vary: ` you can tell a reverse proxy to add multiple cache entries for the same URI, essentially extending its internal identifier by not only using the URI but also including the `Vary` headers.

This is great but a lot of stuff - especially in PHP applications - is bound to PHP session and thus the `Cookie` header that contains the `PHPSESSID` cookie. Now if you want to `Vary` on something that is part of the session, you would need to send a `Vary: Cookie` response which basically kills the whole point of a proxy because not two users will have the same `Cookie` values, right?

What we'd need to do is to split up the data that relates to our PHP session into multiple headers so we can `Vary` on them separately. Let's work on an example for that. Think of some legacy application that has no responsive layout yet and you'd have some desktop and mobile version and you can switch these whereas the application stores the version you like in your session. Now, as the content is not the same on mobile and desktop, we need to cache these entries individually. So having `Page-Layout: mobile` and `Page-Layout: desktop` and the corresponding `Vary: Page-Layout` headers on the response would solve our problem. But no browser is going to send you the `Page-Layout: mobile` header on the initial page view because where should it know that from and the reverse proxy will thus only ever consider one of your page layouts. Bummer!

Of course, there is a solution to it. I call it "preflight request" but I haven't found a clear definition for it yet, but the concept is simple:

[![Diagram supporting the explanation that follows in text form](./docs/preflight_requests.png "Diagram")](./docs/preflight_requests.png)

1. Client sends request to server.
2. Proxy intercepts the request to try to serve from the cache.
3. Based on some conditions (usually `Cookie` or `Authorization` headers) the proxy executes a "preflight request" to the real application.
4. The real application notices it's just a "preflight request" and replies with the "replay headers" (in our example `Page-Layout: `)
5. The proxy "replays" the headers of the preflight request onto the real request and starts over.
6. Now the proxy checks the internal cache again if a cache entry wanted to `Vary` on `Page-Layout` and correctly serves different versions for the same URI.

You can find more information about the concept in the docs of the awesome [FOSHttpCacheBundle](http://foshttpcachebundle.readthedocs.io/en/latest/features/user-context.html#how-it-works) on top of which this bundle sits.

The `FOSHttpCacheBundle`, however, handles this process only for one specifiy use case which is the "user context". For the `FOSHttpCacheBundle` there's always only one header which is the `User-Context-Hash`. Of course, you could include the `Page-Layout` value in this hash and you could achieve individual cache entries per page layout. One disadvantage of this approach, however, is that it includes information of multiple sources in one header again. Remember we said `Vary: Cookie` is not really helpful because nobody shares the same `Cookie` header value? Of course this is not quite the same here because you will still have a lot of matches but the rule is simple:

> The more information you include in the same header you want to `Vary` on, the less cache hits you will get.

This becomes especially interesting when you work with a lot of ESI requests and your page is made up of many little fragments that `Vary` on different information. Now imagine you have 10 fragments and only 1 varies based on the user permissions (`User-Context-Hash`) and the other 9 only `Vary` based on the `Page-Layout`. If you included all the information in the same hash, the 9 fragments would be never shared amongst user permissions although they perfectly could!

This is where this bundle jumps in. It allows you to easily register your event listeners and takes care of replaying them automatically for the Symfony HttpCache. Unfortunately, for Varnish it still takes manual configuration but we'll get to that.

Installation
============

[](#installation)

Step 1: Download the Bundle
---------------------------

[](#step-1-download-the-bundle)

Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:

```
$ composer require terminal42/header-replay-bundle "^1.0" php-http/guzzle6-adapter "^1.0.0"
```

The `header-replay-bundle` sits on top of the `friendsofsymfony/http-cache-bundle`which requires the virtual package `php-http/client-implementation`. You can use any client-implementation you like but you have to require one, which is why in this example we've used `php-http/guzzle6-adapter`. You can read more about HTTPlug [here](http://docs.php-http.org/en/latest/httplug/users.html).

This command requires you to have Composer installed globally, as explained in the [installation chapter](https://getcomposer.org/doc/00-intro.md)of the Composer documentation.

Step 2: Enable the Bundle
-------------------------

[](#step-2-enable-the-bundle)

Then, enable the bundle by adding it to the list of registered bundles in the `app/AppKernel.php` file of your project:

```
