From a6c785f70974bb27107907aeb063ebd18ceca3ff Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Mon, 20 Apr 2026 15:15:26 +0800 Subject: [PATCH] feat(rust): Add Config::header() for custom HTTP and WebSocket headers Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 1 + rust/src/config.rs | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f611de57..324410f2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Added +- **Rust:** `Config::header(key, value)` builder method to inject custom headers into every HTTP request and WebSocket upgrade request. - **Rust, Python:** `ContentContext` adds three new methods: - `topic_detail(topic_id)` — get detail of a single topic. - `list_topic_replies(opts)` — list replies for a topic, with optional page/size filtering. diff --git a/rust/src/config.rs b/rust/src/config.rs index 48b3eb1b6..0d2c6a7ec 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -6,7 +6,7 @@ use std::{ sync::Arc, }; -pub(crate) use http::{HeaderValue, Request, header}; +pub(crate) use http::{HeaderName, HeaderValue, Request, header}; use longbridge_httpcli::{HttpClient, HttpClientConfig, is_cn}; use longbridge_oauth::OAuth; use num_enum::IntoPrimitive; @@ -127,6 +127,8 @@ pub struct Config { pub(crate) enable_print_quote_packages: bool, pub(crate) language: Language, pub(crate) log_path: Option, + /// Extra headers injected into every HTTP and WebSocket upgrade request. + pub(crate) custom_headers: HashMap, } /// Reads an env var by trying `LONGBRIDGE_` first, then falling back @@ -218,6 +220,7 @@ impl Config { push_candlestick_mode: extras.push_candlestick_mode, enable_print_quote_packages: extras.enable_print_quote_packages, log_path: extras.log_path, + custom_headers: Default::default(), } } @@ -266,6 +269,7 @@ impl Config { push_candlestick_mode: extras.push_candlestick_mode, enable_print_quote_packages: extras.enable_print_quote_packages, log_path: extras.log_path, + custom_headers: Default::default(), } } @@ -320,6 +324,7 @@ impl Config { push_candlestick_mode: extras.push_candlestick_mode, enable_print_quote_packages: extras.enable_print_quote_packages, log_path: extras.log_path, + custom_headers: Default::default(), }) } @@ -419,7 +424,12 @@ impl Config { config = config.http_url(url.clone()); } - HttpClient::new(config).header(header::ACCEPT_LANGUAGE, self.language.as_str()) + let mut client = + HttpClient::new(config).header(header::ACCEPT_LANGUAGE, self.language.as_str()); + for (key, value) in &self.custom_headers { + client = client.header(key.as_str(), value.as_str()); + } + client } fn create_ws_request(&self, url: &str) -> tokio_tungstenite::tungstenite::Result> { @@ -428,6 +438,14 @@ impl Config { header::ACCEPT_LANGUAGE, HeaderValue::from_str(self.language.as_str()).unwrap(), ); + for (key, value) in &self.custom_headers { + if let (Ok(name), Ok(val)) = ( + HeaderName::from_bytes(key.as_bytes()), + HeaderValue::from_str(value), + ) { + request.headers_mut().append(name, val); + } + } Ok(request) } @@ -471,6 +489,13 @@ impl Config { self } + /// Add a custom header to every HTTP request and WebSocket upgrade request. + #[must_use] + pub fn header(mut self, key: impl Into, value: impl Into) -> Self { + self.custom_headers.insert(key.into(), value.into()); + self + } + /// Set the HTTP endpoint URL in place. pub fn set_http_url(&mut self, url: impl Into) { self.http_url = Some(url.into());