我写的请求和curl一样,但没有收到任何响应,为什么?

后端开发 2026-07-09

我在尝试从Bybit交易所获取时间。curl能按预期工作,但我的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() {
    // Establish TCP connection
    let stream = TcpStream::connect("api.bybit.com:443").unwrap();

    // Create TlsConnector
    let connector = TlsConnector::new().unwrap();

    // Perform TLS handshake at TCP connection
    let mut stream = connector.connect("api.bybit.com", stream).unwrap();

    // Send requests
    let request = "GET /v5/market/time HTTP/1.1\r\nHost: api.bybit.com\r\n\r\n";

    stream.write_all(&request.as_bytes()).unwrap();

    // Changes nothing
    stream.flush().unwrap();
    stream.get_ref().flush().unwrap();
    stream.flush().unwrap();
    stream.get_ref().flush().unwrap();

    // Get response
    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;
        }
    };
}

解决方案

如 @SteffenUllrich所说

HTTP/1.1默认开启keep-alive,也就是说响应不会以TCP连接关闭作为结尾,而是保持TCP连接打开,等待下一次请求。

基于此我猜测服务器会对响应进行缓冲,直到连接应该被关闭才发送(见下方代码)。

use native_tls::TlsConnector;
use std::io::{Read, Write};
use std::net::TcpStream;

fn main() {
    // Establish TCP connection
    let stream = TcpStream::connect("api.bybit.com:443").unwrap();

    // Create TlsConnector
    let connector = TlsConnector::new().unwrap();

    // Perform TLS handshake at TCP connection
    let mut stream = connector.connect("api.bybit.com", stream).unwrap();

    // Send requests
    let request = "GET /v5/market/time HTTP/1.1\r\nHost: api.bybit.com\r\n\r\n";
    let last_request = "GET /v5/market/time HTTP/1.1\r\nHost: api.bybit.com\r\nConnection: close\r\n\r\n";

    stream.write_all(&request.as_bytes()).unwrap();
    stream.write_all(&request.as_bytes()).unwrap();
    stream.write_all(&last_request.as_bytes()).unwrap();

    // stream.flush().unwrap(); // no, it is not about manual flushing :)

    // Get response
    let mut res = vec![];
    // stream.shutdown().unwrap(); // use it before reading if you do not wanna send Connection header
                                  // shutdown forces server to send all packets it buffered
    stream.read_to_end(&mut res).unwrap();
    print!("{}", String::from_utf8_lossy(&res));
}

Header Connection: close 会强制服务器发送它缓冲的所有响应并关闭连接。

P. S.不确定所有服务器是否都会这样做,想测试的朋友可以试试看?

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章