NGINX — conditional variables
This week I learned how to use nginx map directive
Suppose you have an API server running on https://api.example.com and would like to make sure your API’s get used by https://shop.example.com and https://marketing.example.com.
One way to achieve this is through CORS (cross origin resource sharing), which helps you tell browsers to allow requests to your domains and block all other domains.
You might be tempted to add something like this to your nginx configuration.
And then the browser would complain with an error like this
Access to fetch at 'https://api.example.com/' from origin 'https://marketing.example.com' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
In general, if statements are not recommend in nginx, unless they’re the only option.
In our scenario, a map
directive can help us create an “allow list” of domains that we want to share our API’s with and provide default value for all other domains.
# api server configuration
http {
# allow list
map $http_origin $allow_origin {
~^https://shop.example.com$ $http_origin;
~^https://marketing.example.com$ $http_origin;
default "";
}
server {
# ...
add_header "Access-Control-Allow-Origin" $allow_origin always;
}
}
This nginx syntax can be compared to a switch statement.
For example, in a Javascript based server (ex: expressjs
), you might create the same allow list like shown in the below snippet.
// express server
function generateAllowedOrigin(requestOrigin) {
switch(requestOrigin) {
case 'https://shop.example.com':
case 'https://marketing.example.com':
return requestOrigin;
default:
return '';
}
}
app.use((req, res, next) => {
const http_origin = req.headers.origin;
const allow_origin = generateAllowedOrigin(http_origin);
if(allow_origin) { // expressjs sends headers with empty values, but nginx does not
res.header('Access-Control-Allow-Origin', allow_origin);
}
next();
});
Use cases:
- Allow CORS for your domains only
- Allow site access to some countries