What this covers
A static site (build.type: static, see Static pages) can carry its own routing rules in the repository. They are read at deploy time, compiled, and published together with the files, so a rollback restores the rules that went with that version of the site. This page covers the _redirects and _headers files, the matching app.yaml fields, the serving options, the order rules are evaluated in, and how to test them.
Where rules come from
The two files are removed from the served tree when the deploy is published, so visitors cannot download them. Rules from
app.yaml rank before rules from _redirects.
_redirects
One rule per line: from [query matches] to [status[!]]. Lines starting with # are comments.
- The default status is
301. Supported statuses:200(rewrite),301,302,303,307,308, and404,410,451(answer with the page named by the destination). :namematches one path segment and*matches the rest of the path (last segment only). Both can be used in the destination.*is available as:splat.- Matching ignores case and a trailing slash.
- The visitor’s query string is passed on to a redirect destination that has no query of its own.
- A
200rewrite must point at a path on this site. Rewriting to another site (a proxy) is not supported; use a path forwarder on the domain instead. - Conditions such as
Country=,Language=,Role=andCookie=need an edge runtime and are not supported. A line that uses one is skipped and reported.
_headers
A path line, then indented header lines. Use ! Name to remove a header.
, . Headers the ingress manages (Host, Content-Length, Connection, Transfer-Encoding, X-Forwarded-* and a few others) cannot be set. Header names must be valid tokens and values must be a single line.
app.yaml
These fields are only valid with
build.type: static. A mistake in them fails the deploy before anything is published.
Order of evaluation
- Rules, in order:
app.yamlroutes, then_redirects. The first rule that matches wins. A rule that is not forced (!orforce: true) is skipped when a file exists at the requested path, so a stray rule cannot hide real content. - Files: the exact file, then
path.htmlwhen clean URLs are on, thenpath/index.html. Trailing slash and clean URL redirects happen here. - Single page app fallback, when
static.spais on: a path with no file and no extension servesindex.htmlwith status 200. A missing/app.jsstill returns 404. - 404 page, served with status 404. If there is none, a plain 404 response.
Safety
- Redirect destinations are either a path on this site or an absolute
httporhttpsURL. A destination that starts with//, contains backslashes or whitespace, carries credentials, or uses a placeholder in its host is rejected, so a rule cannot become an open redirect. - Values captured from the request are re-escaped before they are placed in a
Locationheader. - Header names and values are checked for control characters, so a rule cannot inject a second header.
- Matching uses linear time regular expressions, so a crafted URL cannot stall the ingress.
Limits
Going over a cap fails the deploy with the variable’s name in the message.
Problems and the deploy log
A bad line in_redirects or _headers is skipped, never applied half understood, and reported in the deploy log under Compile routing rules with its file and line number. The same problems are listed on the Routing rules page of the app. The previous deploy keeps serving until the new one is published, and a failed deploy leaves its rules untouched.
See the rules and test a URL
The Routing rules page of a static app (Traffic section of the app menu) shows the parsed rules, header blocks, options and any problems. Test a URL runs a path through the live rules and files and shows which rule or file answered, the status, and each step considered. Check rules before deploying parses pasted_redirects or _headers text without deploying.
The same from the CLI and the API:
lint exits non-zero when the text has problems, so it fits a CI step.