You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

使用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

火山引擎 最新活动