我使用 Caddy 作为我的 VPS 上的代理服务器,
这是我的 Caddyfile 配置:
https://api.yuhenabc.com {
gzip
tls /etc/ssl/caddy/chained.crt /etc/ssl/caddy/private.key
proxy / 127.0.0.1:5000 {
header_downstream -Server
}
}
配置正常,你也可以使用其他的,
问题是代理后的标头是“小写”,
例如“Content-Type”==>“content-type”
那么,有没有办法阻止 Caddy 将首字母大写?
使用 curl 查看差异:
~ curl -I https://agent.yuhenabc.com/
HTTP/2 200
accept-ranges: bytes
content-type: text/html
date: Sun, 04 Aug 2019 01:55:34 GMT
etag: "2d-573507058d0c0"
last-modified: Mon, 13 Aug 2018 12:43:23 GMT
server: Caddy
content-length: 45
原来的:
~ curl -I http://127.0.0.1:5000
HTTP/1.1 200 OK
Date: Sun, 04 Aug 2019 02:19:06 GMT
Server: Apache/2.4.34 (Unix) LibreSSL/2.5.5 PHP/7.1.23
Last-Modified: Mon, 13 Aug 2018 12:43:23 GMT
ETag: "2d-573507058d0c0"
Accept-Ranges: bytes
Content-Length: 45
Content-Type: text/html
答案1
这个是正常的。
在 HTTP/1.x 中,标头名称不区分大小写. 应用程序是必需的接受Content-Type
、content-type
和甚至CoNtEnT-tYpE
作为相同的标题。
RFC 7230:3.2. 标头字段
每个标头字段由一个不区分大小写的字段名称(后跟冒号(“:”))、可选的前导空格、字段值和可选的尾随空格组成。
HTTP/2 也是如此,但标头还总是 以小写形式发送根据规范。由于 cURL 和 Caddy 都支持 HTTP/2 并尽可能使用它,因此您将始终看到全小写的标头 - 任何其他内容都会违反协议的规范。
RFC 7540:8.1.2. HTTP 标头字段
与 HTTP/1.x 一样,标头字段名称是 ASCII 字符串,以不区分大小写的方式进行比较。但是,在 HTTP/2 中,标头字段名称在编码之前必须转换为小写。包含大写标头字段名称的请求或响应必须被视为格式错误。
答案2
如果你真的非常勇敢,你可以用 Golang 1.19.5 创建一个新的 GOROOT,并将这四个文件替换为我制作的这个 Golang fork:
- src/net/http/header.go
- src/net/http/request.go
- src/net/http/server.go
- src/net/textproto/reader.go
然后,使用指向你的 GOROOT 的 xcaddy 构建 Caddy:
GOROOT=/home/porech/my-custom-goroot/go1.19.5 XCADDY_WHICH_GO=/home/porech/my-custom-goroot/go1.19.5/bin/go xcaddy build
我当时非常绝望,我绝对需要这个,我建议你只有在同样的情况下才这样做。我在生产中使用它并且它有效,但可能存在我不知道的重要副作用!