以下是gist.github.com支援reverse proxied APIs的範例:3 I8 x& o; K8 q9 M! d9 E: i& k0 L0 t5 c
" d$ R* H$ ~+ \) U, g0 t& Z* {9 |4 B
# CORS header support8 R+ g& M. `$ x3 [
#
9 V* C5 N4 Z% j! }0 t. I" t3 X# One way to use this is by placing it into a file called "cors_support"
2 U" F2 {. L- q3 {# under your Nginx configuration directory and placing the following
+ j: V% l# B/ E1 R7 Y7 j7 [7 U# statement inside your **location** block(s):
5 ?- j+ `- i+ Q+ J- w' Q#$ {7 _1 [. _ `
# include cors_support;8 U, J5 q5 r- d- h w/ c: J
#* q1 n* h. G5 s0 ~1 \( ^
# As of Nginx 1.7.5, add_header supports an "always" parameter which
" v9 ^* i( e5 m1 m8 H5 w b/ Y# allows CORS to work if the backend returns 4xx or 5xx status code.7 I+ O. x# q8 i% @% X
#
! X+ ?: |" I$ L# For more information on CORS, please see: http://enable-cors.org/( K& s9 M% B0 N, g+ y4 V) z
# Forked from this Gist: https://gist.github.com/michiel/1064640
* D) A) n- u$ N#
+ d, z! r6 p. S7 T3 b) R7 s. M7 ^; I: M& [: R6 r
set $cors '';: _$ @, r W: y3 W$ k7 C# ?
if ($http_origin ~ '^https?://(localhost|www\.yourdomain\.com|www\.yourotherdomain\.com)$') {' r4 B, @4 d( A6 l
set $cors 'true';
/ A; y: I) q; z9 X5 G}
8 Y2 f3 D$ E3 S1 f/ v* ?, d/ d. [# u/ Z5 f* ]* _
if ($cors = 'true') {/ f1 h- C" `4 }' b) @6 ^) ]& \# L+ B
add_header 'Access-Control-Allow-Origin' "$http_origin" always; K$ s* M/ p5 T6 f3 `( k3 k6 U
add_header 'Access-Control-Allow-Credentials' 'true' always;+ b" u u6 C4 x A: e
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;( P' t; u m# |% Q. z
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;$ z- P8 g g1 c
# required to be able to read Authorization header in frontend
) p: D- ]3 |! h" A9 Y1 H #add_header 'Access-Control-Expose-Headers' 'Authorization' always;6 j! E' K [; t/ I' L0 S
}. j4 R8 d: q; G1 u& s
/ B0 F6 r9 j D+ W5 Aif ($request_method = 'OPTIONS') {; j7 w3 q8 U8 J. ~
# Tell client that this pre-flight info is valid for 20 days/ c0 T/ u+ ~$ O" X1 C: _5 `
add_header 'Access-Control-Max-Age' 1728000;
& e8 V6 c- H& x' ^% Q! {1 ~+ { add_header 'Content-Type' 'text/plain charset=UTF-8';
7 T+ C% a+ g/ C9 m7 x: W% I add_header 'Content-Length' 0;% \4 j( u; v, \" L+ [7 i
return 204;
: y( k1 a6 r. W/ J" q} https://gist.github.com/Stanback/7145487#file-nginx-conf 的討論範例:* d/ D" ~. q5 V% H q8 X9 c i* i
if ( $request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|PATCH|DELETE)$ ) { return 444;) k3 g, `$ R2 O
}. z6 ^* {. X9 m3 G4 ^$ F
set $origin $http_origin;
/ W$ E$ i6 @0 m l/ z1 s* jif ($origin !~ '^https?://(subdom1|subdom2)\.yourdom\.zone$') {
7 S! y4 Y# t6 R% o o set $origin 'https://default.yourdom.zone';3 g( l- I) `# {# R" b
}
( D* [% i0 G) [8 A( [if ($request_method = 'OPTIONS') {6 e2 @* U+ j2 O: b6 x
add_header 'Access-Control-Allow-Origin' "$origin" always;
+ f7 U$ u+ d. v6 u U add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always;, {+ A$ ^. [: `' n* I- u1 U2 f
add_header 'Access-Control-Allow-Headers' 'Content-Type, Accept, Authorization' always;' v! N: z. K! k" M: A, k
add_header 'Access-Control-Allow-Credentials' 'true' always;
* E! M) \% ^$ F' q y- h/ f add_header Access-Control-Max-Age 1728000; #20 days 0 G8 i# d7 m- M4 M, `2 h9 n, O$ W
add_header Content-Type 'text/plain charset=UTF-8';
6 o# f" ^4 q6 q* q, x+ {: k add_header Content-Length 0;
D9 A& X: X4 [ return 204;
' w! O5 k5 ]! b) I}
! E& j; K) Z ` w& kif ($request_method ~ '(GET|POST|PATCH|PUT|DELETE)') {+ C6 D! w: Z* `; N' R& D7 a* v: o6 _
add_header Access-Control-Allow-Origin "$origin" always;
" n8 }3 S8 N, k; `6 h- }- `$ L add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always;
o- G, `* n# X- C add_header Access-Control-Allow-Headers 'Content-Type, Accept, Authorization' always;
q' Q) s4 ?# Z add_header Access-Control-Allow-Credentials true always; g: x$ ^2 B- r
} Access-Control-Allow-Origin Multiple Origin Domains? 的例子:# based on https://gist.github.com/4165271/0 H9 L5 \$ k- `) N: y3 H) l
#" }& i) n! W# Q6 f6 A6 |! l
# Slightly tighter CORS config for nginx0 X6 L) O7 B! g" W
#! v! a! \5 W5 y" j& d% }- A. ?' H
# A modification of https://gist.github.com/1064640/ to include a white-list of URLs. a$ n+ y! i% v: ^
#5 i: D$ v% U8 \0 ]) F3 K
# Despite the W3C guidance suggesting that a list of origins can be passed as part of
: u8 J+ e/ F1 ]4 P( p5 c# Access-Control-Allow-Origin headers, several browsers (well, at least Firefox)
, Y0 [' t1 D. M: T8 w u( y# don't seem to play nicely with this.
- s3 a9 W/ v( N% h5 S#
( y/ j! ]/ E! w% j3 G! p% e# To avoid the use of 'Access-Control-Allow-Origin: *', use a simple-ish whitelisting
, q9 `2 ^! H1 b2 d5 a7 s+ L# method to control access instead.
" c1 B/ x2 T. G; ~2 [, z6 i#
! P F% o, Z" \) o' Y( ]4 @' r# NB: This relies on the use of the 'Origin' HTTP Header.7 H- b6 o2 ]% K$ a; p4 B
3 X2 m. {7 B% @; o* L9 o
location / {
4 J. ?0 s4 w9 v1 k& U# y
0 a- _2 \% s2 D$ J if ($http_origin ~* (^https?://([^/]+\.)*(domainone|domaintwo)\.com$)) {
6 \ Q% G# i) N2 `% [5 V set $cors "true";! B2 b$ `: X2 j
}
2 K7 f: u- F( G/ q4 h, N& k2 e
: f" x- {: W8 P3 ~9 v # Nginx doesn't support nested If statements. This is where things get slightly nasty.! P& T) d* Y" s- F$ s# o9 s& L! ?* O
# Determine the HTTP request method used
s( ~ {' o0 h$ X/ c o" m! p if ($request_method = 'OPTIONS') {/ Y# a+ r {' [! z8 J3 |
set $cors "${cors}options";8 P6 V$ z8 g6 V% _, H; V
}( L( ^: X& f5 d1 S6 s3 h# X
if ($request_method = 'GET') {! h. d( \% e% ~8 V0 Z1 E8 J; _
set $cors "${cors}get";
1 G$ K/ v; M( x7 g7 B" `5 K1 C( ] }4 A, v X* Q. K+ m6 j
if ($request_method = 'POST') {
b( I7 c) z( ^# c. p5 z8 q, \ set $cors "${cors}post";
4 t0 W; e8 m! T+ {9 k' V& Y } T" F% W6 n- g
$ V6 {& W+ Z. K( Q% K3 x/ ~1 ? if ($cors = "true") {
/ f, h1 Q5 t/ P3 l0 T4 J0 O) a # Catch all incase there's a request method we're not dealing with properly+ P( K2 V1 x$ K- j# L: c8 m
add_header 'Access-Control-Allow-Origin' "$http_origin";2 O4 E$ S# I0 l" r
}
9 b m+ d/ K3 z
. x! T7 \7 W) i; ?5 k0 @& S if ($cors = "trueget") {( v, |, T2 L+ {+ N) u: c
add_header 'Access-Control-Allow-Origin' "$http_origin";
' q% X8 s$ i: v7 o' q0 y+ ~3 g% q add_header 'Access-Control-Allow-Credentials' 'true';) o3 r0 l% ]$ j3 O) W
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
+ c! u2 b5 M6 |9 D3 V7 X add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';/ d3 c: w( ^/ l+ B2 t) W% Z: v
}
$ t: X4 V* _+ C5 {$ ^8 I P2 i# `/ D/ r
if ($cors = "trueoptions") {
$ A, f% n n- ~2 x6 w6 {) R add_header 'Access-Control-Allow-Origin' "$http_origin";
P' Y; Y: t4 n3 O
" i2 f5 J' r( q8 e, H+ `" ` #" d8 d( K# y6 s$ ~; J: G
# Om nom nom cookies& b% s, M4 Q3 T; K: q
#( g+ ~7 n1 M2 M) g
add_header 'Access-Control-Allow-Credentials' 'true';
7 Q' L% h' c4 L" N' F$ u add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
' U4 b7 p2 l8 V6 q+ \* i
4 w) W% k& ~7 S5 q9 M #: q; P2 b& B, [* `/ j
# Custom headers and headers various browsers *should* be OK with but aren't( C" j& \$ r6 w; V
#
0 O9 g. }$ _; ?) S4 D; X add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';! d9 H; x$ _1 }& E6 [; [
) ~+ U# W3 H6 H5 G& R$ h: U/ w #6 g) G, w$ Y1 q# P7 E' A# c
# Tell client that this pre-flight info is valid for 20 days. f$ V. f9 A5 }% P" q8 ~1 n( B
#
$ t i* E/ A1 E: f0 U; h, k add_header 'Access-Control-Max-Age' 1728000;- |) E# w& h2 S- c v
add_header 'Content-Type' 'text/plain charset=UTF-8';
4 A* w5 X: s% v% L; v- W4 O add_header 'Content-Length' 0;
" ?# g3 r% X5 H3 o9 i" ] return 204;1 S( G2 g9 u; p" d
}8 L" @ Q9 X7 Y6 ^
) a, Z) g; h8 X- W4 O6 E! l T0 V; R
if ($cors = "truepost") {, u; g% ^& v7 t* N$ M
add_header 'Access-Control-Allow-Origin' "$http_origin";3 Z. `6 t6 z4 g( u; P# j) E: R
add_header 'Access-Control-Allow-Credentials' 'true';8 s* I! r( N2 p7 R# W _
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
( q4 F2 s% o. J add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';9 l- Z% M" u F5 h1 R
}
: \ l9 d- B, G/ r! \0 N& S+ f
, A+ Z( A$ P8 j% C/ x% j' E} 0 Y3 c7 z; }! m
7 P5 ?# K0 _3 E/ n |4 X
|
|