A Regular Expression Tester for NGINX and NGINX Plus

NGINX | June 11, 2019

While working on a regular expression (regex) to use with NGINX, I got an idea for a way to easily test a regex from within an actual NGINX configuration. (The regex tester works just the same for NGINX Open Source and NGINX Plus, and for ease of reading I’ll refer simply to NGINX in this post.)

Support for regular expressions is one of the powerful features of NGINX, but regexes can be complex and difficult to get right, especially if you don’t work with them regularly. NGINX allows regexes in multiple parts of a configuration, for example locations, maps, rewrites, and server names. The tester described here is for regexes in locations and maps.

There are other free online regex testers that are good for most regexes, but NGINX uses some non‑standard shortcuts optimized for web applications. For example, you don’t have to escape the forward slash (/) in a URI as you do in a standard regex. Also, when using a regex in a map, you specify what value to set based on a match. With other regex testers you might have to modify the regex or, in the case of a map, infer what value will be set. In addition, it is always good to be able to test a regex with the actual regex engine in the actual environment.

Notes:

  • NGINX uses Perl Compatible Regular Expressions (PCRE), and this post assumes a basic understanding of both NGINX and regular expressions. Explaining how to construct regexes is outside the scope of this post, and we regret that we cannot answer further questions in the comments section about how to do so. There are numerous websites that provide tools or documentation for building regexes. Two that we have found useful are:
  • The tester handles regexes in two contexts – map{} blocks and HTTP location{} blocks – and below there’s a brief discussion of how regexes work in each case. Explaining how NGINX handles regexes in all contexts is outside the scope of this post; see our documentation:
  • The tester is intentionally designed to be as simple as possible and to fulfill one purpose: test regexes as written by the user, using the actual NGINX regex engine for maps and HTTP locations. As a consequence, you need to provide only a minimal amount of information to create a working NGINX config. We have no plans to add features (such as validating the regex before testing) because that would violate the guiding principle of simplicity. We are happy to fix bugs, of course; please submit them on the Issues tab at our GitHub repo.

Overview

Before we get into the details of the regex tester, let’s first discuss how regexes can be used in NGINX locations and maps.

Locations

Regular expressions in NGINX location{} blocks are of the form:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

For example, a location{} block with the following regex handles all PHP requests with a URI ending with myapp/filename.php, such as /test/myapp/hello.php and /myapp/hello.php. The asterisk after the tilde (~*) makes the match case‑insensitive.

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

NGINX and the regex tester support positional capture groups in location{} blocks. In the following example, the first group captures everything before the PHP file name and the second captures the PHP filename:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

For the URI /myapp/hello.php, the variable $1 is set to /myapp and $2 is set to hello.php.

NGINX also supports named capture groups:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

In this case the variable $begin is set to /myapp and $end is set to hello.php.

The regex tester supports named capture groups but treats them like positional capture groups in its output, displaying their ordinal numbers rather than names.

Maps

NGINX map{} blocks that use regular expressions are of the form:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

For example, this map{} block sets the variable $isphp to 1 if the URI (as recorded in the $uri variable) ends in .php, and 0 if it does not (the match is case sensitive):

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

For maps, NGINX and the regex tester support both positional and named capture groups.

For example, the following maps both set the variable $fileext to the value of the file extension, which is also captured as $1 in this example:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

And as $ext in this example:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

You can use the regex tester for map{} blocks in both the http{} and stream{} contexts, because the syntax and behavior of maps is the same in both contexts. Note, however, that if your map is in the stream{} context, you can use only the map{} block from the tester’s output. See the note below for details.

The Regular Expression Tester

The regex tester is implemented in a Docker container with NGINX and NGINX Unit installed. NGINX Unit serves two variations of a PHP page, one for regexes in location{} blocks and the other for regexes in map{} blocks. The two pages prompt the user for different inputs:

  • Location page:
    • The regex
    • Case sensitivity
    • The URI
  • Map page:
    • The regex
    • Case sensitivity
    • The value to test (the value of the variable that is the first parameter to the map directive)
    • The value to set in the variable specified as the second parameter to the map directive

After providing the information, click the Test button. The tester generates the necessary NGINX configuration file, the configuration is reloaded, and a request is sent to test the regex. The results are then displayed and indicate whether a match was found. If so, on the Location Tester page the values of the capture groups are displayed and on the Map Tester page the value set by the map is reported.

Location Page Example

This example shows the results of a case‑insensitive test of the regex (.*myapp)/(.+\.php)$ against the URI /myapp/hello.php:

Map Page Example

This example shows the results of a case‑insensitive test of the regex .+\.(?<ext>.*)$ against the value /myapp/hello.php, with the named capture group $ext as the value to set:

Note: If your map is in the stream{} context, you can use only the map{} block from the output in your configuration. The server{} block is not valid because it includes a location{} block, which is not supported in the stream{} context.

Conclusion

You can see that the NGINX configuration is quite short and simple. The hard work is done by the PHP page that generates the necessary NGINX configuration file based on the values entered by the user, reloads NGINX, sends a request to NGINX, and displays the results.

You can try out the regex tester for yourself: all the code is available at our GitHub repo (https://github.com/nginxinc/NGINX-Demos/tree/master/nginx-regex-tester).

To make it easy to get the regex tester up and running, all the necessary files are included. To build the Docker image and build the container, simply run:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Then point your browser to http://Docker-host/regextester.php.

I hope you find tester helpful when using regular expressions and that it gives you a glimpse of some of the power, flexibility, and simplicity of NGINX.

To try out the regex tester with NGINX Plus, start your free 30-day trial today or contact us to discuss your use cases.


Share

About the Author

Rick Nelson
Rick NelsonRVP, Solution Engineering

More blogs by Rick Nelson

Related Blog Posts

Automating Certificate Management in a Kubernetes Environment
NGINX | 10/05/2022

Automating Certificate Management in a Kubernetes Environment

Simplify cert management by providing unique, automatically renewed and updated certificates to your endpoints.

Secure Your API Gateway with NGINX App Protect WAF
NGINX | 05/26/2022

Secure Your API Gateway with NGINX App Protect WAF

As monoliths move to microservices, applications are developed faster than ever. Speed is necessary to stay competitive and APIs sit at the front of these rapid modernization efforts. But the popularity of APIs for application modernization has significant implications for app security.

How Do I Choose? API Gateway vs. Ingress Controller vs. Service Mesh
NGINX | 12/09/2021

How Do I Choose? API Gateway vs. Ingress Controller vs. Service Mesh

When you need an API gateway in Kubernetes, how do you choose among API gateway vs. Ingress controller vs. service mesh? We guide you through the decision, with sample scenarios for north-south and east-west API traffic, plus use cases where an API gateway is the right tool.

Deploying NGINX as an API Gateway, Part 2: Protecting Backend Services
NGINX | 01/20/2021

Deploying NGINX as an API Gateway, Part 2: Protecting Backend Services

In the second post in our API gateway series, Liam shows you how to batten down the hatches on your API services. You can use rate limiting, access restrictions, request size limits, and request body validation to frustrate illegitimate or overly burdensome requests.

New Joomla Exploit CVE-2015-8562
NGINX | 12/15/2015

New Joomla Exploit CVE-2015-8562

Read about the new zero day exploit in Joomla and see the NGINX configuration for how to apply a fix in NGINX or NGINX Plus.

Why Do I See “Welcome to nginx!” on My Favorite Website?
NGINX | 01/01/2014

Why Do I See “Welcome to nginx!” on My Favorite Website?

The ‘Welcome to NGINX!’ page is presented when NGINX web server software is installed on a computer but has not finished configuring

Deliver and Secure Every App
F5 application delivery and security solutions are built to ensure that every app and API deployed anywhere is fast, available, and secure. Learn how we can partner to deliver exceptional experiences every time.
Connect With Us