{"id":21518535,"url":"https://github.com/thijsferyn/cacheable-site-silex","last_synced_at":"2026-03-18T00:37:10.499Z","repository":{"id":145343243,"uuid":"80603834","full_name":"ThijsFeryn/cacheable-site-silex","owner":"ThijsFeryn","description":"Develop cacheable sites by levering HTTP. This example site was written in PHP using the Silex framework.","archived":false,"fork":false,"pushed_at":"2017-08-07T08:07:37.000Z","size":35,"stargazers_count":54,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-10-25T02:44:02.183Z","etag":null,"topics":["cache","caching","http","php","silex","twig","varnish","varnish-cache"],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThijsFeryn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-01T09:04:31.000Z","updated_at":"2025-03-18T05:29:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"3172f2d0-eb98-4963-ad00-14220913fb6c","html_url":"https://github.com/ThijsFeryn/cacheable-site-silex","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ThijsFeryn/cacheable-site-silex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThijsFeryn%2Fcacheable-site-silex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThijsFeryn%2Fcacheable-site-silex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThijsFeryn%2Fcacheable-site-silex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThijsFeryn%2Fcacheable-site-silex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThijsFeryn","download_url":"https://codeload.github.com/ThijsFeryn/cacheable-site-silex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThijsFeryn%2Fcacheable-site-silex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30637261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-18T00:09:27.587Z","status":"ssl_error","status_checked_at":"2026-03-18T00:09:26.123Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","caching","http","php","silex","twig","varnish","varnish-cache"],"created_at":"2024-11-24T00:52:55.533Z","updated_at":"2026-03-18T00:37:10.434Z","avatar_url":"https://github.com/ThijsFeryn.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Develop cacheable sites by levering HTTP\nThis piece of example code uses the [Silex](http://silex.sensiolabs.org/) framework to illustrate how you can leverage HTTP to develop cacheable sites.\n \nThe code uses the following HTTP concepts:\n \n * The use of `Cache-Control` headers using directives like `Public`, `Private` to decide which HTTP responses are cacheable and which are not\n * The use of `Cache-Control` headers using directives like `Max-Age` and `S-Maxage` to determine how long HTTP responses can be cached  \n * `Expires` headers as a fallback to control the *time-to-live*\n * Cache variations based on the `Vary` header\n * Conditional requests based on the `Etag` header\n * Returning an `HTTP 304` status code when content was successfully revalidated\n * Content negotiation and language selection based on the `Accept-Language` header\n * Block caching using [Edge Side Includes](https://www.w3.org/TR/esi-lang) and [HInclude](http://mnot.github.io/hinclude/)\n \n## Cacheable\n \nThe output that this example code generates is highly cacheable. We don't keep track of state using cookies and the proper `Cache-Control` headers are used to store the output in an HTTP cache.\n \nIf a reverse caching proxy (like [Varnish](https://www.varnish-cache.org/)) is installed in front of this application, it will respect the *time-to-live* that was set by the application.\n\nReverse caching proxies will also create cache variations by respecting the `Vary` header. A separate version of the response is stored in cache per language.\n\nNon-cacheable content blocks will not cause a full miss on the page. These content blocks are loaded separately using *ESI* or *HInclude*. Either of those techniques load blocks as a subrequest.\n\n*ESI* tags are rendered by the reverse proxy, *HInclude* tags are loaded client-side by the browser. If the code notices that there's no *reverse caching proxy* in front of the application, it will render the output inline, without ESI.\n\n\n\u003e When you test this code, please have a look at the HTTP request headers and HTTP response headers.\n\u003e That's where the magic happens.\n\n## How to install\n\nThe minimum PHP version requirement is `PHP 5.5.9`. All dependencies are loaded via [Composer](https://getcomposer.org), the PHP package manager. Dependency definition happens in the [composer.json](/composer.json) file:\n\n```json\n{\n    \"require\": {\n        \"silex/silex\": \"^2.0\",\n        \"twig/twig\": \"^1.27\",\n        \"symfony/twig-bridge\": \"^3.1\",\n        \"symfony/translation\": \"^3.1\"\n    }\n}\n```\n\nRun `composer install` to install these dependencies. They will be stored in the *vendor* folder. They are bootstrapped in [index.php](/public/index.php) via `require_once __DIR__ . '/../vendor/autoload.php';\n`\n\nIf you use *Apache* as your webserver, there's an [.htaccess](/public/.htaccess) file that routes all traffic for non-existent files and directories to [index.php](/public/index.php).\n\nPlease make sure that your webserver's *document root* points to the [public](/public) folder where the [index.php](/public/index.php) file is located.\n\n## Key components\n\nThe [index.php](/public/index.php) file is the controller of the application. It reads HTTP input and generates HTTP output.\nRoutes are matched via `$app-\u003eget()` callbacks.\n\nOutput is formatted using the [Twig](http://twig.sensiolabs.org) templating language. The [views](/views) folder contains the template file for each route:\n\n* [footer.twig](/views/footer.twig) contains the footer template which returns a translated string and a timestamp\n* [header.twig](/views/header.twig) contains the header template which also returns a translated string and a timestamp\n* [index.twig](/views/index.twig) contains the main template where the header, footer, and navigation are loaded, either via *ESI* or via *HInclude*\n* [nav.twig](/views/nav.twig) contains the navigation template\n\n## Varnish\n\nTo see the impact of this code, I would advise you to install [Varnish](https://www.varnish-cache.org/). Varnish will respect the *HTTP response headers* that were set and will cache the output.\n\nThis is the minimum amount of [VCL code](https://www.varnish-cache.org/docs/4.1/reference/vcl.html#varnish-configuration-language) you need to make this work:\n\n```\nvcl 4.0;\n\nbackend default {\n    .host = \"localhost\";\n    .port = \"8080\";\n}\n\nsub vcl_recv {\n    set req.http.Surrogate-Capability=\"key=ESI/1.0\";\n    if ((req.method != \"GET\" \u0026\u0026 req.method != \"HEAD\") || req.http.Authorization) {\n        return (pass);\n    }\n    return(hash);\n}\n\nsub vcl_backend_response {\n    if(beresp.http.Surrogate-Control~\"ESI/1.0\") {\n        unset beresp.http.Surrogate-Control;\n        set beresp.do_esi=true;\n        return(deliver);\n    }\n}\n```\n\n**This piece of *VCL* code assumes that Varnish is installed on port 80 and your webserver on port 8080 on the same machine.**\n\n## Disclaimer\n\nThis repository and its code are part of the code examples that are featured in my book **\"Getting Started With Varnish Cache\"**. \nIt serves as a set of best practices that should encourage developers to control the cacheability of their sites themselves, instead of relying on infrastructure configuration.\n\nMore information about me:\n\n* Visit my website: https://feryn.eu\n* Learn more about my book: https://book.feryn.eu\n* Follow me on Twitter: [@ThijsFeryn](https://twitter.com/ThijsFeryn)\n* Follow me on Instagram: [@ThijsFeryn](https://instagram.com/ThijsFeryn)\n* View my LinkedIn profile: http://linkedin.com/in/thijsferyn\n* View my public speaking track record: https://talks.feryn.eu\n* Read my blog: https://blog.feryn.eu\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthijsferyn%2Fcacheable-site-silex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthijsferyn%2Fcacheable-site-silex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthijsferyn%2Fcacheable-site-silex/lists"}