Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
E

echo-nginx-module

> 编程语言
Open source

An Nginx module for bringing the power of "echo", "sleep", "time" and more to Nginx's config file

1.2K stars0 likes0 views
WebsiteGitHub

About

An Nginx module for bringing the power of "echo", "sleep", "time" and more to Nginx's config file

Name

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.

Table of Contents

  • Name
  • Status
  • Version
  • Synopsis
  • Description
  • Content Handler Directives
    • echo
    • echo_duplicate
    • echo_flush
    • echo_sleep
    • echo_blocking_sleep
    • echo_reset_timer
    • echo_read_request_body
    • echo_location_async
    • echo_location
    • echo_subrequest_async
    • echo_subrequest
    • echo_foreach_split
    • echo_end
    • echo_request_body
    • echo_exec
    • echo_status
  • Filter Directives
    • echo_before_body
    • echo_after_body
  • Variables
    • $echo_it
    • $echo_timer_elapsed
    • $echo_request_body
    • $echo_request_method
    • $echo_client_request_method
    • $echo_client_request_headers
    • $echo_cacheable_request_uri
    • $echo_request_uri
    • $echo_incr
    • $echo_response_status
  • Installation
  • Compatibility
  • Modules that use this module for testing
  • Community
    • English Mailing List
    • Chinese Mailing List
  • Report Bugs
  • Source Repository
  • Changes
  • Test Suite
  • TODO
  • Getting involved
  • Author
  • Copyright & License
  • See Also

Status

This module is production ready.

Version

This document describes ngx_echo v0.63 released on 1 August, 2022.

Synopsis

nginx

   location /hello {
     echo "hello, world!";
   }
nginx

   location /hello {
     echo -n "hello, ";
     echo "world!";
   }
nginx

   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.";
   }
nginx

   location /echo_with_sleep {
     echo hello;
     echo_flush;  # ensure the client can see previous output immediately
     echo_sleep   2.5;  # in sec
     echo world;
   }
nginx

   # 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;
   }
nginx

   # 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;
   }
nginx

   # 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;
   }
nginx

   # Accessing /dup gives
   #   ------ END ------
   location /dup {
     echo_duplicate 3 "--";
     echo_duplicate 1 " END ";
     echo_duplicate 3 "--";
     echo;
   }
nginx

   # /bighello will generate 1000,000,000 hello's.
   location /bighello {
     echo_duplicate 1000_000_000 'hello';
   }
nginx

   # echo back the client request
   location /echoback {
     echo_duplicate 1 $echo_client_request_headers;
     echo "\r";

     echo_read_request_body;

     echo_request_body;
   }
…
nginx

   # 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;
   }
nginx

   # 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;
   }

Back to TOC

Description

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

  1. serve static contents directly from memory (loading from the Nginx config file).
  2. wrap the upstream response with custom header and footer (kinda like the addition module but with contents read directly from the config file and Nginx variables).
  3. merge contents of various "Nginx locations" (i.e., subrequests) together in a single main request (using echo_location and its friends).

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:

  1. Issue parallel subrequests directly from content handler.
  2. Issue chained subrequests directly from content handler, by passing continuation along the subrequest chain.
  3. Issue subrequests with all HTTP 1.1 methods and even an optional faked HTTP request body.
  4. Interact with the Nginx event model directly from content handler using custom events and timers, and resume the content handler back if necessary.
  5. Dual-role module that can (lazily) serve as a content handler or an output filter or both.
  6. Nginx config file variable creation and interpolation.
  7. Streaming output control using output_chain, flush and its friends.
  8. Read client request body from the content handler, and returns back (asynchronously) to the content handler after completion.
  9. Use Perl-based declarative test suite to drive the development of Nginx C modules.

Back to TOC

Content Handler Directives

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:

nginx

   location /hello {
     default_type text/plain;
     echo hello;
   }

Then on the client side:

bash

   $ 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

Since the v0.22 release, all of the directives are allowed in the rewrite module's if directive block, for instance:

nginx

 location ^~ /if {
     set $res miss;
     if ($arg_val ~* '^a') {
         set $res hit;
         echo $res;
     }
     echo $res;
 }

Back to TOC

echo

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

nginx

    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

nginx

    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

nginx

 location /echo {
     echo hello;
     echo world;
 }

The output on the client side looks like this

bash

 $ curl 'http://localhost/echo'
 hello
 world

Special 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

nginx

 location /echo {
     echo -n "hello, ";
     echo "world";
 }

Accessing /echo gives

bash

 $ curl 'http://localhost/echo'
 hello, world

Leading -n in variable values won't take effect and will be emitted literally, as in

nginx

 location /echo {
     set $opt -n;
     echo $opt "hello,";
     echo "world";
 }

This gives the following output

bash

 $ curl 'http://localhost/echo'
 -n hello,
 world

One can output leading -n literals and other options using the special -- option like this

nginx

 location /echo {
     echo -- -n is an option;
 }

which yields

bash

 $ curl 'http://localhost/echo'
 -n is an option

Use this form when you want to output anything leading with a dash (-).

Back to TOC

echo_duplicate

syntax: echo_duplicate <count> <string>

default: no

context: location, location if

phase: content

Outputs dup

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

C

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言