使用Rust Tokio Tungstenite构建WebSocket客户端时遭遇400错误求助
使用tokio-tungstenite连接Coinbase WebSocket时出现400 Bad Request的解决方法
问题原因
Coinbase的WebSocket Feed服务器会校验请求的User-Agent头部,而tokio_tungstenite::connect_async默认不会携带该头部,导致服务器返回400 Bad Request。浏览器插件会自动添加合法的User-Agent,因此能正常连接。
解决方案
通过自定义HTTP握手请求,添加符合要求的User-Agent头部,使用tokio_tungstenite::client_async方法发起连接。
修改后的代码
use std::env; use futures::{SinkExt, StreamExt}; use tokio_tungstenite::{client_async, tungstenite::protocol::Message}; use hyper::{Request, header::USER_AGENT}; use hyper_tls::HttpsConnector; #[tokio::main] async fn main() { env::set_var("RUST_BACKTRACE", "1"); let url = "wss://ws-feed.exchange.coinbase.com"; let msg = r#" { "type": "subscribe", "product_ids": [ "ETH-USD" ], "channels": [ "level2", "heartbeat", { "name": "ticker", "product_ids": [ "ETH-USD" ] } ] }"#; // 构建HTTPS连接器 let https_connector = HttpsConnector::new(); let client = hyper::Client::builder().build::<_, hyper::Body>(https_connector); // 构造WebSocket握手请求,添加User-Agent头 let mut req = Request::get(url) .header(USER_AGENT, "rust-tokio-tungstenite-client/0.1") .body(hyper::Body::empty()) .unwrap(); // 添加WebSocket升级所需的标准头 tokio_tungstenite::add_websocket_headers(&mut req); match client_async(req, client).await { Ok((ws_stream, _)) => { let (mut write, mut read) = ws_stream.split(); match write.send(Message::Text(msg.to_string())).await { Ok(_) => println!("Message sent successfully"), Err(e) => println!("Failed to send message: {}", e), } while let Some(msg) = read.next().await { match msg { Ok(msg) => println!("Received: {}", msg), Err(e) => println!("Error reading message: {}", e), } } }, Err(e) => println!("Failed to connect: {}", e), } }
更新Cargo.toml依赖
需要补充hyper和hyper-tls依赖:
[dependencies] futures = "0.3" tokio = { version = "1", features = ["full"] } tokio-tungstenite = "0.15.0" hyper = "0.14" hyper-tls = "0.5"
说明
User-Agent头是解决问题的核心,你可以使用自定义标识,也可以使用贴近浏览器的标识(比如Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36)。client_async方法允许完全控制握手请求的头部,弥补了connect_async默认缺少必要头的缺陷。- 修改后重新运行代码,即可成功建立连接并接收Coinbase的WebSocket数据。
内容的提问来源于stack exchange,提问作者fourarms
相关产品推荐
相关产品推荐

