Weserv Images#

The weserv module resizes, crops, and converts images on the fly. It is part of the weserv/images project, the code behind the wsrv.nl service. The module works in one of two modes:

  • proxy — fetches the image from the remote server given in the url query parameter;

  • filter — processes images in responses produced by other handlers, such as static files.

In both modes, the query string sets the processing: w and h set the target width and height, fit sets how the image fits into them, output sets the output format, and so on. The full list of parameters is in the wsrv.nl documentation.

Installation#

To install the module, use one of the following packages:

  • Angie: angie-module-weserv-images

  • Angie PRO: angie-pro-module-weserv-images

Directives#

The main directives of the module:

  • weserv — enables the module in a location and selects the mode, proxy or filter

  • weserv_deny_ip — denies fetching images from the specified addresses or CIDR ranges; it applies only to IP addresses written in the url parameter directly, not to host names

  • weserv_connect_timeout, weserv_send_timeout, weserv_read_timeout — set the timeouts for connecting to the remote server, sending the request to it, and reading its response

  • weserv_max_size — limits the size of an image to be processed

  • weserv_limit_input_pixels, weserv_limit_output_pixels — limit the number of pixels in the input and output images

  • weserv_savers — lists the output formats that the output parameter may request

  • weserv_quality — sets the default output quality; directives such as weserv_jpeg_quality and weserv_webp_quality override it for a single format

In proxy mode, the $weserv_response_length variable holds the size of the fetched original image in bytes; in filter mode, the variable is not set.

All directives with their defaults are described in the module documentation.

Loading the Module#

To use the module, it must be loaded in the main{} context:

load_module modules/ngx_weserv_module.so;

Configuration Example#

server {
    listen 80;

    server_name images.weserv.local;

    root /var/www/imagesweserv/public;

    location / {
        weserv proxy;

        add_header X-Upstream-Response-Length $weserv_response_length;
    }

    location /static/ {
        weserv filter;

        alias /var/www/imagesweserv/public/;
    }
}

Here, requests with the url parameter are processed in proxy mode, and for requests under /static/ the module processes files from the /var/www/imagesweserv/public/ directory in filter mode. A request to / without url is not processed by the module and gets a static file from root.

Angie resolves host names in url with its own resolver; by default, it queries the name servers listed in /etc/resolv.conf, and the /etc/hosts file is not consulted. To use other DNS servers, set the resolver directive. IP addresses in url need no resolution.

Demonstration#

Suppose a server at 127.0.0.1:8081 serves the original image sample.png (400 × 300 pixels, 2351 bytes), and the same file lies in /var/www/imagesweserv/public/.

In proxy mode, the module fetches the image given in url and scales it to the width w, keeping the aspect ratio:

$ curl -s -D - -o out.png 'http://localhost/?url=127.0.0.1:8081/sample.png&w=100'
HTTP/1.1 200 OK
...
Content-Type: image/png
Content-Length: 15633
Content-Disposition: inline; filename=image.png
Link: <http://127.0.0.1:8081/sample.png>; rel="canonical"
...
X-Upstream-Response-Length: 2351

$ file out.png
out.png: PNG image data, 100 x 75, 8-bit/color RGB, non-interlaced

The Link header points to the original image, and X-Upstream-Response-Length carries its size, which the example configuration adds from $weserv_response_length. The http:// prefix in url is optional; adding &output=jpg to the same request returns a JPEG image instead.

In filter mode, the same parameters apply to a local file; here the image is cropped to fill a 50 × 50 square and converted to WebP:

$ curl -s -D - -o small.webp 'http://localhost/static/sample.png?w=50&h=50&fit=cover&output=webp'
HTTP/1.1 200 OK
...
Content-Type: image/webp
Content-Length: 250
...

The file small.webp is a 50 × 50 WebP image. The response has no X-Upstream-Response-Length header: the /static/ location does not add it, and in filter mode $weserv_response_length is not set.

When the module cannot return an image, it responds with an error in JSON:

$ curl -s 'http://localhost/?url=127.0.0.1:8081/missing.png'
{"status":"error","code":404,"message":"The requested URL returned error: 404"}

Additional Information#

Version: v5.1.0

Detailed documentation and source code are available at: weserv/images