Turn on the CORS by Feng Shui... maybe 🙃
- Easy and clear to use
- Does not use
add_header
intoif
(therefore, your headers will not be lost) - Configurable and flexibility
cd /usr/local/etc/nginx/
git clone git@github.com:RubaXa/nginx-cors.git
cd /usr/local/etc/nginx/
vim ./cors-enabled.conf
CORS confirugration
# If in your project setted larger, then this directive is not required
map_hash_bucket_size 256;
# Setup the $cors_path variable
map $request_uri $cors_path {
~^(?<path>[^?]+) $path;
}
# Convert Endpoints to CORS service
map "$scheme://$host$cors_path" $cors_service {
"https://api.project.com/user/info" "cors.service.user-info";
~^https://api.auth.project.com/(login|logout)$ "cors.service.auth";
default "<<unknown>>";
}
# Convert Origin to CORS client
map "$http_origin" $cors_client {
~^https://(foo|bar)\.client\.com$ "cors.client.$1"; # "cors.client.foo" or "cors.client.bar";
default "<<unknown>>";
}
# Turn on CORS by client and service map
map "$cors_client -> $cors_service" $cors_enabled {
# Access for 'foo' client
"cors.client.foo -> cors.service.auth" "true";
"cors.client.foo -> cors.service.user-info" "true";
# Access for 'bar' client
"cors.client.bar -> cors.service.auth" "true";
}
http {
# One (!)
include 'cors-enabled.conf';
server {
listen 80;
server_name api.project.com;
location /user/info {
# Two (!!)
include 'nginx-cors/cors.conf';
}
}
server {
listen 80;
server_name api.auth.project.com;
location ~/(login|logout) {
# Three (!!!)
set $cors_allow_credentials "true";
include 'nginx-cors/cors.conf';
}
}
}
location /api/user/exists {
if ($http_origin = 'https://client.com') {
set $cors_enabled 'true';
}
include 'nginx-cors/cors.conf';
}
See detail in source: cors.conf
Thx.
- It's hard to read who exactly enabled CORS
- It is easy to make a mistake in RegExp
- If there is an add_header inside, it will not work
location ~ '/api/auth/(login|logout)' {
if ($http_origin ~ '^https?://(about|company|account)\.(((alpha|beta|omega)\.))?test\.)?)?business\.com$')
set $cors '1';
}
add_header X-My-Header "true"; # it will not work
if ($request_method = 'OPTIONS') {
set $cors "${cond}2";
}
if ($cors = '12') {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Headers "...";
add_header Access-Control-Allow-Methods "...";
add_header Access-Control-Expose-Headers "X-My-Header";
return 204;
}
if ($cors = '1') {
add_header X-My-Header "true"; # but here it will work (1)
add_header Access-Control-Allow-Origin $http_origin;
}
# bla-bla-bla
}
- Easy to read and maintain.
- Flexible configuration
- Operating not at the RegExp level, but client -> service
# Setup the $cors_path variable
map $request_uri $cors_path {
~^(?<path>[^?]+) $path;
}
# Convert endpoints to CORS service
map "$scheme://$host$cors_path" $cors_service {
~^https://project.com/api/(login|logout)$ "cors.service.auth";
default "<<unknown>>";
}
# Convert Origin to CORS client
map "$http_origin" $cors_client {
# Yes, it would be possible to write in one regexp, but it is much more readable and more flexible.
# In addition, you need to list subdomains! Why so? See next `map` ;]
~^https://([^\.]+)\.business.com$" "cors.client.business.$1";
~^https://([^\.]+)\.test\.business.com$" "cors.client.business.$1";
~^https://([^\.]+)\.(alpha|beta|omega)\.test\.business.com$" "cors.client.business.$1";
default "<<unknown>>";
}
# Turn on CORS by client and service map
map "$cors_client -> $cors_service" $cors_enabled {
# And now we can clearly and elegantly include rights
# based on the "$cors_client" and the "$cors_service" to which "client" invoke!
"cors.client.business.about -> cors.service.auth" "false";
"cors.client.business.company -> cors.service.auth" "true";
"cors.client.business.account -> cors.service.auth" "true";
default "false";
}
and
location ~ '/api/auth/(login|logout)' {
add_header X-My-Header "true"; # It's work!
set $cors_allow_expose_headers "X-My-Header";
inclide "ngxin-cors/cors.conf";
}