Created
June 29, 2017 01:20
-
-
Save tzumby/fe5d0f666c4ceaa434515a77fee09ada to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{{ $cfg := .Cfg }} | |
{{ $IsIPV6Enabled := .IsIPV6Enabled }} | |
{{ $healthzURI := .HealthzURI }} | |
{{ $backends := .Backends }} | |
{{ $proxyHeaders := .ProxySetHeaders }} | |
daemon off; | |
worker_processes {{ $cfg.WorkerProcesses }}; | |
pid /run/nginx.pid; | |
{{ if ne .MaxOpenFiles 0 }} | |
worker_rlimit_nofile {{ .MaxOpenFiles }}; | |
{{ end}} | |
events { | |
multi_accept on; | |
worker_connections {{ $cfg.MaxWorkerConnections }}; | |
use epoll; | |
} | |
http { | |
{{/* we use the value of the header X-Forwarded-For to be able to use the geo_ip module */}} | |
{{ if $cfg.UseProxyProtocol }} | |
set_real_ip_from {{ $cfg.ProxyRealIPCIDR }}; | |
real_ip_header proxy_protocol; | |
{{ else }} | |
set_real_ip_from {{ $cfg.ProxyRealIPCIDR }}; | |
real_ip_header X-Forwarded-For; | |
{{ end }} | |
real_ip_recursive on; | |
{{/* databases used to determine the country depending on the client IP address */}} | |
{{/* http://nginx.org/en/docs/http/ngx_http_geoip_module.html */}} | |
{{/* this is require to calculate traffic for individual country using GeoIP in the status page */}} | |
geoip_country /etc/nginx/GeoIP.dat; | |
geoip_city /etc/nginx/GeoLiteCity.dat; | |
geoip_proxy_recursive on; | |
{{ if $cfg.EnableVtsStatus }} | |
vhost_traffic_status_zone shared:vhost_traffic_status:{{ $cfg.VtsStatusZoneSize }}; | |
vhost_traffic_status_filter_by_set_key $geoip_country_code country::*; | |
{{ end }} | |
# lua section to return proper error codes when custom pages are used | |
lua_package_path '/etc/nginx/lua/vendor/lua-resty-http/lib/?.lua;/etc/nginx/lua/?.lua;/usr/local/waf_rules/?.lua;/etc/nginx/lualib/?.lua;/etc/nginx/lualib/resty/?.lua;/etc/nginx/site/lualib/?.lua;'; | |
lua_shared_dict waf_storage 40m; | |
init_by_lua_block { | |
require "resty.core" | |
local lua_resty_waf = require "resty.waf" | |
lua_resty_waf.init() | |
require("error_page") | |
} | |
sendfile on; | |
aio threads; | |
tcp_nopush on; | |
tcp_nodelay on; | |
log_subrequest on; | |
reset_timedout_connection on; | |
keepalive_timeout {{ $cfg.KeepAlive }}s; | |
keepalive_requests {{ $cfg.KeepAliveRequests }}; | |
client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }}; | |
large_client_header_buffers {{ $cfg.LargeClientHeaderBuffers }}; | |
client_body_buffer_size {{ $cfg.ClientBodyBufferSize }}; | |
http2_max_field_size {{ $cfg.HTTP2MaxFieldSize }}; | |
http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }}; | |
types_hash_max_size 2048; | |
server_names_hash_max_size {{ $cfg.ServerNameHashMaxSize }}; | |
server_names_hash_bucket_size {{ $cfg.ServerNameHashBucketSize }}; | |
map_hash_bucket_size {{ $cfg.MapHashBucketSize }}; | |
variables_hash_bucket_size {{ $cfg.VariablesHashBucketSize }}; | |
variables_hash_max_size {{ $cfg.VariablesHashMaxSize }}; | |
underscores_in_headers {{ if $cfg.EnableUnderscoresInHeaders }}on{{ else }}off{{ end }}; | |
ignore_invalid_headers {{ if $cfg.IgnoreInvalidHeaders }}on{{ else }}off{{ end }}; | |
include /etc/nginx/mime.types; | |
default_type text/html; | |
{{ if $cfg.UseGzip }} | |
gzip on; | |
gzip_comp_level 5; | |
gzip_http_version 1.1; | |
gzip_min_length 256; | |
gzip_types {{ $cfg.GzipTypes }}; | |
gzip_proxied any; | |
{{ end }} | |
server_tokens {{ if $cfg.ShowServerTokens }}on{{ else }}off{{ end }}; | |
# disable warnings | |
uninitialized_variable_warn off; | |
log_format upstreaminfo {{ if $cfg.LogFormatEscapeJSON }}escape=json {{ end }}'{{ buildLogFormatUpstream $cfg }}'; | |
{{/* map urls that should not appear in access.log */}} | |
{{/* http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log */}} | |
map $request_uri $loggable { | |
{{ range $reqUri := $cfg.SkipAccessLogURLs }} | |
{{ $reqUri }} 0;{{ end }} | |
default 1; | |
} | |
{{ if $cfg.DisableAccessLog }} | |
access_log off; | |
{{ else }} | |
access_log /var/log/nginx/access.log upstreaminfo if=$loggable; | |
{{ end }} | |
error_log /var/log/nginx/error.log {{ $cfg.ErrorLogLevel }}; | |
{{ buildResolvers $cfg.Resolver }} | |
{{/* Whenever nginx proxies a request without a "Connection" header, the "Connection" header is set to "close" */}} | |
{{/* when making the target request. This means that you cannot simply use */}} | |
{{/* "proxy_set_header Connection $http_connection" for WebSocket support because in this case, the */}} | |
{{/* "Connection" header would be set to "" whenever the original request did not have a "Connection" header, */}} | |
{{/* which would mean no "Connection" header would be in the target request. Since this would deviate from */}} | |
{{/* normal nginx behavior we have to use this approach. */}} | |
# Retain the default nginx handling of requests without a "Connection" header | |
map $http_upgrade $connection_upgrade { | |
default upgrade; | |
'' close; | |
} | |
# trust http_x_forwarded_proto headers correctly indicate ssl offloading | |
map $http_x_forwarded_proto $pass_access_scheme { | |
default $http_x_forwarded_proto; | |
'' $scheme; | |
} | |
map $http_x_forwarded_port $pass_server_port { | |
default $http_x_forwarded_port; | |
'' $server_port; | |
} | |
{{ if $cfg.UseProxyProtocol }} | |
map $http_x_forwarded_for $the_real_ip { | |
default $http_x_forwarded_for; | |
'' $proxy_protocol_addr; | |
} | |
{{ else }} | |
map $http_x_forwarded_for $the_real_ip { | |
default $http_x_forwarded_for; | |
'' $remote_addr; | |
} | |
{{ end }} | |
# map port 442 to 443 for header X-Forwarded-Port | |
map $pass_server_port $pass_port { | |
442 443; | |
default $pass_server_port; | |
} | |
# Map a response error watching the header Content-Type | |
map $http_accept $httpAccept { | |
default html; | |
application/json json; | |
application/xml xml; | |
text/plain text; | |
} | |
map $httpAccept $httpReturnType { | |
default text/html; | |
json application/json; | |
xml application/xml; | |
text text/plain; | |
} | |
# Obtain best http host | |
map $http_host $this_host { | |
default $http_host; | |
'' $host; | |
} | |
map $http_x_forwarded_host $best_http_host { | |
default $http_x_forwarded_host; | |
'' $this_host; | |
} | |
server_name_in_redirect off; | |
port_in_redirect off; | |
ssl_protocols {{ $cfg.SSLProtocols }}; | |
# turn on session caching to drastically improve performance | |
{{ if $cfg.SSLSessionCache }} | |
ssl_session_cache builtin:1000 shared:SSL:{{ $cfg.SSLSessionCacheSize }}; | |
ssl_session_timeout {{ $cfg.SSLSessionTimeout }}; | |
{{ end }} | |
# allow configuring ssl session tickets | |
ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }}; | |
# slightly reduce the time-to-first-byte | |
ssl_buffer_size {{ $cfg.SSLBufferSize }}; | |
{{ if not (empty $cfg.SSLCiphers) }} | |
# allow configuring custom ssl ciphers | |
ssl_ciphers '{{ $cfg.SSLCiphers }}'; | |
ssl_prefer_server_ciphers on; | |
{{ end }} | |
{{ if not (empty $cfg.SSLDHParam) }} | |
# allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam | |
ssl_dhparam {{ $cfg.SSLDHParam }}; | |
{{ end }} | |
{{ if not $cfg.EnableDynamicTLSRecords }} | |
ssl_dyn_rec_size_lo 0; | |
{{ end }} | |
ssl_ecdh_curve {{ $cfg.SSLECDHCurve }}; | |
{{ if .CustomErrors }} | |
# Custom error pages | |
proxy_intercept_errors on; | |
{{ end }} | |
{{ range $errCode := $cfg.CustomHTTPErrors }} | |
error_page {{ $errCode }} = @custom_{{ $errCode }};{{ end }} | |
proxy_ssl_session_reuse on; | |
{{ if $cfg.AllowBackendServerHeader }} | |
proxy_pass_header Server; | |
{{ end }} | |
{{ range $name, $upstream := $backends }} | |
{{ if eq $upstream.SessionAffinity.AffinityType "cookie" }} | |
upstream sticky-{{ $upstream.Name }} { | |
sticky hash={{ $upstream.SessionAffinity.CookieSessionAffinity.Hash }} name={{ $upstream.SessionAffinity.CookieSessionAffinity.Name }} httponly; | |
{{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} | |
keepalive {{ $cfg.UpstreamKeepaliveConnections }}; | |
{{ end }} | |
{{ range $server := $upstream.Endpoints }}server {{ $server.Address | formatIP }}:{{ $server.Port }} max_fails={{ $server.MaxFails }} fail_timeout={{ $server.FailTimeout }}; | |
{{ end }} | |
} | |
{{ end }} | |
upstream {{ $upstream.Name }} { | |
# Load balance algorithm; empty for round robin, which is the default | |
{{ if ne $cfg.LoadBalanceAlgorithm "round_robin" }} | |
{{ $cfg.LoadBalanceAlgorithm }}; | |
{{ end }} | |
{{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} | |
keepalive {{ $cfg.UpstreamKeepaliveConnections }}; | |
{{ end }} | |
{{ range $server := $upstream.Endpoints }}server {{ $server.Address | formatIP }}:{{ $server.Port }} max_fails={{ $server.MaxFails }} fail_timeout={{ $server.FailTimeout }}; | |
{{ end }} | |
} | |
{{ end }} | |
{{/* build the maps that will be use to validate the Whitelist */}} | |
{{ range $index, $server := .Servers }} | |
{{ range $location := $server.Locations }} | |
{{ $path := buildLocation $location }} | |
{{ if isLocationAllowed $location }} | |
{{ if gt (len $location.Whitelist.CIDR) 0 }} | |
geo $the_real_ip {{ buildDenyVariable (print $server.Hostname "_" $path) }} { | |
default 1; | |
{{ range $ip := $location.Whitelist.CIDR }} | |
{{ $ip }} 0;{{ end }} | |
} | |
{{ end }} | |
{{ end }} | |
{{ end }} | |
{{ end }} | |
{{/* build all the required rate limit zones. Each annotation requires a dedicated zone */}} | |
{{/* 1MB -> 16 thousand 64-byte states or about 8 thousand 128-byte states */}} | |
{{ range $zone := (buildRateLimitZones .Servers) }} | |
{{ $zone }} | |
{{ end }} | |
{{ $backlogSize := .BacklogSize }} | |
{{ range $index, $server := .Servers }} | |
server { | |
server_name {{ $server.Hostname }}; | |
listen 80{{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $backlogSize }}{{end}}; | |
{{ if $IsIPV6Enabled }}listen [::]:80{{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $backlogSize }}{{ end }};{{ end }} | |
set $proxy_upstream_name "-"; | |
access_by_lua_block { | |
local lua_resty_waf = require "resty.waf" | |
local waf = lua_resty_waf:new() | |
waf:set_option("storage_zone", "waf_storage") | |
waf:set_option("debug", true) | |
waf:set_option("mode", "ACTIVE") | |
waf:set_option("add_ruleset", {"941_application_attack_xss", "930_application_attack"}) | |
waf:exec() | |
} | |
{{/* Listen on 442 because port 443 is used in the TLS sni server */}} | |
{{/* This listener must always have proxy_protocol enabled, because the SNI listener forwards on source IP info in it. */}} | |
{{ if not (empty $server.SSLCertificate) }}listen 442 proxy_protocol{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $backlogSize }}{{end}} ssl {{ if $cfg.UseHTTP2 }}http2{{ end }}; | |
{{ if $IsIPV6Enabled }}{{ if not (empty $server.SSLCertificate) }}listen [::]:442 proxy_protocol{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $backlogSize }}{{end}} ssl {{ if $cfg.UseHTTP2 }}http2{{ end }};{{ end }} | |
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}} | |
# PEM sha: {{ $server.SSLPemChecksum }} | |
ssl_certificate {{ $server.SSLCertificate }}; | |
ssl_certificate_key {{ $server.SSLCertificate }}; | |
{{ end }} | |
{{ if (and (not (empty $server.SSLCertificate)) $cfg.HSTS) }} | |
more_set_headers "Strict-Transport-Security: max-age={{ $cfg.HSTSMaxAge }}{{ if $cfg.HSTSIncludeSubdomains }}; includeSubDomains{{ end }};{{ if $cfg.HSTSPreload }} preload{{ end }}"; | |
{{ end }} | |
{{ if $cfg.EnableVtsStatus }}vhost_traffic_status_filter_by_set_key $geoip_country_code country::$server_name;{{ end }} | |
{{ range $location := $server.Locations }} | |
{{ $path := buildLocation $location }} | |
{{ $authPath := buildAuthLocation $location }} | |
{{ if not (empty $location.CertificateAuth.AuthSSLCert.CAFileName) }} | |
# PEM sha: {{ $location.CertificateAuth.AuthSSLCert.PemSHA }} | |
ssl_client_certificate {{ $location.CertificateAuth.AuthSSLCert.CAFileName }}; | |
ssl_verify_client on; | |
ssl_verify_depth {{ $location.CertificateAuth.ValidationDepth }}; | |
{{ end }} | |
{{ if (or $location.Redirect.ForceSSLRedirect (and (not (empty $server.SSLCertificate)) $location.Redirect.SSLRedirect)) }} | |
# enforce ssl on server side | |
if ($pass_access_scheme = http) { | |
return 301 https://$best_http_host$request_uri; | |
} | |
{{ end }} | |
{{ if not (empty $location.Redirect.AppRoot)}} | |
if ($uri = /) { | |
return 302 {{ $location.Redirect.AppRoot }}; | |
} | |
{{ end }} | |
{{ if not (empty $authPath) }} | |
location = {{ $authPath }} { | |
internal; | |
set $proxy_upstream_name "internal"; | |
{{ if not $location.ExternalAuth.SendBody }} | |
proxy_pass_request_body off; | |
proxy_set_header Content-Length ""; | |
{{ end }} | |
{{ if not (empty $location.ExternalAuth.Method) }} | |
proxy_method {{ $location.ExternalAuth.Method }}; | |
proxy_set_header X-Original-URI $request_uri; | |
proxy_set_header X-Scheme $pass_access_scheme; | |
{{ end }} | |
proxy_pass_request_headers on; | |
proxy_set_header Host {{ $location.ExternalAuth.Host }}; | |
proxy_ssl_server_name on; | |
client_max_body_size "{{ $location.Proxy.BodySize }}"; | |
set $target {{ $location.ExternalAuth.URL }}; | |
proxy_pass $target; | |
} | |
{{ end }} | |
location {{ $path }} { | |
set $proxy_upstream_name "{{ buildUpstreamName $server.Hostname $backends $location }}"; | |
{{ if isLocationAllowed $location }} | |
{{ if gt (len $location.Whitelist.CIDR) 0 }} | |
if ({{ buildDenyVariable (print $server.Hostname "_" $path) }}) { | |
return 403; | |
} | |
{{ end }} | |
port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; | |
{{ if not (empty $authPath) }} | |
# this location requires authentication | |
auth_request {{ $authPath }}; | |
{{- range $idx, $line := buildAuthResponseHeaders $location }} | |
{{ $line }} | |
{{- end }} | |
{{ end }} | |
{{ if not (empty $location.ExternalAuth.SigninURL) }} | |
error_page 401 = {{ $location.ExternalAuth.SigninURL }}; | |
{{ end }} | |
{{/* if the location contains a rate limit annotation, create one */}} | |
{{ $limits := buildRateLimit $location }} | |
{{ range $limit := $limits }} | |
{{ $limit }}{{ end }} | |
{{ if $location.BasicDigestAuth.Secured }} | |
{{ if eq $location.BasicDigestAuth.Type "basic" }} | |
auth_basic "{{ $location.BasicDigestAuth.Realm }}"; | |
auth_basic_user_file {{ $location.BasicDigestAuth.File }}; | |
{{ else }} | |
auth_digest "{{ $location.BasicDigestAuth.Realm }}"; | |
auth_digest_user_file {{ $location.BasicDigestAuth.File }}; | |
{{ end }} | |
proxy_set_header Authorization ""; | |
{{ end }} | |
{{ if $location.EnableCORS }} | |
{{ template "CORS" }} | |
{{ end }} | |
client_max_body_size "{{ $location.Proxy.BodySize }}"; | |
proxy_set_header Host $best_http_host; | |
# Pass the extracted client certificate to the backend | |
{{ if not (empty $location.CertificateAuth.AuthSSLCert.CAFileName) }} | |
proxy_set_header ssl-client-cert $ssl_client_cert; | |
{{ end }} | |
# Allow websocket connections | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection $connection_upgrade; | |
proxy_set_header X-Real-IP $the_real_ip; | |
proxy_set_header X-Forwarded-For $the_real_ip; | |
proxy_set_header X-Forwarded-Host $best_http_host; | |
proxy_set_header X-Forwarded-Port $pass_port; | |
proxy_set_header X-Forwarded-Proto $pass_access_scheme; | |
proxy_set_header X-Original-URI $request_uri; | |
proxy_set_header X-Scheme $pass_access_scheme; | |
# mitigate HTTPoxy Vulnerability | |
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ | |
proxy_set_header Proxy ""; | |
# Custom headers | |
{{ range $k, $v := $proxyHeaders }} | |
proxy_set_header {{ $k }} "{{ $v }}"; | |
{{ end }} | |
proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; | |
proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; | |
proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; | |
proxy_redirect off; | |
proxy_buffering off; | |
proxy_buffer_size "{{ $location.Proxy.BufferSize }}"; | |
proxy_buffers 4 "{{ $location.Proxy.BufferSize }}"; | |
proxy_http_version 1.1; | |
proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; | |
proxy_cookie_path {{ $location.Proxy.CookiePath }}; | |
# In case of errors try the next upstream server before returning an error | |
proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream }}{{ if $cfg.RetryNonIdempotent }} non_idempotent{{ end }}; | |
{{/* rewrite only works if the content is not compressed */}} | |
{{ if $location.Redirect.AddBaseURL }} | |
proxy_set_header Accept-Encoding ""; | |
{{ end }} | |
{{/* Add any additional configuration defined */}} | |
{{ $location.ConfigurationSnippet }} | |
{{ buildProxyPass $server.Hostname $backends $location }} | |
{{ else }} | |
#{{ $location.Denied }} | |
return 503; | |
{{ end }} | |
} | |
{{ end }} | |
{{ if eq $server.Hostname "_" }} | |
# health checks in cloud providers require the use of port 80 | |
location {{ $healthzURI }} { | |
access_log off; | |
return 200; | |
} | |
# this is required to avoid error if nginx is being monitored | |
# with an external software (like sysdig) | |
location /nginx_status { | |
allow 127.0.0.1; | |
{{ if $IsIPV6Enabled }}allow ::1;{{ end }} | |
deny all; | |
access_log off; | |
stub_status on; | |
} | |
{{ end }} | |
{{ template "CUSTOM_ERRORS" $cfg }} | |
} | |
{{ end }} | |
# default server, used for NGINX healthcheck and access to nginx stats | |
server { | |
# Use the port 18080 (random value just to avoid known ports) as default port for nginx. | |
# Changing this value requires a change in: | |
# https://github.com/kubernetes/contrib/blob/master/ingress/controllers/nginx/nginx/command.go#L104 | |
listen 18080 default_server reuseport backlog={{ .BacklogSize }}; | |
{{ if $IsIPV6Enabled }}listen [::]:18080 default_server reuseport backlog={{ .BacklogSize }};{{ end }} | |
set $proxy_upstream_name "-"; | |
location {{ $healthzURI }} { | |
access_log off; | |
return 200; | |
} | |
location /nginx_status { | |
set $proxy_upstream_name "internal"; | |
{{ if $cfg.EnableVtsStatus }} | |
vhost_traffic_status_display; | |
vhost_traffic_status_display_format html; | |
{{ else }} | |
access_log off; | |
stub_status on; | |
{{ end }} | |
} | |
# this location is used to extract nginx metrics | |
# using prometheus. | |
# TODO: enable extraction for vts module. | |
location /internal_nginx_status { | |
set $proxy_upstream_name "internal"; | |
allow 127.0.0.1; | |
{{ if not $cfg.DisableIpv6 }}allow ::1;{{ end }} | |
deny all; | |
access_log off; | |
stub_status on; | |
} | |
location / { | |
set $proxy_upstream_name "upstream-default-backend"; | |
proxy_pass http://upstream-default-backend; | |
} | |
{{ template "CUSTOM_ERRORS" $cfg }} | |
} | |
# default server for services without endpoints | |
server { | |
listen 8181; | |
set $proxy_upstream_name "-"; | |
location / { | |
{{ if .CustomErrors }} | |
content_by_lua_block { | |
openURL(ngx.req.get_headers(0), 503) | |
} | |
{{ else }} | |
return 503; | |
{{ end }} | |
} | |
} | |
} | |
{{/* definition of templates to avoid repetitions */}} | |
{{ define "CUSTOM_ERRORS" }} | |
{{ range $errCode := .CustomHTTPErrors }} | |
location @custom_{{ $errCode }} { | |
internal; | |
content_by_lua_block { | |
openURL(ngx.req.get_headers(0), {{ $errCode }}) | |
} | |
} | |
{{ end }} | |
{{ end }} | |
{{/* CORS support from https://michielkalkman.com/snippets/nginx-cors-open-configuration.html */}} | |
{{ define "CORS" }} | |
if ($request_method = 'OPTIONS') { | |
add_header 'Access-Control-Allow-Origin' '*'; | |
# | |
# Om nom nom cookies | |
# | |
add_header 'Access-Control-Allow-Credentials' 'true'; | |
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS'; | |
# | |
# Custom headers and headers various browsers *should* be OK with but aren't | |
# | |
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; | |
# | |
# Tell client that this pre-flight info is valid for 20 days | |
# | |
add_header 'Access-Control-Max-Age' 1728000; | |
add_header 'Content-Type' 'text/plain charset=UTF-8'; | |
add_header 'Content-Length' 0; | |
return 204; | |
} | |
set $cors_method 0; | |
if ($request_method = 'GET') { | |
set $cors_method 1; | |
} | |
if ($request_method = 'PUT') { | |
set $cors_method 1; | |
} | |
if ($request_method = 'POST') { | |
set $cors_method 1; | |
} | |
if ($request_method = 'DELETE') { | |
set $cors_method 1; | |
} | |
if ($cors_method = 1) { | |
add_header 'Access-Control-Allow-Origin' '*' always; | |
add_header 'Access-Control-Allow-Credentials' 'true'; | |
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS'; | |
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; | |
} | |
{{ end }} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment