docs: efficiently serving large static files (X-Sendfile/X-Accel-Redirect) (#896)

* docs: X-Sendfile/X-Accel-Redirect

* lint

* fix
This commit is contained in:
Kévin Dunglas
2025-04-14 17:18:50 +02:00
committed by GitHub
parent 96dd739064
commit 5e1ad5d797
4 changed files with 144 additions and 1 deletions

View File

@@ -88,6 +88,7 @@ frankenphp php-server
* [Worker mode](https://frankenphp.dev/docs/worker/)
* [Early Hints support (103 HTTP status code)](https://frankenphp.dev/docs/early-hints/)
* [Real-time](https://frankenphp.dev/docs/mercure/)
* [Efficiently Serving Large Static Files](https://frankenphp.dev/docs/x-sendfile/)
* [Configuration](https://frankenphp.dev/docs/config/)
* [Docker images](https://frankenphp.dev/docs/docker/)
* [Deploy in production](https://frankenphp.dev/docs/production/)

View File

@@ -19,7 +19,7 @@
# }
#}
root * public/
root public/
encode zstd br gzip
# Uncomment the following lines to enable Mercure and Vulcain modules

71
docs/fr/x-sendfile.md Normal file
View File

@@ -0,0 +1,71 @@
# Servir efficacement les gros fichiers statiques (`X-Sendfile`/`X-Accel-Redirect`)
Habituellement, les fichiers statiques peuvent être servis directement par le serveur web,
mais parfois, il est nécessaire d'exécuter du code PHP avant de les envoyer :
contrôle d'accès, statistiques, en-têtes HTTP personnalisés...
Malheureusement, utiliser PHP pour servir de gros fichiers statiques est inefficace comparé à
à l'utilisation directe du serveur web (surcharge mémoire, diminution des performances...).
FrankenPHP permet de déléguer l'envoi des fichiers statiques au serveur web
**après** avoir exécuté du code PHP personnalisé.
Pour ce faire, votre application PHP n'a qu'à définir un en-tête HTTP personnalisé
contenant le chemin du fichier à servir. FrankenPHP se chargera du reste.
Cette fonctionnalité est connue sous le nom de **`X-Sendfile`** pour Apache, et **`X-Accel-Redirect`** pour NGINX.
Dans les exemples suivants, nous supposons que le "document root" du projet est le répertoire `public/`
et que nous voulons utiliser PHP pour servir des fichiers stockés en dehors du dossier `public/`,
depuis un répertoire nommé `private-files/`.
## Configuration
Tout d'abord, ajoutez la configuration suivante à votre `Caddyfile` pour activer cette fonctionnalité :
```patch
root public/
# ...
+ # Needed for Symfony, Laravel and other projects using the Symfony HttpFoundation component
+ request_header X-Sendfile-Type x-accel-redirect
+ request_header X-Accel-Mapping ../private-files=/private-files
+
+ intercept {
+ @accel header X-Accel-Redirect *
+ handle_response @accel {
+ root private-files/
+ rewrite * {resp.header.X-Accel-Redirect}
+ method * GET
+
+ # Remove the X-Accel-Redirect header set by PHP for increased security
+ header -X-Accel-Redirect
+
+ file_server
+ }
+ }
php_server
```
## PHP simple
Définissez le chemin relatif du fichier (à partir de `private-files/`) comme valeur de l'en-tête `X-Accel-Redirect` :
```php
header('X-Accel-Redirect: file.txt') ;
```
## Projets utilisant le composant Symfony HttpFoundation (Symfony, Laravel, Drupal...)
Symfony HttpFoundation [supporte nativement cette fonctionnalité](https://symfony.com/doc/current/components/http_foundation.html#serving-files).
Il va automatiquement déterminer la bonne valeur pour l'en-tête `X-Accel-Redirect` et l'ajoutera à la réponse.
```php
use Symfony\Component\HttpFoundation\BinaryFileResponse;
BinaryFileResponse::trustXSendfileTypeHeader();
$response = new BinaryFileResponse(__DIR__.'/../private-files/file.txt');
// ...
```

71
docs/x-sendfile.md Normal file
View File

@@ -0,0 +1,71 @@
# Efficiently Serving Large Static Files (`X-Sendfile`/`X-Accel-Redirect`)
Usually, static files can be served directly by the web server,
but sometimes it's necessary to execute some PHP code before sending them:
access control, statistics, custom HTTP headers...
Unfortunately, using PHP to serve large static files is inefficient compared to
direct use of the web server (memory overload, reduced performance...).
FrankenPHP lets you delegate the sending of static files to the web server
**after** executing customized PHP code.
To do this, your PHP application simply needs to define a custom HTTP header
containing the path of the file to be served. FrankenPHP takes care of the rest.
This feature is known as **`X-Sendfile`** for Apache, and **`X-Accel-Redirect`** for NGINX.
In the following examples, we assume that the document root of the project is the `public/` directory.
and that we want to use PHP to serve files stored outside the `public/` directory,
from a directory named `private-files/`.
## Configuration
First, add the following configuration to your `Caddyfile` to enable this feature:
```patch
root public/
# ...
+ # Needed for Symfony, Laravel and other projects using the Symfony HttpFoundation component
+ request_header X-Sendfile-Type x-accel-redirect
+ request_header X-Accel-Mapping ../private-files=/private-files
+
+ intercept {
+ @accel header X-Accel-Redirect *
+ handle_response @accel {
+ root private-files/
+ rewrite * {resp.header.X-Accel-Redirect}
+ method * GET
+
+ # Remove the X-Accel-Redirect header set by PHP for increased security
+ header -X-Accel-Redirect
+
+ file_server
+ }
+ }
php_server
```
## Plain PHP
Set the relative file path (from `private-files/`) as the value of the `X-Accel-Redirect` header:
```php
header('X-Accel-Redirect: file.txt');
```
## Projects using the Symfony HttpFoundation component (Symfony, Laravel, Drupal...)
Symfony HttpFoundation [natively supports this feature](https://symfony.com/doc/current/components/http_foundation.html#serving-files).
It will automatically determine the correct value for the `X-Accel-Redirect` header and add it to the response.
```php
use Symfony\Component\HttpFoundation\BinaryFileResponse;
BinaryFileResponse::trustXSendfileTypeHeader();
$response = new BinaryFileResponse(__DIR__.'/../private-files/file.txt');
// ...
```