错误信息
received corrupt message of type InvalidContentType
reqwest 把它显示在“error sending request for url (…): client error (Connect): received corrupt message of type InvalidContentType”的末尾;ureq 显示为“io: received corrupt message of type InvalidContentType”。基于 OpenSSL 的客户端会把同样的情况报告为“wrong version number”。
rustls (via reqwest, ureq, tonic) — rustls::Error::InvalidMessage(InvalidContentType): the peer's reply is not TLS
含义
rustls 把服务器响应的第一个字节当作 TLS 记录的内容类型来读取,却发现这个值不可能出现在任何 TLS 记录中。对端说的不是 TLS:典型情况是在通过 https:// 访问的端口上,HTTP 服务器用“HTTP/1.1 …”作答;或者是明文 gRPC 服务器;又或者是按普通 HTTP 处理请求的代理。
原因
用 https:// 访问普通 HTTP 端口
常见未启用 TLS 的本地开发服务器、边车容器或内部端口。
用 TLS 连接普通代理
偶见HTTPS_PROXY 被设为 https:// URL,而该代理与客户端之间只使用普通 HTTP 通信。
启用 TLS 的 gRPC 客户端连接明文服务器
偶见由 https:// 端点(或带 TLS 配置)创建的 tonic 通道,连接的却是未启用 TLS 的服务器。
修复方法
- 1.
弄清端口使用的协议
如果应答的是普通 HTTP,就改用 http://,或者连接服务器的 TLS 端口。
bash curl -si http://127.0.0.1:8080/ | head -1 # plain HTTP answers -> use http:// or the TLS port - 2.
让端点的协议与服务器一致
在受信任的网络中,连接明文 gRPC 服务器时使用 http:// 端点;其他情况下使用 https:// 并配置 TLS。
rust // tonic: use an http:// endpoint for plaintext servers, https:// + TLS config for TLS servers let channel = tonic::transport::Channel::from_static("http://127.0.0.1:50051").connect().await?;