Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions src/exchange/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,9 @@ mod tests {

/// Validate and normalise a URL override from a CLI flag or environment variable.
///
/// Accepts `http://` (for local test servers) and `https://` schemes only.
/// Accepts `https://`, `http://`, `wss://`, and `ws://` schemes.
/// Unencrypted schemes (`http://`, `ws://`) are restricted to localhost unless
/// `BITMEX_DANGER_ALLOW_ANY_URL_HOST=1` is set.
/// Returns `None` if `cli_flag` and `env_val` are both `None`, so callers fall
/// back to their compiled-in default.
pub fn resolve_url_override(
Expand All @@ -462,14 +464,14 @@ pub fn resolve_url_override(
let url = url::Url::parse(raw)?;
let scheme = url.scheme();

if scheme != "https" && scheme != "http" {
if !matches!(scheme, "https" | "http" | "wss" | "ws") {
return Err(BitmexError::Validation { message: format!(
"URL must use https:// or http://, got: {raw}"
"URL must use https://, http://, wss://, or ws://, got: {raw}"
) });
}

// Block arbitrary internet hosts unless the danger env var is set.
if scheme == "http" {
// Block arbitrary internet hosts for unencrypted schemes unless the danger env var is set.
if matches!(scheme, "http" | "ws") {
let host = url.host_str().unwrap_or("");
let is_local = host == "localhost"
|| host == "127.0.0.1"
Expand All @@ -479,7 +481,7 @@ pub fn resolve_url_override(
env::var("BITMEX_DANGER_ALLOW_ANY_URL_HOST").is_ok_and(|v| v == "1");
if !is_local && !danger_allowed {
return Err(BitmexError::Validation { message: format!(
"http:// is only allowed for localhost/127.0.0.1 or when \
"{scheme}:// is only allowed for localhost/127.0.0.1 or when \
BITMEX_DANGER_ALLOW_ANY_URL_HOST=1 is set. Got: {raw}"
) });
}
Expand Down
16 changes: 11 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ pub struct Cli {
#[arg(long, global = true)]
pub api_url: Option<String>,

/// Override WebSocket URL.
#[arg(long, global = true)]
pub ws_url: Option<String>,

/// API key override (takes precedence over env/config).
#[arg(long, global = true)]
pub api_key: Option<String>,
Expand Down Expand Up @@ -435,11 +439,13 @@ pub(crate) async fn execute_command(ctx: &AppContext, command: Command) -> Resul
}

Command::Ws(args) => {
let ws_url = if ctx.testnet {
exchange::client::WS_TESTNET_URL.to_string()
} else {
exchange::client::WS_MAINNET_URL.to_string()
};
let ws_url = ctx.ws_url.clone().unwrap_or_else(|| {
if ctx.testnet {
exchange::client::WS_TESTNET_URL.to_string()
} else {
exchange::client::WS_MAINNET_URL.to_string()
}
});
let needs_auth = args.auth || args.topics.iter().any(|t| ws::is_private_topic(t));
let creds = if needs_auth {
config::resolve_credentials(
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ async fn main() {
};

let api_url = resolve(cli.api_url.as_deref(), "BITMEX_API_URL", "--api-url");
let ws_url = resolve(None, "BITMEX_WS_URL", "BITMEX_WS_URL");
let ws_url = resolve(cli.ws_url.as_deref(), "BITMEX_WS_URL", "--ws-url");

// Merge CLI --testnet with the active profile's testnet flag
let testnet = bitmex_cli::config::effective_testnet(cli.profile.as_deref(), cli.testnet);
Expand Down