Skip to content

eval: Evaluate memcached or proxy response into a variable

Debian/Ubuntu installation

These docs apply to the APT package nginx-module-eval provided by the GetPageSpeed Extras repository.

  1. Configure the APT repository as described in APT repository setup.
  2. Install the module:
sudo apt-get update
sudo apt-get install nginx-module-eval
Show suites and architectures
| Distro   | Suite             | Component   | Architectures   |
|----------|-------------------|-------------|-----------------|
| debian   | bookworm          | main        | amd64, arm64    |
| debian   | bookworm-mainline | main        | amd64, arm64    |
| debian   | trixie            | main        | amd64, arm64    |
| debian   | trixie-mainline   | main        | amd64, arm64    |
| ubuntu   | focal             | main        | amd64, arm64    |
| ubuntu   | focal-mainline    | main        | amd64, arm64    |
| ubuntu   | jammy             | main        | amd64, arm64    |
| ubuntu   | jammy-mainline    | main        | amd64, arm64    |
| ubuntu   | noble             | main        | amd64, arm64    |
| ubuntu   | noble-mainline    | main        | amd64, arm64    |

ngx_eval - Capturing subrequest response bodies into NGINX variables

Status

This module is experimental and production use is discouraged. If you want similar (but more powerful) functionalities, see the ngx_lua module instead.

Synopsis

## an example for working with the ngx_drizzle + ngx_rds_json
## modules, but you must put ngx_rds_json *after*
## ngx_eval during nginx configure, for example:
## ./configure --add-module=/path/to/nginx-eval-module \
## --add-module=/path/to/rds-json-nginx-module \
## --add-module=/path/to/drizzle-nginx-module
location = /mysql {
    eval_subrequest_in_memory off;
    eval_override_content_type text/plain;
    eval_buffer_size 4k; # default 4k, truncated if overflown
    eval $res {
        drizzle_query "select * from cats";
        drizzle_pass my_mysql_backend;
        rds_json on;
    }
    # now $res holds the JSON formatted result set
    if ($res ~ '"Tom"') {
        echo "Found the Tom cat!";
        break;
    }
    echo "The Tom cat is missing!";
}

## an example for working with the ngx_postgres module
location = /login {
   eval_subrequest_in_memory off;
   eval_override_content_type text/plain;
   eval_buffer_size 1k;
   eval $uid {
       postgres_query "select id
           from users
           where name=$arg_name and pass=$arg_pass";
       postgres_pass pg_backend;
       postgres_output value 0 0;
   }
   if ($uid !~ '^\d+$') {
       rewrite ^ /relogin redirect; break;
   }
   # your content handler settings...
}

Description

This fork of ngx_eval can work with any content handlers and even with filters enabled as long as you put ngx_eval before your filter modules during nginx configure, for instance

./configure --prefix=/opt/nginx \
        --add-module=/path/to/this/nginx-eval-module \
        --add-module=/path/to/your/filter/module \
        --add-module=/path/to/your/other/filters

such that ngx_eval's filter works after your filter modules.

Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the --add-dynamic-module=PATH option instead of --add-module=PATH on the ./configure command line above. And then you can explicitly load the module in your nginx.conf via the load_module directive, for example,

load_module /path/to/modules/ngx_http_eval_module.so;

Use Lua instead

Nowadays, however, we prefer ngx_lua to do the tasks originally done by ngx_eval because of various inherent limitations in ngx_eval.

Here's a small example using ngx_lua:

location = /filter-spam {
    internal;
    proxy_pass http://blah.blah/checker;
}

location / {
    rewrite_by_lua '
        local res = ngx.location.capture("/filter-spam")
        if res.status ~= ngx.HTTP_OK or res.body == nil then
            return
        end
        if string.match(res.body, "SPAM") then
            return ngx.redirect("/terms-of-use")
        end
    ';

    fastcgi_pass ...;
}

this is roughly equivalent to

location / {
    eval $res {
        proxy_pass http://blah.blah/checker;
    }
    if ($res ~ 'SPAM') {
        rewrite ^ /terms-of-use redirect;
        break;
    }

    fastcgi_pass ...;
}

Even though the Lua example is a little longer but is much more flexible and stable.

Limitations

  • The contents of subrequests issued from within the eval block (like those fired by echo_subrequest) won't be captured properly.

Nginx Compatibility

The following versions of Nginx should work with this module:

  • 1.9.x (last tested: 1.9.7)
  • 1.8.x
  • 1.7.x (last tested: 1.7.7)
  • 1.5.x (last tested: 1.5.12)
  • 1.4.x (last tested: 1.4.4)
  • 1.3.x (last tested: 1.3.11)
  • 1.2.x (last tested: 1.2.9)
  • 1.1.x (last tested: 1.1.5)
  • 1.0.x (last tested: 1.0.15)
  • 0.9.x (last tested: 0.9.4)
  • 0.8.0 ~ 0.8.41, 0.8.54+ (0.8.42 ~ 0.8.53 requires patching, see below) (last tested: 0.8.54)
  • 0.7.x >= 0.7.21 (last tested: 0.7.68)

Note that nginx 0.8.42 ~ 0.8.53 won't work due to a famous regression appeared since 0.8.42.

Original ngx_eval documentation

Documentation for this module could be found under following URLs:

  • English: http://www.grid.net.ru/nginx/eval.en.html

  • Russian: http://www.grid.net.ru/nginx/eval.ru.html

This work is commissioned by gadu-gadu.pl

See Also