发现 Nginx 可以通过 proxy_set_header
来解决 CORS 问题,Caddy 也可以通过 header
来解决。
代码
一般情况下的部署是这样的,但是没有转发后端接口
:80 {
header / {
Access-Control-Allow-Origin *
Access-Control-Allow-Methods GET, POST, OPTIONS
Access-Control-Allow-Headers Origin, X-Requested-With, Content-Type, Accept
}
}
如果需要转发后端接口,可以这样
:80 {
header /api/* {
Access-Control-Allow-Origin *
Access-Control-Allow-Methods GET, POST, OPTIONS
Access-Control-Allow-Headers Origin, X-Requested-With, Content-Type, Accept
}
reverse_proxy /api/* http://localhost:3000
}
比较成熟的方案
一般方案
:8088 {
reverse_proxy /* http://xxxx:80 {
header_up Host {http.reverse_proxy.upstream.hostport}
header_down Access-Control-Allow-Headers *
header_down Access-Control-Allow-Origin *
}
}
带模块的方案
(cors) {
@cors_preflight method OPTIONS
@cors header Origin {args.0}
handle @cors_preflight {
header Access-Control-Allow-Origin "{args.0}"
header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE"
header Access-Control-Allow-Headers "Content-Type"
header Access-Control-Max-Age "3600"
respond "" 204
}
handle @cors {
header Access-Control-Allow-Origin "{args.0}"
header Access-Control-Expose-Headers "Link"
}
}
example.com {
import cors https://example.com
reverse_proxy localhost:8080
}
这是网上看到的,但是存在一个问题就是写死的不够智能,比如 Access-Control-Allow-Origin
的值是 *
,在请求参数中有 Cookie 的情况下就不能实现动态的跨域了。
(cors) {
@cors_preflight method OPTIONS
@cors header Origin {http.request.header.Origin}
handle @cors_preflight {
header Access-Control-Allow-Origin {http.request.header.Origin}
header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE"
header Access-Control-Allow-Headers "Content-Type, x-xsrf-token"
header Access-Control-Max-Age "3600"
header Access-Control-Allow-Credentials true
respond "" 204
}
}
:8088 {
import cors http://localhost:8088
reverse_proxy http://192.168.234.49:8080
}
还有个写法是
(cors) {
@origin{args.0} header Origin {args.0}
header @origin{args.0} Access-Control-Allow-Origin "{args.0}"
header @origin{args.0} Access-Control-Allow-Headers "content-type, x-requested-with"
header @origin{args.0} Vary Origin
}
myawesomewebsite.com {
root * /srv/public/
file_server
header Access-Control-Allow-Methods "POST, GET, OPTIONS"
@options {
method OPTIONS
}
respond @options 204
import cors https://member.myawesomewebsite.com
import cors https://customer.myawesomewebsite.com
}
后记
如果请求参数中有 Cookie 的情况下,需要设置 Access-Control-Allow-Credentials
为 true
,并且 Access-Control-Allow-Origin
的值不能为 *
,需要设置为请求的域名。
参考
- https://caddyserver.com/docs/caddyfile/directives/reverse_proxy
- https://gist.github.com/ryanburnette/d13575c9ced201e73f8169d3a793c1a3
- https://caddyserver.com/docs/caddyfile/concepts
这个是占位符的文档,可以看到有很多占位符可以使用
- https://caddyserver.com/docs/conventions#placeholders
- https://caddyserver.com/docs/caddyfile/concepts#placeholders
这个是匹配器
这个是官方 Demo
Caddy 实战
还有个 Whistle 也可以解决跨域,这儿就不多说了