GoDoxy
Advanced TopicsRule-Based Routing

Conditions

Conditions are used to match the request and determine if the rule should be applied.

In block syntax, conditions are written in the rule header (before { ... }). In YAML, the same expression is written in on:. Conditions can be combined using logical operators.

Logical Operators

OperatorDescriptionExample
|OR - Any condition can matchheader X-API-Key | header Authorization
& or \nAND - All conditions must matchmethod GET & path /api/*

Syntax

<condition> <args> [[ | <condition> <args> ] [ & <condition> <args> ]]...

Available Conditions

ConditionArgumentsDescriptionExample
header<name> <pattern>Match when request header matches patternheader Content-Type application/json, header X-API-Key regex("^sk-.*")
header<name>Match when header exists (any value)header X-API-Key
query<name> <pattern>Match when query parameter matches patternquery debug true, query id regex("^[a-f0-9-]{36}$")
query<name>Match when query parameter existsquery debug
cookie<name> <pattern>Match when cookie matches patterncookie session_id abc123, cookie token glob("sess_*")
cookie<name>Match when cookie existscookie session_id
form<name> <pattern>Match when form field matches patternform action submit, form email regex("^[^@]+@[^@]+$")
form<name>Match when form field existsform action
postform<name> <pattern>Match when POST form field matches patternpostform action submit, postform file glob("*.pdf")
postform<name>Match when POST form field existspostform action
proto<http | https | h1 | h2 | h2c | h3>Match when protocol equals valueproto h2
method<method>Match when HTTP method equals valuemethod POST
host<pattern>Match when host matches patternhost example.com, host glob(*.example.com), host regex("^[a-z]+-prod\.com$")
path<pattern>Match when path matches patternpath /version, path glob(/api/*), path regex("^/api/v[0-9]+/.*)
remote<ip | cidr>Match when client IP matches CIDR rangeremote 192.168.1.0/24
route<pattern>Match when route name matches patternroute api, route glob(api-*)
basic_auth<username> <hashed_password>Match when basic auth credentials matchbasic_auth admin $2y$10$...
status<status>Match when status code matches valuestatus 200, status 200-300, status 2xx
resp_header<name> <pattern>Match when response header matches patternresp_header Content-Type application/json, resp_header X-API-Key regex("^sk-.*")
resp_header<name>Match when response header existsresp_header Content-Type

Form Field Conditions

Both form and postform conditions match form field values, but they resolve values differently:

postform Precedence Order

  • Matches request body form fields only (no query-string fallback)

form Precedence Order

  1. Form body fields (POST/PUT/PATCH, urlencoded or multipart)
  2. Query parameters (fallback)

Example

# For POST /example?action=query with body action=form
postform action form     # Matches body value only
form action form         # Matches form value first; query can be fallback

Basic Authentication

For basic_auth conditions, the password must be bcrypt hashed. Generate the hash using:

htpasswd -nbB '' your-password | cut -c 2-

Basic Auth Concept

To protect a resource, you need to:

  • Require basic authentication by default
  • Allow specific users to pass through (or proxy to another service) with valid credentials

Example Basic Auth Rule

default {
  require_basic_auth "Restricted Area"
}

basic_auth user1 "$2y$10$..." | basic_auth user2 "$2y$10$..." {
  pass
}

Path Pattern Syntax

The path condition supports three types of patterns for matching request paths:

String Matching

path /api/users # Exact match for /api/users

Glob Patterns

Glob patterns use github.com/gobwas/glob. GoDoxy compiles them without separators, so * and ? match / the same way they match any other character. ** also matches any sequence; with no separators it is equivalent to * for /.

PatternDescriptionExampleMatchesNon-matches
*Any sequence of characters, including //api/*/api/users, /api/users/123/api
**Any sequence of characters, including //static/**/static/css/style.css, /static/js/app.js
?Any single character, including //file?.txt/file1.txt, /fileA.txt, /file/.txt/file12.txt, /file/abc.txt
[abc]Set: match any listed character/file[123].txt/file1.txt, /file2.txt, /file3.txt/file4.txt, /fileA.txt
[!abc]Negated set/file[!123].txt/fileA.txt, /fileB.txt/file1.txt, /file2.txt
[a-z]Single range/file[a-z].txt/filea.txt, /filem.txt, /filez.txt/fileA.txt, /file1.txt
[0-9]Single numeric range/v[0-9]/api/v1/api, /v5/api, /v9/api/v10/api, /va/api
{a,b,c}Alternatives (comma-separated, no spaces)/api/{users,posts,comments}/api/users, /api/posts, /api/comments/api/products, /api/users/123
\*Literal asterisk/file\*.txt/file*.txt/fileabc.txt
\?Literal question mark/file\?.txt/file?.txt/filea.txt

A [...] class is either one range ([a-z], [0-9]) or a set of listed characters ([abc], [!_], [-abcdef0123456789]), not both. Mixed forms such as [a-f0-9] or [a-f0-9-] do not compile. Put a literal - first or last in a set ([-abc] or [abc-]). Unclosed { / [ and a trailing \ are syntax errors.

Advanced Glob Examples

# Match common web asset files
path glob("/static/**/*.{css,js,png,jpg,jpeg,gif,svg}")

# Match versioned API paths (one digit; * still matches nested segments)
path glob("/api/v[0-9]/*")

# Hex-and-hyphen name: list the set, do not mix ranges in one [...]
path glob("/users/[-abcdef0123456789]*/profile")

# Match date-based paths (each [0-9] is its own range)
path glob("/logs/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*")

# Match file extensions with character classes
path glob("/uploads/*.{[Pp][Dd][Ff],[Dd][Oo][Cc][Xx]}")

# Exclude names whose first character is underscore
path glob("/images/[!_]*")

Regular Expressions

path regex("^/api/v[0-9]+/users/[a-f0-9-]{36}$")  # Match specific UUID pattern
path regex("^/files/[0-9]{4}-[0-9]{2}-[0-9]{2}$")  # Match date pattern

On this page