使用Rust调用Bybit接口遇HTTP/1.1无响应问题求助
问题:Bybit API请求在Rust中仅HTTP/1.0有效,HTTP/1.1无响应、HTTP/2触发CloudFront错误
尝试从Bybit交易所获取时间数据,curl用HTTP/1.1能正常返回结果,但自行编写的Rust代码只有使用HTTP/1.0时有效,用HTTP/1.1完全无响应,用HTTP/2会触发CloudFront错误,TLS实现依赖native-tls crate。
Curl命令
curl --trace dump.txt --http1.1 -H 'User-Agent:' -H 'Accept:' https://api.bybit.com/v5/market/time
问题中的Rust代码
use native_tls::TlsConnector; use std::io::{Read, Write}; use std::net::TcpStream; fn main() { // 建立TCP连接 let stream = TcpStream::connect("api.bybit.com:443").unwrap(); // 创建TLS连接器 let connector = TlsConnector::new().unwrap(); // 在TCP连接上完成TLS握手 let mut stream = connector.connect("api.bybit.com", stream).unwrap(); // 发送请求 let request = "GET /v5/market/time HTTP/1.1 Host: api.bybit.com "; stream.write_all(&request.as_bytes()).unwrap(); // 尝试刷新连接(无效果) stream.flush().unwrap(); stream.get_ref().flush().unwrap(); stream.flush().unwrap(); stream.get_ref().flush().unwrap(); // 读取响应 let mut buf = vec![]; loop { let cnt = stream.read(&mut buf).unwrap(); if cnt != 0 { print!("We got at least something:"); println!("{}", String::from_utf8_lossy(&buf)); break; } }; }
解决方案
1. HTTP/1.1无响应的核心原因
HTTP/1.1默认使用持久连接,服务器不会主动关闭连接。你的读取逻辑仅在第一次读到非零数据时就终止循环,但实际上可能只读取了部分响应,或者服务器在等待后续请求,导致代码卡在read调用上。而HTTP/1.0默认是短连接,服务器返回响应后会关闭连接,所以read最终会返回0,刚好触发循环终止。
快速修复:强制使用短连接
在请求头中添加Connection: close,让服务器返回响应后主动关闭连接,同时修正读取逻辑,持续读取直到连接关闭:
// 修改请求内容,添加Connection头 let request = "GET /v5/market/time HTTP/1.1 Host: api.bybit.com Connection: close "; // 修正读取逻辑 let mut buf = vec![]; loop { let mut temp_buf = [0; 1024]; let cnt = stream.read(&mut temp_buf).unwrap(); if cnt == 0 { break; } buf.extend_from_slice(&temp_buf[0..cnt]); } println!("{}", String::from_utf8_lossy(&buf));
推荐方案:使用成熟HTTP客户端库
手动处理TCP/TLS/HTTP的底层细节容易出错,直接用reqwest(支持native-tls)可以自动处理连接、响应解析等逻辑:
use reqwest::Client; use native_tls::TlsConnector; use reqwest::tls::NativeTls; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // 配置native-tls连接器 let tls_connector = TlsConnector::new()?; let client = Client::builder() .use_native_tls() .tls_built_in_root_certs(false) .tls_connector(NativeTls::from(tls_connector)?) .build()?; let response = client.get("https://api.bybit.com/v5/market/time") .header("User-Agent", "") .header("Accept", "") .send() .await?; let body = response.text().await?; println!("{}", body); Ok(()) }
需要在Cargo.toml中添加依赖:
[dependencies] reqwest = { version = "0.11", features = ["native-tls", "json"] } tokio = { version = "1.0", features = ["full"] } native-tls = "0.2"
2. HTTP/2触发CloudFront错误的原因
Bybit API通过CloudFront分发,HTTP/2对请求的ALPN协商、TLS版本、请求头格式等要求更严格,手动实现HTTP/2复杂度极高。使用成熟客户端库可以自动处理这些细节,避免触发CloudFront的拦截规则。
内容的提问来源于stack exchange,提问作者user32660809




