Search
Varnish Enterprise

image

Description

The image vmod provides a tool for image modification and optimization.

Example

Convert to WebP

This example assumes that you want to convert all JPEG and PNG images to WebP. If this is not the case, see the comment in vcl_backend_response below to adjust to your needs. The example also includes error handling, which makes it longer than most other examples.

import image;
import headerplus;

sub vcl_recv {
	if (req.http.Accept ~ "image/webp") {
		set req.http.X-Varnish-Webp = "enabled";
	} else {
		unset req.http.X-Varnish-Webp;
	}
	unset req.http.X-Varnish-Webp-Result;
}

sub vcl_backend_response {
	# The following "if" test controls which assets should be
	# converted to WebP. If you want a different set than all
	# JPEG and PNG images, you need to updates the contents
	# of this "if" test accordingly.
	if (beresp.http.Content-Type == "image/jpeg" ||
		beresp.http.Content-Type == "image/png")
	{
		if (bereq.http.X-Varnish-Webp && bereq.retries == 0) {
			image.webp();
			set bereq.http.X-Varnish-Webp-Result = "active";
		}
		headerplus.init(beresp);
		headerplus.attr_set("Vary", "X-Varnish-Webp");
		headerplus.write();
	}
}

sub vcl_backend_error {
	if (bereq.retries == 0
		&& bereq.http.X-Varnish-Webp-Result == "active") {
		set bereq.http.X-Varnish-Webp-Result = "failed";
		# Getting here is usually because conversion
		# failed. On the next go, we will not try to
		# convert, as bereq.retries will be 1
		return (retry);
	}
}

The above uses Vary on a self-maintained header (X-Varnish-Webp) to facilitate serving both the original image and the webp version as different variants, and makes sure that Vary is updated for exactly the assets where we might attempt WebP conversion.

In addition to this, the header X-Varnish-Webp-Result is used to keep track of what has happened. The header will make it easier to debug as you can see the header updates in the log, and even filter requests by this header value. The X-Varnish-Webp-Result can also be used by the backend to understand what Varnish is doing.

Note that if we get bereq.http.X-Varnish-Webp-Result = "failed", then this means that the following has happened, in order:

  • Varnish has gotten a full set of backend response headers
  • VCL processing of the backend response headers has happened in sub vcl_backend_response where conversion to WebP was turned on.
  • The image VMOD turned off streaming (equivalent to set beresp.do_stream = false; in VCL), tried to fetch the entire response body and convert it.
  • An error occurred, either when fetching the body or trying to convert the image.
  • As a result of the error happening when streaming was disabled, sub vcl_backend_error was called.
  • In sub vcl_backend_error, a retry of the backend fetch was initiated.

In the scenario above, the second backend fetch will be happen, and if the fetch is successful, an object will be inserted. Subsequent fetches from clients accepting WebP will then get the original - no additional conversion will happen until the inserted objects has left the cache.

API

webp

VOID webp([INT quality = 75], [INT resize_width = 0], [INT resize_height = 0], [BOOL aspect_lock = 0], [INT crop_x = 0], [INT crop_y = 0], [INT crop_width = 0], [INT crop_height = 0], [BOOL lossless = 0], [INT lossless_level = 6], [ENUM {contain, cover, crop} fit])

Convert an image to the WebP format and store it in cache. Optionally scale, resize, crop, or change the quality of conversion. If aspect_lock is set to 1, scaling is done by using only one of resize_width or resize_height. quality and lossless are mutually exclusive options. The supported content types to convert are image/png, image/jpeg and image/webp. When called this function disables streaming. It should not be re-enabled for proper functionality.

Note: The area to crop is defined by X,Y coordinates from the top left corner and then the desired width and height. If only crop_width or crop_height is given (without the corresponding offset), the crop starts from the top-left corner of the source image. When using crop parameters, crop_x requires crop_width to be set, and crop_y requires crop_height to be set. The crop rectangle must fall within the source image boundaries.

Note: When using this function to both crop and rescale an image, the crop will take place prior to rescaling.

Note: quality is a number between 0 and 100, a lower number will result in a smaller size but lower quality. mode is a number between 0 and 9, a lower number is faster but produces a larger file size.

Note: aspect_lock will ensure that the resulting image obeys the aspect ratio of the original image. If the desired resize values do not match this ratio, then, unless fit is specified, the new dimensions will be calculated using the smallest of the two input values, with resize_width being prioritized if both values are identical.

The fit parameter controls how the image is fitted into the box defined by resize_width and resize_height. It requires aspect_lock to be set to true and both resize_width and resize_height to be specified and greater than zero.

When fit is used with crop parameters: if a crop dimension is omitted, the full image extent in that axis is used. The manual crop is applied first, and the fit logic then operates on the resulting cropped image.

The possible values for fit are:

  • contain – The image is resized to be as large as possible while fitting entirely within the resize_width x resize_height box. The aspect ratio is preserved. The resulting image will be at most resize_width pixels wide and at most resize_height pixels tall, but one of the dimensions may be smaller than the requested size.

  • cover – The image is resized to fully cover the resize_width x resize_height box while preserving the aspect ratio. The parts of the image that extend beyond the box are cropped, centered. The resulting image will be exactly resize_width x resize_height pixels.

  • crop – The image is cropped (centered) to fit within the resize_width x resize_height box, but it is never scaled up. If the source image is smaller than the target in a given dimension, the original size is kept in that dimension. If the source image is larger, it is cropped to the target size in that dimension.

Arguments:

  • quality accepts type INT with a default value of 75 optional

  • resize_width accepts type INT with a default value of 0 optional

  • resize_height accepts type INT with a default value of 0 optional

  • aspect_lock accepts type BOOL with a default value of 0 optional

  • crop_x accepts type INT with a default value of 0 optional

  • crop_y accepts type INT with a default value of 0 optional

  • crop_width accepts type INT with a default value of 0 optional

  • crop_height accepts type INT with a default value of 0 optional

  • lossless accepts type BOOL with a default value of 0 optional

  • lossless_level accepts type INT with a default value of 6 optional

  • fit is an ENUM that accepts values of contain, cover, and crop

Type: Function

Returns: None

Restricted to: vcl_backend_response

Availability

The image VMOD is available in the varnish-plus-vmods-extra package.


®Varnish Software, Wallingatan 12, 111 60 Stockholm, Organization nr. 556805-6203