Rewrites and proxies
When you assign an HTTP status code of 200
to a redirect rule, it becomes a rewrite. This means that the URL in the visitor’s address bar remains the same, while Netlify’s servers fetch the new location behind the scenes.
This can be useful for single page apps, proxying to other services, proxying to other Netlify sites (internal rewrites), or transitioning for legacy content.
Except where noted, the examples on this page use the _redirects
file syntax, but all of these options are available in the Netlify configuration file syntax as well.
# Limitations
Rewrites can be very powerful, but there are a few things they cannot do:
- For security reasons, rewrites between Netlify sites belonging to different teams are not allowed.
- Infinitely looping rules, where the “from” and “to” resolve to the same location, are incorrect and will be ignored.
- By default, we limit internal rewrites to one “hop” — you cannot proxy from Netlify SiteA to Netlify SiteB to Netlify SiteC in a single request. This limitation may be amended for customers on a case-by-case basis. Contact support for more information.
- Proxy rewrite requests will time out after 26 seconds. If you are proxying to a longer-running process, we recommend making an asynchronous request rather than waiting for a response.
- Rewrites can cause pages that use assets specified through relative paths to load incorrectly. To make sure your site’s proxied content is displayed as expected, use absolute paths for your assets or a
<base>
tag. - Paths handled by proxies or functions may not redirect from HTTP to HTTPS URLs as expected. If you’re working with proxies or functions, we recommend only publishing HTTPS URLs for your visitors to use.
- While rewrites within the same password-protected site are supported, rewrites to separate password protected sites are not allowed.
# History pushState
and single-page apps
If you’re developing a single page app and want the history pushState
method to work so you get clean URLs, you’ll want to add the following rewrite rule. If you have other redirect or rewrite rules, this is typically the last rule listed.
/* /index.html 200
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
This will effectively serve the index.html
instead of giving a 404
no matter what URL the browser requests.
# Shadowing
By default, you can’t shadow a URL that actually exists within the site. This applies to rewrites using a splat or dynamic path segment as well as rewrites for individual routes or files. This means that even if you’ve setup the following rewrite rule:
/* /index.html 200
The path /partials/chat.html
would still render the contents of that file, if that file actually exists. This tends to be the preferred behavior when setting up rewrite rules for single page apps, etc.
If you’re 100% sure that you’ll always want to redirect, even when the URL matches a static file, you can append an exclamation mark to the rule:
/app/* /app/index.html 200!
This will rewrite everything within /app/*
to /app/index.html
even if a file matches the URL.
This method can also be applied to individual routes or files:
/best-pets/dogs /best-pets/cats.html 200!
With the rule above, /best-pets/dogs
will always display the content in /best-pets/cats.html
even if there is a file at /best-pets/dogs/index.html
.
# Proxy to another service
Similar to how you can rewrite paths like /*
to /index.html
, you can also set up rules to let parts of your site proxy to external services. Let’s say you need to communicate from a single-page app with an API on https://api.example.com
that doesn’t support CORS requests. The following rule will let you use /api/
from your JavaScript client:
/api/* https://api.example.com/:splat 200
Now all requests to /api/...
will be proxied through to https://api.example.com
straight from our CDN servers without an additional connection from the browser. If the API supports standard HTTP caching mechanisms like ETags or Last-Modified
headers, the responses will even get cached by our CDN nodes.
# Custom headers in proxy redirects
For redirect rules specified in the Netlify configuration file, you can add a map with custom headers for your proxy redirects, and Netlify will send the custom headers to another website with every request:
[[redirects]]
from = "/search"
to = "https://api.mysearch.com"
status = 200
force = true
headers = {X-From = "Netlify"}
Custom headers apply to the request, not the response
If you are proxying content to your site, custom headers will not be applied to that content.
# Signed proxy redirects
You can use a JSON Web Signature (JWS) to sign all proxy requests to an external URL.
To enable JWS on your requests, Netlify requires a secret token. You can set the token in your site’s environment variables and indicate the variable name as the signed
value in the redirect rule. Note that if you have the option to set specific scopes for your environment variables, the scope must include Runtime to be available for signed proxy redirects.
Netlify will inject the environment variable value automatically, so you don’t need to take extra steps to substitute the variable value in the configuration file. Once proxy redirects are added, Netlify will send the JWS as an HMAC HS256 encoded x-nf-sign
header to another, non-Netlify website with every proxied request.
Signed proxy redirects must be specified in the Netlify configuration file.
[[redirects]]
from = "/search"
to = "https://api.mysearch.com"
status = 200
force = true
signed = "API_SIGNATURE_TOKEN_PLACEHOLDER"
The JSON document we sign with this JWS header has this format:
{
"deploy_context": "production",
"exp": 1623876755,
"iss": "netlify",
"netlify_id": "1be0f471-6532-45ff-b1b1-f9c66ea24dc1",
"site_url": "https://mysitename.netlify.app"
}
Signed proxy redirects for external sites only
When proxying from one Netlify application to another, using JWS to sign requests isn’t supported.
# Proxy to another Netlify site
With internal rewrites, you can proxy from one Netlify site to another. If you want to proxy to another Netlify site, we recommend using the site’s .netlify.app
subdomain instead of the custom domain in your rewrite rule:
/netlify-site/* https://my-other-site.netlify.app/:splat 200
Did you find this doc useful?
Your feedback helps us improve our docs.