Rewrite Flags

The Flag Set, Grouped by What It Does

Flags follow the substitution in brackets, comma-separated with no spaces, as in [R=301,L]:

RewriteRule flags grouped by effect
Group Flags What they do
Flow L, END, N, C, S=n Last, end, next, chain, skip n
Outcome R=code, F, G, P, PT Redirect, 403, 410, proxy, pass
Query string QSA, QSD, QSL Append, drop, split at last ?
Escaping B, BNP, BCTLS, BNE, NE Escape captures, or do not
Matching NC, NS, UNC No case, no subrequests, keep //
Side effects E, CO, T, H, DPI Env, cookie, type, handler
Safety valves UnsafeAllow3F, UnsafePrefixStat Reopen blocked behavior

QSL arrived in 2.4.19, BCTLS and BNE in 2.4.57, UNC in 2.4.63, and the Unsafe pair in 2.4.60, whose fixes for CVE-2024-38474 and CVE-2024-38475 broke some old rules until the flag was added. R alone means 302, and a code outside 300-399 (R=410) drops the substitution.

Query-string and escaping flagsApache config
RewriteEngine On
RewriteRule ^a$ show.php?x=1 [L]
RewriteRule ^b$ show.php?x=1 [QSA,L]
RewriteRule ^c$ /show.php [R=301,QSD,L]
RewriteRule ^s1/(.+)$ show.php?q=$1 [L]
RewriteRule ^s2/(.+)$ show.php?q=$1 [B,L]
Output
$ t '/a?y=2' '/b?y=2' '/c?y=2' /s1/x%20%26%20y /s2/x%20%26%20y
/a?y=2                200  {"x":"1"}
/b?y=2                200  {"x":"1","y":"2"}
/c?y=2                301 http://example.com/show.php
/s1/x%20%26%20y       403
/s2/x%20%26%20y       200  {"q":"x & y"}

A substitution with ? replaces the query string unless QSA merges the old one in; QSD strips it from a redirect. The s1 capture decoded to x & y, and since 2.4.56 (the fix for CVE-2023-25690, request splitting) Apache 129 refuses a rewritten query string containing a space: 403, logged as AH10411: Rewritten query string contains control characters or spaces. [B] re-escaped the capture; use it on every capture that lands in a query string.