An Nginx module for bringing the power of "echo", "sleep", "time" and more to Nginx's config file
An Nginx module for bringing the power of "echo", "sleep", "time" and more to Nginx's config file
ngx_echo - Brings "echo", "sleep", "time", "exec" and more shell-style goodies to Nginx config file.
This module is not distributed with the Nginx source. See the installation instructions.
This module is production ready.
This document describes ngx_echo v0.63 released on 1 August, 2022.
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; # ensure the client can see previous output immediately
echo_sleep 2.5; # in sec
echo world;
}
# in the following example, accessing /echo yields
# 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;
}
# the output of /main might be
# hello
# world
# took 0.000 sec for total.
# and the whole request would take about 2 sec to complete.
location /main {
echo_reset_timer;
# subrequests in parallel
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;
}
# the output of /main might be
# hello
# world
# took 3.003 sec for total.
# and the whole request would take about 3 sec to complete.
location /main {
echo_reset_timer;
# subrequests in series (chained by 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;
}
# Accessing /dup gives
# ------ END ------
location /dup {
echo_duplicate 3 "--";
echo_duplicate 1 " END ";
echo_duplicate 3 "--";
echo;
}
# /bighello will generate 1000,000,000 hello's.
location /bighello {
echo_duplicate 1000_000_000 'hello';
}
# echo back the client request
location /echoback {
echo_duplicate 1 $echo_client_request_headers;
echo "\r";
echo_read_request_body;
echo_request_body;
}…
# GET /merge?/foo.js&/bar/blah.js&/yui/baz.js will merge the .js resources together
location /merge {
default_type 'text/javascript';
echo_foreach_split '&' $query_string;
echo "/* JS File $echo_it */";
echo_location_async $echo_it;
echo;
echo_end;
}
# accessing /if?val=abc yields the "hit" output
# while /if?val=bcd yields "miss":
location ^~ /if {
set $res miss;
if ($arg_val ~* '^a') {
set $res hit;
echo $res;
}
echo $res;
}This module wraps lots of Nginx internal APIs for streaming input and output, parallel/sequential subrequests, timers and sleeping, as well as various meta data accessing.
Basically it provides various utilities that help testing and debugging of other modules by trivially emulating different kinds of faked subrequest locations.
People will also find it useful in real-world applications that need to
This is a special dual-role module that can lazily serve as a content handler or register itself as an output filter only upon demand. By default, this module does not do anything at all.
Technically, this module has also demonstrated the following techniques that might be helpful for module writers:
Use of the following directives register this module to the current Nginx location as a content handler. If you want to use another module, like the standard proxy module, as the content handler, use the filter directives provided by this module.
All the content handler directives can be mixed together in a single Nginx location and they're supposed to run sequentially just as in the Bash scripting language.
Every content handler directive supports variable interpolation in its arguments (if any).
The MIME type set by the standard default_type directive is respected by this module, as in:
location /hello {
default_type text/plain;
echo hello;
}Then on the client side:
$ 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-aliveSince the v0.22 release, all of the directives are allowed in the rewrite module's if directive block, for instance:
location ^~ /if {
set $res miss;
if ($arg_val ~* '^a') {
set $res hit;
echo $res;
}
echo $res;
}syntax: echo [options] <string>...
default: no
context: location, location if
phase: content
Sends arguments joined by spaces, along with a trailing newline, out to the client.
Note that the data might be buffered by Nginx's underlying buffer. To force the output data flushed immediately, use the echo_flush command just after echo, as in
echo hello world;
echo_flush;When no argument is specified, echo emits the trailing newline alone, just like the echo command in shell.
Variables may appear in the arguments. An example is
echo The current request uri is $request_uri;where $request_uri is a variable exposed by the ngx_http_core_module.
This command can be used multiple times in a single location configuration, as in
location /echo {
echo hello;
echo world;
}The output on the client side looks like this
$ curl 'http://localhost/echo'
hello
worldSpecial characters like newlines (\n) and tabs (\t) can be escaped using C-style escaping sequences. But a notable exception is the dollar sign ($). As of Nginx 0.8.20, there's still no clean way to escape this character. (A work-around might be to use a $echo_dollor variable that is always evaluated to the constant $ character. This feature will possibly be introduced in a future version of this module.)
As of the echo v0.28 release, one can suppress the trailing newline character in the output by using the -n option, as in
location /echo {
echo -n "hello, ";
echo "world";
}Accessing /echo gives
$ curl 'http://localhost/echo'
hello, worldLeading -n in variable values won't take effect and will be emitted literally, as in
location /echo {
set $opt -n;
echo $opt "hello,";
echo "world";
}This gives the following output
$ curl 'http://localhost/echo'
-n hello,
worldOne can output leading -n literals and other options using the special -- option like this
location /echo {
echo -- -n is an option;
}which yields
$ curl 'http://localhost/echo'
-n is an optionUse this form when you want to output anything leading with a dash (-).
syntax: echo_duplicate <count> <string>
default: no
context: location, location if
phase: content
Outputs dup
No open issues yet, or sync has not completed.