Skip to content

Commit 22f2032

Browse files
committed
merge
2 parents c1a4576 + 8092f4a commit 22f2032

23 files changed

Lines changed: 196 additions & 60 deletions

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
- name: Run integrations tests
6969
run: ./reload_test.sh
7070
- name: Lint Go code
71-
uses: golangci/golangci-lint-action@v6
71+
uses: golangci/golangci-lint-action@v7
7272
if: matrix.php-versions == '8.4'
7373
with:
7474
version: latest

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ frankenphp php-server
8888
* [Worker mode](https://frankenphp.dev/docs/worker/)
8989
* [Early Hints support (103 HTTP status code)](https://frankenphp.dev/docs/early-hints/)
9090
* [Real-time](https://frankenphp.dev/docs/mercure/)
91+
* [Efficiently Serving Large Static Files](https://frankenphp.dev/docs/x-sendfile/)
9192
* [Configuration](https://frankenphp.dev/docs/config/)
9293
* [Docker images](https://frankenphp.dev/docs/docker/)
9394
* [Deploy in production](https://frankenphp.dev/docs/production/)

build-static.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ if type "brew" >/dev/null 2>&1; then
138138
fi
139139

140140
if [ "${SPC_REL_TYPE}" = "binary" ]; then
141-
mkdir static-php-cli/
141+
mkdir -p static-php-cli/
142142
cd static-php-cli/
143-
curl -o spc -fsSL "https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-$(uname -m)"
143+
curl -o spc -fsSL "https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-${arch}"
144144
chmod +x spc
145145
spcCommand="./spc"
146146
elif [ -d "static-php-cli/src" ]; then

caddy/admin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (admin *FrankenPHPAdmin) restartWorkers(w http.ResponseWriter, r *http.Requ
4444
return nil
4545
}
4646

47-
func (admin *FrankenPHPAdmin) threads(w http.ResponseWriter, r *http.Request) error {
47+
func (admin *FrankenPHPAdmin) threads(w http.ResponseWriter, _ *http.Request) error {
4848
debugState := frankenphp.DebugState()
4949
prettyJson, err := json.MarshalIndent(debugState, "", " ")
5050
if err != nil {

caddy/frankenphp/Caddyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# }
2020
#}
2121

22-
root * public/
22+
root public/
2323
encode zstd br gzip
2424

2525
# Uncomment the following lines to enable Mercure and Vulcain modules

cgi.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func packCgiVariable(key *C.zend_string, value string) C.ht_key_value_pair {
168168
return C.ht_key_value_pair{key, toUnsafeChar(value), C.size_t(len(value))}
169169
}
170170

171-
func addHeadersToServer(thread *phpThread, fc *frankenPHPContext, trackVarsArray *C.zval) {
171+
func addHeadersToServer(fc *frankenPHPContext, trackVarsArray *C.zval) {
172172
for field, val := range fc.request.Header {
173173
if k := mainThread.commonHeaders[field]; k != nil {
174174
v := strings.Join(val, ", ")
@@ -197,7 +197,7 @@ func go_register_variables(threadIndex C.uintptr_t, trackVarsArray *C.zval) {
197197
fc := thread.getRequestContext()
198198

199199
addKnownVariablesToServer(thread, fc, trackVarsArray)
200-
addHeadersToServer(thread, fc, trackVarsArray)
200+
addHeadersToServer(fc, trackVarsArray)
201201

202202
// The Prepared Environment is registered last and can overwrite any previous values
203203
addPreparedEnvToServer(fc, trackVarsArray)

docs/config.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
FrankenPHP, Caddy as well as the Mercure and Vulcain modules can be configured using [the formats supported by Caddy](https://caddyserver.com/docs/getting-started#your-first-config).
44

5-
In [the Docker images](docker.md), the `Caddyfile` is located at `/etc/caddy/Caddyfile`.
6-
The static binary will look for the `Caddyfile` in the directory in which it is started.
5+
In [the Docker images](docker.md), the `Caddyfile` is located at `/etc/caddy/Caddyfile`. The static binary will look for the `Caddyfile` in the directory where the `frankenphp run` command is executed. You can specify a custom path with the `-c` or `--config` option.
76

87
PHP itself can be configured [using a `php.ini` file](https://www.php.net/manual/en/configuration.file.php).
98

@@ -103,7 +102,9 @@ other.example.com {
103102
```
104103

105104
Using the `php_server` directive is generally what you need,
106-
but if you need full control, you can use the lower level `php` directive:
105+
but if you need full control, you can use the lower-level `php` directive.
106+
The `php` directive passes all input to PHP, instead of first checking whether
107+
it's a PHP file or not. Read more about it in the [performance page](performance.md).
107108

108109
Using the `php_server` directive is equivalent to this configuration:
109110

docs/fr/config.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ other.example.com {
104104

105105
L'utilisation de la directive `php_server` est généralement suffisante,
106106
mais si vous avez besoin d'un contrôle total, vous pouvez utiliser la directive `php`, qui permet un plus grand niveau de finesse dans la configuration.
107+
La directive `php` transmet toutes les entrées à PHP, au lieu de vérifier d'abord si
108+
c'est un fichier PHP ou pas. En savoir plus à ce sujet dans la [page performances](performance.md).
107109

108110
Utiliser la directive `php_server` est équivalent à cette configuration :
109111

docs/fr/x-sendfile.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Servir efficacement les gros fichiers statiques (`X-Sendfile`/`X-Accel-Redirect`)
2+
3+
Habituellement, les fichiers statiques peuvent être servis directement par le serveur web,
4+
mais parfois, il est nécessaire d'exécuter du code PHP avant de les envoyer :
5+
contrôle d'accès, statistiques, en-têtes HTTP personnalisés...
6+
7+
Malheureusement, utiliser PHP pour servir de gros fichiers statiques est inefficace comparé à
8+
à l'utilisation directe du serveur web (surcharge mémoire, diminution des performances...).
9+
10+
FrankenPHP permet de déléguer l'envoi des fichiers statiques au serveur web
11+
**après** avoir exécuté du code PHP personnalisé.
12+
13+
Pour ce faire, votre application PHP n'a qu'à définir un en-tête HTTP personnalisé
14+
contenant le chemin du fichier à servir. FrankenPHP se chargera du reste.
15+
16+
Cette fonctionnalité est connue sous le nom de **`X-Sendfile`** pour Apache, et **`X-Accel-Redirect`** pour NGINX.
17+
18+
Dans les exemples suivants, nous supposons que le "document root" du projet est le répertoire `public/`
19+
et que nous voulons utiliser PHP pour servir des fichiers stockés en dehors du dossier `public/`,
20+
depuis un répertoire nommé `private-files/`.
21+
22+
## Configuration
23+
24+
Tout d'abord, ajoutez la configuration suivante à votre `Caddyfile` pour activer cette fonctionnalité :
25+
26+
```patch
27+
root public/
28+
# ...
29+
30+
+ # Needed for Symfony, Laravel and other projects using the Symfony HttpFoundation component
31+
+ request_header X-Sendfile-Type x-accel-redirect
32+
+ request_header X-Accel-Mapping ../private-files=/private-files
33+
+
34+
+ intercept {
35+
+ @accel header X-Accel-Redirect *
36+
+ handle_response @accel {
37+
+ root private-files/
38+
+ rewrite * {resp.header.X-Accel-Redirect}
39+
+ method * GET
40+
+
41+
+ # Remove the X-Accel-Redirect header set by PHP for increased security
42+
+ header -X-Accel-Redirect
43+
+
44+
+ file_server
45+
+ }
46+
+ }
47+
48+
php_server
49+
```
50+
51+
## PHP simple
52+
53+
Définissez le chemin relatif du fichier (à partir de `private-files/`) comme valeur de l'en-tête `X-Accel-Redirect` :
54+
55+
```php
56+
header('X-Accel-Redirect: file.txt') ;
57+
```
58+
59+
## Projets utilisant le composant Symfony HttpFoundation (Symfony, Laravel, Drupal...)
60+
61+
Symfony HttpFoundation [supporte nativement cette fonctionnalité](https://symfony.com/doc/current/components/http_foundation.html#serving-files).
62+
Il va automatiquement déterminer la bonne valeur pour l'en-tête `X-Accel-Redirect` et l'ajoutera à la réponse.
63+
64+
```php
65+
use Symfony\Component\HttpFoundation\BinaryFileResponse;
66+
67+
BinaryFileResponse::trustXSendfileTypeHeader();
68+
$response = new BinaryFileResponse(__DIR__.'/../private-files/file.txt');
69+
70+
// ...
71+
```

docs/x-sendfile.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Efficiently Serving Large Static Files (`X-Sendfile`/`X-Accel-Redirect`)
2+
3+
Usually, static files can be served directly by the web server,
4+
but sometimes it's necessary to execute some PHP code before sending them:
5+
access control, statistics, custom HTTP headers...
6+
7+
Unfortunately, using PHP to serve large static files is inefficient compared to
8+
direct use of the web server (memory overload, reduced performance...).
9+
10+
FrankenPHP lets you delegate the sending of static files to the web server
11+
**after** executing customized PHP code.
12+
13+
To do this, your PHP application simply needs to define a custom HTTP header
14+
containing the path of the file to be served. FrankenPHP takes care of the rest.
15+
16+
This feature is known as **`X-Sendfile`** for Apache, and **`X-Accel-Redirect`** for NGINX.
17+
18+
In the following examples, we assume that the document root of the project is the `public/` directory.
19+
and that we want to use PHP to serve files stored outside the `public/` directory,
20+
from a directory named `private-files/`.
21+
22+
## Configuration
23+
24+
First, add the following configuration to your `Caddyfile` to enable this feature:
25+
26+
```patch
27+
root public/
28+
# ...
29+
30+
+ # Needed for Symfony, Laravel and other projects using the Symfony HttpFoundation component
31+
+ request_header X-Sendfile-Type x-accel-redirect
32+
+ request_header X-Accel-Mapping ../private-files=/private-files
33+
+
34+
+ intercept {
35+
+ @accel header X-Accel-Redirect *
36+
+ handle_response @accel {
37+
+ root private-files/
38+
+ rewrite * {resp.header.X-Accel-Redirect}
39+
+ method * GET
40+
+
41+
+ # Remove the X-Accel-Redirect header set by PHP for increased security
42+
+ header -X-Accel-Redirect
43+
+
44+
+ file_server
45+
+ }
46+
+ }
47+
48+
php_server
49+
```
50+
51+
## Plain PHP
52+
53+
Set the relative file path (from `private-files/`) as the value of the `X-Accel-Redirect` header:
54+
55+
```php
56+
header('X-Accel-Redirect: file.txt');
57+
```
58+
59+
## Projects using the Symfony HttpFoundation component (Symfony, Laravel, Drupal...)
60+
61+
Symfony HttpFoundation [natively supports this feature](https://symfony.com/doc/current/components/http_foundation.html#serving-files).
62+
It will automatically determine the correct value for the `X-Accel-Redirect` header and add it to the response.
63+
64+
```php
65+
use Symfony\Component\HttpFoundation\BinaryFileResponse;
66+
67+
BinaryFileResponse::trustXSendfileTypeHeader();
68+
$response = new BinaryFileResponse(__DIR__.'/../private-files/file.txt');
69+
70+
// ...
71+
```

0 commit comments

Comments
 (0)