0%

Linux 使用 Caddy 解决 CORS 问题

发现 Nginx 可以通过 proxy_set_header 来解决 CORS 问题,Caddy 也可以通过 header 来解决。

代码

一般情况下的部署是这样的,但是没有转发后端接口

1
2
3
4
5
6
7
:80 {
header / {
Access-Control-Allow-Origin *
Access-Control-Allow-Methods GET, POST, OPTIONS
Access-Control-Allow-Headers Origin, X-Requested-With, Content-Type, Accept
}
}

如果需要转发后端接口,可以这样

1
2
3
4
5
6
7
8
: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
}

比较成熟的方案

一般方案

1
2
3
4
5
6
7
: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 *
}
}

带模块的方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(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 的情况下就不能实现动态的跨域了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(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
}

还有个写法是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(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-Credentialstrue,并且 Access-Control-Allow-Origin 的值不能为 *,需要设置为请求的域名。

参考

这个是占位符的文档,可以看到有很多占位符可以使用

这个是匹配器

这个是官方 Demo

Caddy 实战

还有个Whistle也可以解决跨域,这儿就不多说了