custom headers via --headers (#30)

* add custom headers via --headers

* add tests

* better parsing
This commit is contained in:
Chris Tate
2026-01-12 12:01:19 -06:00
committed by GitHub
parent 4f6fd8ec5c
commit 1a88d7f585
8 changed files with 347 additions and 7 deletions
+91 -2
View File
@@ -80,7 +80,14 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
} else {
format!("https://{}", url)
};
Ok(json!({ "id": id, "action": "navigate", "url": url }))
let mut nav_cmd = json!({ "id": id, "action": "navigate", "url": url });
// If --headers flag is set, include headers (scoped to this origin)
if let Some(ref headers_json) = flags.headers {
if let Ok(headers) = serde_json::from_str::<serde_json::Value>(headers_json) {
nav_cmd["headers"] = headers;
}
}
Ok(nav_cmd)
}
"back" => Ok(json!({ "id": id, "action": "back" })),
"forward" => Ok(json!({ "id": id, "action": "forward" })),
@@ -766,7 +773,13 @@ fn parse_set(rest: &[&str], id: &str) -> Result<Value, ParseError> {
context: "set headers".to_string(),
usage: "set headers <json>",
})?;
Ok(json!({ "id": id, "action": "headers", "headers": headers_json }))
// Parse the JSON string into an object
let headers: serde_json::Value = serde_json::from_str(headers_json)
.map_err(|_| ParseError::MissingArguments {
context: "set headers".to_string(),
usage: "set headers <json> (must be valid JSON object)",
})?;
Ok(json!({ "id": id, "action": "headers", "headers": headers }))
}
Some("credentials") | Some("auth") => {
let user = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
@@ -886,6 +899,7 @@ mod tests {
full: false,
headed: false,
debug: false,
headers: None,
executable_path: None,
}
}
@@ -1013,6 +1027,81 @@ mod tests {
assert_eq!(cmd["url"], "https://example.com");
}
#[test]
fn test_navigate_with_headers() {
let mut flags = default_flags();
flags.headers = Some(r#"{"Authorization": "Bearer token"}"#.to_string());
let cmd = parse_command(&args("open api.example.com"), &flags).unwrap();
assert_eq!(cmd["action"], "navigate");
assert_eq!(cmd["url"], "https://api.example.com");
assert_eq!(cmd["headers"]["Authorization"], "Bearer token");
}
#[test]
fn test_navigate_with_multiple_headers() {
let mut flags = default_flags();
flags.headers = Some(r#"{"Authorization": "Bearer token", "X-Custom": "value"}"#.to_string());
let cmd = parse_command(&args("open api.example.com"), &flags).unwrap();
assert_eq!(cmd["headers"]["Authorization"], "Bearer token");
assert_eq!(cmd["headers"]["X-Custom"], "value");
}
#[test]
fn test_navigate_without_headers_flag() {
let cmd = parse_command(&args("open example.com"), &default_flags()).unwrap();
assert_eq!(cmd["action"], "navigate");
// headers should not be present when flag is not set
assert!(cmd.get("headers").is_none());
}
#[test]
fn test_navigate_with_invalid_headers_json() {
let mut flags = default_flags();
flags.headers = Some("not valid json".to_string());
let cmd = parse_command(&args("open api.example.com"), &flags).unwrap();
// Invalid JSON should result in no headers field (graceful handling)
assert!(cmd.get("headers").is_none());
}
// === Set Headers Tests ===
#[test]
fn test_set_headers_parses_json() {
let input: Vec<String> = vec![
"set".to_string(),
"headers".to_string(),
r#"{"Authorization":"Bearer token"}"#.to_string(),
];
let cmd = parse_command(&input, &default_flags()).unwrap();
assert_eq!(cmd["action"], "headers");
// Headers should be an object, not a string
assert!(cmd["headers"].is_object());
assert_eq!(cmd["headers"]["Authorization"], "Bearer token");
}
#[test]
fn test_set_headers_with_multiple_values() {
let input: Vec<String> = vec![
"set".to_string(),
"headers".to_string(),
r#"{"Authorization": "Bearer token", "X-Custom": "value"}"#.to_string(),
];
let cmd = parse_command(&input, &default_flags()).unwrap();
assert_eq!(cmd["headers"]["Authorization"], "Bearer token");
assert_eq!(cmd["headers"]["X-Custom"], "value");
}
#[test]
fn test_set_headers_invalid_json_error() {
let input: Vec<String> = vec![
"set".to_string(),
"headers".to_string(),
"not-valid-json".to_string(),
];
let result = parse_command(&input, &default_flags());
assert!(result.is_err());
}
#[test]
fn test_back() {
let cmd = parse_command(&args("back"), &default_flags()).unwrap();