echo: module Echo de nginx
Installation
Vous pouvez installer ce module dans n'importe quelle distribution basée sur RHEL, y compris, mais sans s'y limiter :
- RedHat Enterprise Linux 7, 8, 9 et 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 et Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-echo
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-echo
Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :
load_module modules/ngx_http_echo_module.so;
Ce document décrit nginx-module-echo v0.65 publié le 07 juin 2026.
location /hello {
echo "hello, world!";
}
location /hello {
echo -n "hello, ";
echo "world!";
}
location /timed_hello {
echo_reset_timer;
echo hello world;
echo "'hello world' takes about $echo_timer_elapsed sec.";
echo hiya igor;
echo "'hiya igor' takes about $echo_timer_elapsed sec.";
}
location /echo_with_sleep {
echo hello;
echo_flush; # assurez-vous que le client peut voir la sortie précédente immédiatement
echo_sleep 2.5; # en sec
echo world;
}
# dans l'exemple suivant, accéder à /echo donne
# hello
# world
# blah
# hiya
# igor
location /echo {
echo_before_body hello;
echo_before_body world;
proxy_pass $scheme://127.0.0.1:$server_port$request_uri/more;
echo_after_body hiya;
echo_after_body igor;
}
location /echo/more {
echo blah;
}
# la sortie de /main pourrait être
# hello
# world
# took 0.000 sec for total.
# et toute la requête prendrait environ 2 sec pour se terminer.
location /main {
echo_reset_timer;
# sous-requêtes en parallèle
echo_location_async /sub1;
echo_location_async /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 2;
echo hello;
}
location /sub2 {
echo_sleep 1;
echo world;
}
# la sortie de /main pourrait être
# hello
# world
# took 3.003 sec for total.
# et toute la requête prendrait environ 3 sec pour se terminer.
location /main {
echo_reset_timer;
# sous-requêtes en série (chaînées par CPS)
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 2;
echo hello;
}
location /sub2 {
echo_sleep 1;
echo world;
}
# Accéder à /dup donne
# ------ END ------
location /dup {
echo_duplicate 3 "--";
echo_duplicate 1 " END ";
echo_duplicate 3 "--";
echo;
}
# /bighello générera 1000,000,000 hello's.
location /bighello {
echo_duplicate 1000_000_000 'hello';
}
# renvoie la requête du client
location /echoback {
echo_duplicate 1 $echo_client_request_headers;
echo "\r";
echo_read_request_body;
echo_request_body;
}
# GET /multi donnera
# querystring: foo=Foo
# method: POST
# body: hi
# content length: 2
# ///
# querystring: bar=Bar
# method: PUT
# body: hello
# content length: 5
# ///
location /multi {
echo_subrequest_async POST '/sub' -q 'foo=Foo' -b 'hi';
echo_subrequest_async PUT '/sub' -q 'bar=Bar' -b 'hello';
}
location /sub {
echo "querystring: $query_string";
echo "method: $echo_request_method";
echo "body: $echo_request_body";
echo "content length: $http_content_length";
echo '///';
}
# GET /merge?/foo.js&/bar/blah.js&/yui/baz.js fusionnera les ressources .js ensemble
location /merge {
default_type 'text/javascript';
echo_foreach_split '&' $query_string;
echo "/* JS File $echo_it */";
echo_location_async $echo_it;
echo;
echo_end;
}
# accéder à /if?val=abc donne la sortie "hit"
# tandis que /if?val=bcd donne "miss":
location ^~ /if {
set $res miss;
if ($arg_val ~* '^a') {
set $res hit;
echo $res;
}
echo $res;
}
Description
Ce module enveloppe de nombreuses API internes de Nginx pour le streaming d'entrée et de sortie, les sous-requêtes parallèles/séquentielles, les minuteries et le sommeil, ainsi que divers accès aux métadonnées.
Fondamentalement, il fournit divers utilitaires qui aident à tester et déboguer d'autres modules en émule trivialement différents types de localisations de sous-requêtes fictives.
Les gens le trouveront également utile dans des applications réelles qui ont besoin de
- servir des contenus statiques directement depuis la mémoire (chargement à partir du fichier de configuration Nginx).
- envelopper la réponse en amont avec un en-tête et un pied de page personnalisés (un peu comme le module addition mais avec des contenus lus directement à partir du fichier de configuration et des variables Nginx).
- fusionner les contenus de diverses "localisations Nginx" (c'est-à-dire, sous-requêtes) ensemble dans une seule requête principale (en utilisant echo_location et ses amis).
C'est un module à double rôle spécial qui peut paresseusement servir de gestionnaire de contenu ou s'enregistrer comme un filtre de sortie uniquement sur demande. Par défaut, ce module ne fait rien du tout.
Techniquement, ce module a également démontré les techniques suivantes qui pourraient être utiles pour les écrivains de modules :
- Émettre des sous-requêtes parallèles directement depuis le gestionnaire de contenu.
- Émettre des sous-requêtes chaînées directement depuis le gestionnaire de contenu, en passant la continuation le long de la chaîne de sous-requête.
- Émettre des sous-requêtes avec toutes les méthodes HTTP 1.1 et même un corps de requête HTTP fictif optionnel.
- Interagir avec le modèle d'événements Nginx directement depuis le gestionnaire de contenu en utilisant des événements et des minuteries personnalisés, et reprendre le gestionnaire de contenu si nécessaire.
- Module à double rôle qui peut (paresseusement) servir de gestionnaire de contenu ou de filtre de sortie ou les deux.
- Création et interpolation de variables de fichier de configuration Nginx.
- Contrôle de sortie en streaming utilisant output_chain, flush et ses amis.
- Lire le corps de la requête client depuis le gestionnaire de contenu, et revenir (asynchrone) au gestionnaire de contenu après achèvement.
- Utiliser une suite de tests déclarative basée sur Perl test suite pour conduire le développement des modules C de Nginx.
Directives du gestionnaire de contenu
L'utilisation des directives suivantes enregistre ce module dans la localisation Nginx actuelle en tant que gestionnaire de contenu. Si vous souhaitez utiliser un autre module, comme le module proxy standard, en tant que gestionnaire de contenu, utilisez les directives de filtre fournies par ce module.
Toutes les directives de gestionnaire de contenu peuvent être mélangées dans une seule localisation Nginx et elles sont censées s'exécuter séquentiellement tout comme dans le langage de script Bash.
Chaque directive de gestionnaire de contenu prend en charge l'interpolation de variables dans ses arguments (le cas échéant).
Le type MIME défini par la directive standard default_type est respecté par ce module, comme dans :
location /hello {
default_type text/plain;
echo hello;
}
Ensuite, du côté client :
$ curl -I 'http://localhost/echo'
HTTP/1.1 200 OK
Server: nginx/0.8.20
Date: Sat, 17 Oct 2009 03:40:19 GMT
Content-Type: text/plain
Connection: keep-alive
Depuis la version v0.22, toutes les directives sont autorisées dans le bloc de directive if du module de réécriture, par exemple :
location ^~ /if {
set $res miss;
if ($arg_val ~* '^a') {
set $res hit;
echo $res;
}
echo $res;
}
echo
syntax: echo [options] <string>...
default: non
context: location, location if
phase: contenu
Envoie des arguments séparés par des espaces, avec une nouvelle ligne à la fin, au client.
Notez que les données peuvent être mises en mémoire tampon par le tampon sous-jacent de Nginx. Pour forcer la sortie des données à être vidée immédiatement, utilisez la commande echo_flush juste après echo, comme dans
echo hello world;
echo_flush;
Lorsque aucun argument n'est spécifié, echo émet uniquement la nouvelle ligne finale, tout comme la commande echo dans le shell.
Des variables peuvent apparaître dans les arguments. Un exemple est
echo The current request uri is $request_uri;
où $request_uri est une variable exposée par le ngx_http_core_module.
Cette commande peut être utilisée plusieurs fois dans une seule configuration de localisation, comme dans
location /echo {
echo hello;
echo world;
}
La sortie du côté client ressemble à ceci
$ curl 'http://localhost/echo'
hello
world
Des caractères spéciaux comme des nouvelles lignes (\n) et des tabulations (\t) peuvent être échappés en utilisant des séquences d'échappement de style C. Mais une exception notable est le signe dollar ($). Depuis Nginx 0.8.20, il n'y a toujours pas de moyen propre d'échapper à ce caractère. (Une solution de contournement pourrait être d'utiliser une variable $echo_dollor qui est toujours évaluée à la constante $. Cette fonctionnalité sera probablement introduite dans une version future de ce module.)
Depuis la version echo v0.28, on peut supprimer le caractère de nouvelle ligne final dans la sortie en utilisant l'option -n, comme dans
location /echo {
echo -n "hello, ";
echo "world";
}
Accéder à /echo donne
$ curl 'http://localhost/echo'
hello, world
Les -n en tête dans les valeurs de variable ne prendront pas effet et seront émis littéralement, comme dans
location /echo {
set $opt -n;
echo $opt "hello,";
echo "world";
}
Cela donne la sortie suivante
$ curl 'http://localhost/echo'
-n hello,
world
On peut émettre des littéraux -n en tête et d'autres options en utilisant l'option spéciale -- comme ceci
location /echo {
echo -- -n is an option;
}
ce qui donne
$ curl 'http://localhost/echo'
-n is an option
Utilisez cette forme lorsque vous souhaitez émettre quoi que ce soit commençant par un tiret (-).
echo_duplicate
syntax: echo_duplicate <count> <string>
default: non
context: location, location if
phase: contenu
Sort une duplication d'une chaîne indiquée par le deuxième argument, en utilisant le compte spécifié dans le premier argument.
Par exemple,
location /dup {
echo_duplicate 3 "abc";
}
produira la sortie de "abcabcabc".
Les traits de soulignement sont autorisés dans le nombre de compte, tout comme en Perl. Par exemple, pour émettre 1000,000,000 instances de "hello, world" :
location /many_hellos {
echo_duplicate 1000_000_000 "hello, world";
}
L'argument count pourrait être zéro, mais pas négatif. Le deuxième argument string pourrait également être une chaîne vide ("").
Contrairement à la directive echo, aucune nouvelle ligne finale n'est ajoutée au résultat. Il est donc possible de "mal utiliser" cette directive comme une version sans nouvelle ligne finale de echo en utilisant "count" 1, comme dans
location /echo_art {
echo_duplicate 2 '---';
echo_duplicate 1 ' END '; # nous ne voulons pas de nouvelle ligne finale ici
echo_duplicate 2 '---';
echo; # nous voulons une nouvelle ligne finale ici...
}
Vous obtenez
------ END ------
Mais l'utilisation de l'option -n dans echo est plus appropriée à cet effet.
Cette directive a été introduite pour la première fois dans version 0.11.
echo_flush
syntax: echo_flush
default: non
context: location, location if
phase: contenu
Force les données potentiellement mises en mémoire tampon par les filtres de sortie sous-jacents de Nginx à être envoyées immédiatement au client via le socket.
Notez que techniquement, la commande émet simplement un objet ngx_buf_t avec le slot flush défini sur 1, donc certains modules de filtre de sortie tiers étranges pourraient toujours le bloquer avant qu'il n'atteigne le filtre d'écriture (dernier) de Nginx.
Cette directive ne prend aucun argument.
Considérez l'exemple suivant :
location /flush {
echo hello;
echo_flush;
echo_sleep 1;
echo world;
}
Ensuite, du côté client, en utilisant curl pour accéder à /flush, vous verrez la ligne "hello" immédiatement, mais seulement après 1 seconde, la dernière ligne "world". Sans appeler echo_flush dans l'exemple ci-dessus, vous ne verrez probablement aucune sortie avant que 1 seconde ne se soit écoulée en raison de la mise en mémoire tampon interne de Nginx.
Cette directive échouera à vider le tampon de sortie en cas de sous-requêtes impliquées. Considérez l'exemple suivant :
location /main {
echo_location_async /sub;
echo hello;
echo_flush;
}
location /sub {
echo_sleep 1;
}
Alors le client ne verra pas "hello" apparaître même si echo_flush a été exécuté avant que la sous-requête vers /sub ait réellement commencé à s'exécuter. Les sorties de /main qui sont envoyées après echo_location_async seront reportées et fermement mises en mémoire tampon.
Cela ne s'applique pas aux sorties envoyées avant l'initiation de la sous-requête. Pour une version modifiée de l'exemple donné ci-dessus :
location /main {
echo hello;
echo_flush;
echo_location_async /sub;
}
location /sub {
echo_sleep 1;
}
Le client verra immédiatement "hello" avant que /sub n'entre en sommeil.
Voir aussi echo, echo_sleep, et echo_location_async.
echo_sleep
syntax: echo_sleep <seconds>
default: non
context: location, location if
phase: contenu
S'endort pendant la période de temps spécifiée par l'argument, qui est en secondes.
Cette opération est non-bloquante côté serveur, donc contrairement à la directive echo_blocking_sleep, elle ne bloquera pas tout le processus de travail Nginx.
La période peut prendre trois chiffres après la virgule et doit être supérieure à 0.001.
Un exemple est
location /echo_after_sleep {
echo_sleep 1.234;
echo resumed!;
}
En coulisses, cela configure un objet "sleep" ngx_event_t par requête, et ajoute un minuteur en utilisant cet événement personnalisé au modèle d'événements Nginx et attend simplement un délai d'expiration sur cet événement. Parce que l'événement "sleep" est par requête, cette directive peut fonctionner dans des sous-requêtes parallèles.
echo_blocking_sleep
syntax: echo_blocking_sleep <seconds>
default: non
context: location, location if
phase: contenu
C'est une version bloquante de la directive echo_sleep.
Voir la documentation de echo_sleep pour plus de détails.
Derrière le rideau, elle appelle la macro ngx_msleep fournie par le noyau Nginx qui se mappe à usleep sur les systèmes conformes à POSIX.
Notez que cette directive bloquera complètement le processus de travail Nginx actuel pendant son exécution, donc ne l'utilisez jamais dans un environnement de production.
echo_reset_timer
syntax: echo_reset_timer
default: non
context: location, location if
phase: contenu
Réinitialise le temps de début du minuteur à maintenant, c'est-à-dire, le temps lorsque cette commande est exécutée pendant la requête.
Le temps de début du minuteur est par défaut le temps de début de la requête actuelle et peut être remplacé par cette directive, potentiellement plusieurs fois dans une seule localisation. Par exemple :
location /timed_sleep {
echo_sleep 0.03;
echo "$echo_timer_elapsed sec elapsed.";
echo_reset_timer;
echo_sleep 0.02;
echo "$echo_timer_elapsed sec elapsed.";
}
La sortie du côté client pourrait être
$ curl 'http://localhost/timed_sleep'
0.032 sec elapsed.
0.020 sec elapsed.
Les chiffres réels que vous obtenez de votre côté peuvent varier un peu en raison des activités actuelles de votre système.
L'invocation de cette directive forcera le minuteur sous-jacent de Nginx à se mettre à jour à l'heure système actuelle (indépendamment de la résolution du minuteur spécifiée ailleurs dans le fichier de configuration). De plus, les références de la variable $echo_timer_elapsed déclencheront également une mise à jour forcée du minuteur.
Voir aussi echo_sleep et $echo_timer_elapsed.
echo_read_request_body
syntax: echo_read_request_body
default: non
context: location, location if
phase: contenu
Lit explicitement le corps de la requête afin que la variable $request_body ait toujours des valeurs non vides (sauf si le corps est si volumineux qu'il a été enregistré par Nginx dans un fichier temporaire local).
Notez que cela pourrait ne pas être le corps de requête d'origine du client car la requête actuelle pourrait être une sous-requête avec un corps "artificiel" spécifié par son parent.
Cette directive ne génère aucune sortie elle-même, tout comme echo_sleep.
Voici un exemple pour renvoyer la requête HTTP d'origine du client (les en-têtes et le corps sont inclus) :
location /echoback {
echo_duplicate 1 $echo_client_request_headers;
echo "\r";
echo_read_request_body;
echo $request_body;
}
Le contenu de /echoback ressemble à ceci de mon côté (j'utilisais l'utilitaire LWP de Perl pour accéder à cette localisation sur le serveur) :
$ (echo hello; echo world) | lwp-request -m POST 'http://localhost/echoback'
POST /echoback HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: lwp-request/5.818 libwww-perl/5.820
Content-Length: 12
Content-Type: application/x-www-form-urlencoded
hello
world
Parce que /echoback est la requête principale, $request_body contient le corps de requête d'origine du client.
Avant Nginx 0.7.56, il n'avait aucun sens d'utiliser cette directive car $request_body a été introduit pour la première fois dans Nginx 0.7.58.
Cette directive elle-même a été introduite pour la première fois dans la version v0.14 du module echo.
echo_location_async
syntax: echo_location_async <location> [<url_args>]
default: non
context: location, location if
phase: contenu
Émet une sous-requête GET à la localisation spécifiée (premier argument) avec des arguments d'URL optionnels spécifiés dans le deuxième argument.
Depuis Nginx 0.8.20, l'argument location ne prend pas en charge les localisations nommées, en raison d'une limitation dans la fonction ngx_http_subrequest. Il en va de même pour son frère, la directive echo_location.
Un exemple très simple est
location /main {
echo_location_async /sub;
echo world;
}
location /sub {
echo hello;
}
Accéder à /main donne
hello
world
Appeler plusieurs localisations en parallèle est également possible :
location /main {
echo_reset_timer;
echo_location_async /sub1;
echo_location_async /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 2; # dort 2 sec
echo hello;
}
location /sub2 {
echo_sleep 1; # dort 1 sec
echo world;
}
Accéder à /main donne
$ time curl 'http://localhost/main'
hello
world
took 0.000 sec for total.
real 0m2.006s
user 0m0.000s
sys 0m0.004s
Vous pouvez voir que le gestionnaire principal /main ne attend pas que les sous-requêtes /sub1 et /sub2 se terminent et continue rapidement, d'où le résultat de timing "0.000 sec". Cependant, toute la requête prend environ 2 sec au total pour se terminer car /sub1 et /sub2 s'exécutent en parallèle (ou "concurremment" pour être plus précis).
Si vous utilisez echo_blocking_sleep dans l'exemple précédent à la place, vous obtiendrez la même sortie, mais avec un temps de réponse total de 3 sec, car "le sommeil bloquant" bloque tout le processus de travail Nginx.
Les localisations peuvent également prendre un argument de chaîne de requête optionnel, par exemple
location /main {
echo_location_async /sub 'foo=Foo&bar=Bar';
}
location /sub {
echo $arg_foo $arg_bar;
}
Accéder à /main donne
$ curl 'http://localhost/main'
Foo Bar
Les chaînes de requête ne peuvent pas être concaténées à l'argument location avec "?" directement, par exemple, /sub?foo=Foo&bar=Bar est une localisation invalide et ne devrait pas être fournie comme premier argument à cette directive.
Techniquement parlant, cette directive est un exemple que le gestionnaire de contenu Nginx émet une ou plusieurs sous-requêtes directement. A ma connaissance, le module fancyindex fait également ce genre de choses ;)
Les localisations nommées Nginx comme @foo ne sont pas prises en charge ici.
Cette directive est logiquement équivalente à la version GET de echo_subrequest_async. Par exemple,
echo_location_async /foo 'bar=Bar';
est logiquement équivalent à
echo_subrequest_async GET /foo -q 'bar=Bar';
Mais appeler cette directive est légèrement plus rapide que d'appeler echo_subrequest_async en utilisant GET car nous n'avons pas à analyser les noms de méthodes HTTP comme GET et les options comme -q.
Cette directive a été introduite pour la première fois dans version 0.09 de ce module et nécessite au moins Nginx 0.7.46.
echo_location
syntax: echo_location <location> [<url_args>]
default: non
context: location, location if
phase: contenu
Tout comme la directive echo_location_async, mais echo_location émet des sous-requêtes en série plutôt qu'en parallèle. C'est-à-dire que les directives de gestionnaire de contenu suivant cette directive ne seront pas exécutées tant que la sous-requête émise par cette directive n'est pas terminée.
Le corps de réponse final est presque toujours équivalent au cas où echo_location_async est utilisé à la place, uniquement si des variables de timing sont utilisées dans les sorties.
Considérez l'exemple suivant :
location /main {
echo_reset_timer;
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 2;
echo hello;
}
location /sub2 {
echo_sleep 1;
echo world;
}
La localisation /main ci-dessus prendra au total 3 sec pour se compléter (comparé à 2 sec si echo_location_async est utilisé à la place ici). Voici le résultat en action sur ma machine :
$ curl 'http://localhost/main'
hello
world
took 3.003 sec for total.
real 0m3.027s
user 0m0.020s
sys 0m0.004s
Cette directive est logiquement équivalente à la version GET de echo_subrequest. Par exemple,
echo_location /foo 'bar=Bar';
est logiquement équivalent à
echo_subrequest GET /foo -q 'bar=Bar';
Mais appeler cette directive est légèrement plus rapide que d'appeler echo_subrequest en utilisant GET car nous n'avons pas à analyser les noms de méthodes HTTP comme GET et les options comme -q.
Derrière le rideau, elle crée un objet ngx_http_post_subrequest_t en tant que continuation et le passe à l'appel de fonction ngx_http_subrequest. Nginx rouvrira plus tard cette "continuation" dans l'appel de fonction ngx_http_finalize_request de la sous-requête. Nous reprenons l'exécution du gestionnaire de contenu de la requête principale et commençons à exécuter la directive suivante (commande) s'il y en a.
Les localisations nommées Nginx comme @foo ne sont pas prises en charge ici.
Cette directive a été introduite pour la première fois dans la version v0.12.
Voir aussi echo_location_async pour plus de détails sur la signification des arguments.
echo_subrequest_async
syntax: echo_subrequest_async <HTTP_method> <location> [-q <url_args>] [-b <request_body>] [-f <request_body_path>]
default: non
context: location, location if
phase: contenu
Initie une sous-requête asynchrone en utilisant la méthode HTTP, des arguments d'URL optionnels (ou chaîne de requête) et un corps de requête optionnel qui peut être défini comme une chaîne ou comme un chemin vers un fichier contenant le corps.
Cette directive est très similaire à une version généralisée de la directive echo_location_async.
Voici un petit exemple démontrant son utilisation :
location /multi {
# corps défini comme chaîne
echo_subrequest_async POST '/sub' -q 'foo=Foo' -b 'hi';
# corps défini comme chemin vers un fichier, relatif au chemin de préfixe nginx s'il n'est pas absolu
echo_subrequest_async PUT '/sub' -q 'bar=Bar' -f '/tmp/hello.txt';
}
location /sub {
echo "querystring: $query_string";
echo "method: $echo_request_method";
echo "body: $echo_request_body";
echo "content length: $http_content_length";
echo '///';
}
Ensuite, du côté client :
$ echo -n hello > /tmp/hello.txt
$ curl 'http://localhost/multi'
querystring: foo=Foo
method: POST
body: hi
content length: 2
///
querystring: bar=Bar
method: PUT
body: hello
content length: 5
///
Voici un exemple plus amusant utilisant le module proxy standard proxy module pour gérer la sous-requête :
location /main {
echo_subrequest_async POST /sub -b 'hello, world';
}
location /sub {
proxy_pass $scheme://127.0.0.1:$server_port/proxied;
}
location /proxied {
echo "method: $echo_request_method.";
# nous devons lire le corps ici explicitement... sinon $echo_request_body
# sera évalué à vide ("")
echo_read_request_body;
echo "body: $echo_request_body.";
}
Ensuite, du côté client, nous pouvons voir que
$ curl 'http://localhost/main'
method: POST.
body: hello, world.
Les localisations nommées Nginx comme @foo ne sont pas prises en charge ici.
Cette directive prend plusieurs options :
-q <url_args> Spécifiez les arguments d'URL (ou chaîne de requête) pour la sous-requête.
-f <path> Spécifiez le chemin pour le fichier dont le contenu servira de corps de requête de la sous-requête.
-b <data> Spécifiez les données du corps de la requête.
Cette directive a été introduite pour la première fois dans la version v0.15.
L'option -f pour définir un chemin de fichier pour le corps a été introduite dans la version v0.35.
Voir aussi les directives echo_subrequest et echo_location_async.
echo_subrequest
syntax: echo_subrequest <HTTP_method> <location> [-q <url_args>] [-b <request_body>] [-f <request_body_path>]
default: non
context: location, location if
phase: contenu
C'est la version synchrone de la directive echo_subrequest_async. Et tout comme echo_location, elle ne bloque pas le processus de travail Nginx (tandis que echo_blocking_sleep le fait), mais utilise plutôt une continuation pour passer le contrôle le long de la chaîne de sous-requête.
Voir echo_subrequest_async pour plus de détails.
Les localisations nommées Nginx comme @foo ne sont pas prises en charge ici.
Cette directive a été introduite pour la première fois dans la version v0.15.
echo_foreach_split
syntax: echo_foreach_split <delimiter> <string>
default: non
context: location, location if
phase: contenu
Divise le deuxième argument string en utilisant le délimiteur spécifié dans le premier argument, puis itère à travers les éléments résultants. Par exemple :
location /loop {
echo_foreach_split ',' $arg_list;
echo "item: $echo_it";
echo_end;
}
Accéder à /main donne
$ curl 'http://localhost/loop?list=cat,dog,mouse'
item: cat
item: dog
item: mouse
Comme vu dans l'exemple précédent, cette directive doit toujours être accompagnée d'une directive echo_end.
Des boucles echo_foreach_split parallèles sont autorisées, mais des boucles imbriquées sont actuellement interdites.
L'argument delimiter pourrait contenir plusieurs caractères arbitraires, comme
# cela produit "cat\ndog\nmouse\n"
echo_foreach_split -- '-a-' 'cat-a-dog-a-mouse';
echo $echo_it;
echo_end;
Logiquement parlant, cette structure de boucle est juste la boucle foreach combinée avec un appel de fonction split en Perl (en utilisant l'exemple précédent) :
foreach (split ',', $arg_list) {
print "item $_\n";
}
Les gens le trouveront également utile pour fusionner plusieurs ressources .js ou .css en un tout. Voici un exemple :
location /merge {
default_type 'text/javascript';
echo_foreach_split '&' $query_string;
echo "/* JS File $echo_it */";
echo_location_async $echo_it;
echo;
echo_end;
}
Ensuite, accéder à /merge pour fusionner les ressources .js spécifiées dans la chaîne de requête :
$ curl 'http://localhost/merge?/foo/bar.js&/yui/blah.js&/baz.js'
On peut également utiliser un module de cache Nginx tiers pour mettre en cache la réponse fusionnée générée par la localisation /merge dans l'exemple précédent.
Cette directive a été introduite pour la première fois dans la version v0.17.
echo_end
syntax: echo_end
default: non
context: location, location if
phase: contenu
Cette directive est utilisée pour terminer le corps des structures de contrôle de boucle et conditionnelles comme echo_foreach_split.
Cette directive a été introduite pour la première fois dans la version v0.17.
echo_request_body
syntax: echo_request_body
default: non
context: location, location if
phase: contenu
Sort le contenu du corps de la requête précédemment lu.
Derrière le rideau, il est implémenté à peu près comme ceci :
if (r->request_body && r->request_body->bufs) {
return ngx_http_output_filter(r, r->request_body->bufs);
}
Contrairement aux variables $echo_request_body et $request_body, cette directive affichera l'intégralité du corps de la requête même si certaines parties ou toutes les parties ont été enregistrées dans des fichiers temporaires sur le disque.
C'est une "no-op" si aucun corps de requête n'a encore été lu.
Cette directive a été introduite pour la première fois dans la version v0.18.
Voir aussi echo_read_request_body et le module chunkin.
echo_exec
syntax: echo_exec <location> [<query_string>]
syntax: echo_exec <named_location>
default: non
context: location, location if
phase: contenu
Effectue une redirection interne vers la localisation spécifiée. Une chaîne de requête optionnelle peut être spécifiée pour les localisations normales, comme dans
location /foo {
echo_exec /bar weight=5;
}
location /bar {
echo $arg_weight;
}
Ou équivalemment
location /foo {
echo_exec /bar?weight=5;
}
location /bar {
echo $arg_weight;
}
Les localisations nommées sont également prises en charge. Voici un exemple :
location /foo {
echo_exec @bar;
}
location @bar {
# vous obtiendrez /foo plutôt que @bar
# en raison d'un bug potentiel dans nginx.
echo $echo_request_uri;
}
Mais la chaîne de requête (le cas échéant) sera toujours ignorée pour les redirections de localisation nommée en raison d'une limitation dans la fonction ngx_http_named_location.
N'essayez jamais d'émettre des choses avant la directive echo_exec ou vous ne verrez pas la réponse appropriée de la localisation vers laquelle vous souhaitez rediriger. Parce que toute émission fera en sorte que le gestionnaire de localisation d'origine envoie des en-têtes HTTP avant que la redirection ne se produise.
Techniquement parlant, cette directive expose les fonctions API internes de Nginx ngx_http_internal_redirect et ngx_http_named_location.
Cette directive a été introduite pour la première fois dans la version v0.21.
echo_status
syntax: echo_status <status-num>
default: echo_status 200
context: location, location if
phase: contenu
Spécifie le code de statut de réponse par défaut. Par défaut à 200. Cette directive est déclarative et l'ordre relatif avec d'autres directives de type echo n'est pas important.
Voici un exemple,
location = /bad {
echo_status 404;
echo "Something is missing...";
}
alors nous obtenons une réponse comme ceci :
HTTP/1.1 404 Not Found
Server: nginx/1.2.1
Date: Sun, 24 Jun 2012 03:58:18 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
Something is missing...
Cette directive a été introduite pour la première fois dans la version v0.40.
Directives de filtre
L'utilisation des directives suivantes déclenche l'enregistrement de filtre de ce module. Par défaut, aucun filtre ne sera enregistré par ce module.
Chaque directive de filtre prend en charge l'interpolation de variables dans ses arguments (le cas échéant).
echo_before_body
syntax: echo_before_body [options] [argument]...
default: non
context: location, location if
phase: filtre de sortie
C'est la version filtre de la directive echo, et préfixe sa sortie au début des sorties d'origine générées par le gestionnaire de contenu sous-jacent.
Un exemple est
location /echo {
echo_before_body hello;
proxy_pass $scheme://127.0.0.1:$server_port$request_uri/more;
}
location /echo/more {
echo world
}
Accéder à /echo depuis le côté client donne
hello
world
Dans l'exemple précédent, nous empruntons le module proxy standard pour servir de gestionnaire de contenu sous-jacent qui génère les "contenus principaux".
Plusieurs instances de cette directive de filtre sont également autorisées, comme dans :
location /echo {
echo_before_body hello;
echo_before_body world;
echo !;
}
Du côté client, la sortie est comme
$ curl 'http://localhost/echo'
hello
world
!
Dans cet exemple, nous utilisons également les directives de gestionnaire de contenu fournies par ce module comme gestionnaire de contenu sous-jacent.
Cette directive prend également en charge les options -n et -- comme la directive echo.
Cette directive peut être mélangée avec sa directive sœur echo_after_body.
echo_after_body
syntax: echo_after_body [argument]...
default: non
context: location, location if
phase: filtre de sortie
C'est très similaire à la directive echo_before_body, mais ajoute sa sortie à la fin des sorties d'origine générées par le gestionnaire de contenu sous-jacent.
Voici un exemple simple :
location /echo {
echo_after_body hello;
proxy_pass http://127.0.0.1:$server_port$request_uri/more;
}
location /echo/more {
echo world
}
Accéder à /echo depuis le côté client donne
world
hello
Plusieurs instances sont autorisées, comme dans :
location /echo {
echo_after_body hello;
echo_after_body world;
echo i;
echo say;
}
La sortie du côté client lors de l'accès à la localisation /echo ressemble à
i
say
hello
world
Cette directive prend également en charge les options -n et -- comme la directive echo.
Cette directive peut être mélangée avec sa directive sœur echo_before_body.
Variables
$echo_it
C'est une "variable de sujet" utilisée par echo_foreach_split, tout comme la variable $_ en Perl.
$echo_timer_elapsed
Cette variable contient les secondes écoulées depuis le début de la requête actuelle (peut être une sous-requête cependant) ou la dernière invocation de la commande echo_reset_timer.
Le résultat de timing prend trois chiffres après la virgule.
Les références de cette variable forceront le minuteur sous-jacent de Nginx à se mettre à jour à l'heure système actuelle, indépendamment des paramètres de résolution du minuteur ailleurs dans le fichier de configuration, tout comme la directive echo_reset_timer.
$echo_request_body
Évalue à l'actuel corps de requête (sous)requête précédemment lu si aucune partie du corps n'a été enregistrée dans un fichier temporaire. Pour toujours afficher le corps de la requête même s'il est très volumineux, utilisez la directive echo_request_body.
$echo_request_method
Évalue à la méthode de requête HTTP de la requête actuelle (cela peut être une sous-requête).
Derrière le rideau, cela prend simplement les données de chaîne stockées dans r->method_name.
Comparez-le à la variable $echo_client_request_method.
Au moins pour Nginx 0.8.20 et plus ancien, la variable $request_method fournie par le module de base http fait en réalité ce que notre $echo_client_request_method fait.
Cette variable a été introduite pour la première fois dans notre version v0.15.
$echo_client_request_method
Évalue toujours à la méthode HTTP de la requête principale même si la requête actuelle est une sous-requête.
Derrière le rideau, cela prend simplement les données de chaîne stockées dans r->main->method_name.
Comparez-le à la variable $echo_request_method.
Cette variable a été introduite pour la première fois dans notre version v0.15.
$echo_client_request_headers
Évalue à l'en-tête de la requête d'origine du client.
Comme le nom l'indique, il prendra toujours la requête principale (ou la requête client) même s'il est actuellement exécuté dans une sous-requête.
Un exemple simple est ci-dessous :
location /echoback {
echo "headers are:"
echo $echo_client_request_headers;
}
Accéder à /echoback donne
$ curl 'http://localhost/echoback'
headers are
GET /echoback HTTP/1.1
User-Agent: curl/7.18.2 (i486-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.8g
Host: localhost:1984
Accept: */*
Derrière le rideau, il récupère r->main->header_in (ou les grands tampons d'en-tête, le cas échéant) au niveau C et ne construit pas les en-têtes lui-même en parcourant les résultats analysés dans l'objet de requête.
Cette variable est toujours évaluée à une valeur vide dans les requêtes HTTP/2 pour l'instant en raison de l'implémentation actuelle.
Cette variable a été introduite pour la première fois dans version 0.15.
$echo_cacheable_request_uri
Évalue à la forme analysée de l'URI (généralement précédée de /) de la (sous-)requête actuelle. Contrairement à la variable $echo_request_uri, elle est mise en cache.
Voir $echo_request_uri pour plus de détails.
Cette variable a été introduite pour la première fois dans version 0.17.
$echo_request_uri
Évalue à la forme analysée de l'URI (généralement précédée de /) de la (sous-)requête actuelle. Contrairement à la variable $echo_cacheable_request_uri, elle n'est pas mise en cache.
C'est assez différent de la variable $request_uri exportée par le ngx_http_core_module, car $request_uri est la forme non analysée de l'URI de la requête actuelle.
Cette variable a été introduite dans version 0.17.
$echo_incr
C'est un compteur qui génère toujours le numéro de comptage actuel, en commençant par 1. Le compteur est toujours associé à la requête principale même s'il est accessible dans une sous-requête.
Considérez l'exemple suivant
location /main {
echo "main pre: $echo_incr";
echo_location_async /sub;
echo_location_async /sub;
echo "main post: $echo_incr";
}
location /sub {
echo "sub: $echo_incr";
}
Accéder à /main donne
main pre: 1
sub: 3
sub: 4
main post: 2
Cette directive a été introduite pour la première fois dans la version v0.18.
$echo_response_status
Évalue au code de statut de la (sous)requête actuelle, nul s'il n'y en a pas.
Derrière le rideau, c'est simplement la représentation textuelle de r->headers_out->status.
Cette directive a été introduite pour la première fois dans la version v0.23.
Modules qui utilisent ce module pour les tests
Les modules suivants tirent parti de ce module echo dans leur suite de tests :
- Le module memc qui prend en charge presque l'ensemble du protocole TCP memcached.
- Le module chunkin qui ajoute le support d'entrée chunked HTTP 1.1 à Nginx.
- Le module headers_more qui vous permet d'ajouter, de définir et de supprimer des en-têtes d'entrée et de sortie sous les conditions que vous spécifiez.
- Le module
echolui-même.
Veuillez m'envoyer d'autres modules qui utilisent echo sous n'importe quelle forme et je les ajouterai à la liste ci-dessus :)
Changements
Les changements de chaque version de ce module peuvent être obtenus à partir des journaux de modifications du bundle OpenResty :
Suite de tests
Ce module est livré avec une suite de tests pilotée par Perl. Les cas de test sont également déclaratifs. Merci au module Test::Nginx dans le monde Perl.
Pour l'exécuter de votre côté :
$ PATH=/path/to/your/nginx-with-echo-module:$PATH prove -r t
Vous devez terminer tous les processus Nginx avant d'exécuter la suite de tests si vous avez changé le binaire du serveur Nginx.
Parce qu'un seul serveur nginx (par défaut, localhost:1984) est utilisé à travers tous les scripts de test (.t fichiers), il est sans signification d'exécuter la suite de tests en parallèle en spécifiant -jN lors de l'invocation de l'utilitaire prove.
Certaines parties de la suite de tests nécessitent également que les modules standard proxy, rewrite et SSI soient activés lors de la construction de Nginx.
Voir aussi
- Le post de blog original sur le développement initial de ce module.
- Le module de filtre addition standard.
- Le module proxy standard.
- Le bundle OpenResty.
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-echo.