我写的请求和curl一样,但没有收到任何响应,为什么?
我在尝试从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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。