Skip to content

Commit 42df0ac

Browse files
authored
Don't quote string values in query parameters (#747)
* Read params regardless of input presence Currently we only check for params added via `-f/--raw-field` and `-F/--field` when `self.input` is not empty. It is valid to pass parameters when no body has been set, set params independently of input. * Don't quote string values in query parameters We read string values into a `serde_json::Value::String` when parsing parameters, using its `Display` format when appending `{key}={value}` to the URI. This is incorrect as `Value::String` encloses the value with double quotes[0]. Use the wrapped string for `Value::String` values to avoid wrapping the string in quotes and reject `Value::Array` and `Value::Object` values as unrepresentable. Full URI before: https://oxide.sys.example.com/v1/instances?project=\"will\" Full URI after: https://oxide.sys.example.com/v1/instances?project=will [0] https://github.com/serde-rs/json/blob/3f1c6de4af28b1f6c5100da323f2bffaf7c2083f/README.md#L121-L127
1 parent e81f408 commit 42df0ac

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed

cli/src/cmd_api.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ use std::{
99
io::{Read, Write},
1010
};
1111

12-
use anyhow::{anyhow, Result};
12+
use anyhow::{anyhow, bail, Result};
1313
use async_trait::async_trait;
1414
use clap::Parser;
1515
use futures::{StreamExt, TryStreamExt};
1616
use oxide::Client;
1717
use serde::Deserialize;
18+
use serde_json::Value;
1819

1920
use crate::{print_nopipe, println_nopipe};
2021

@@ -150,19 +151,27 @@ impl crate::AuthenticatedCmd for CmdApi {
150151

151152
// Set this as our body.
152153
bytes = buf.clone();
154+
}
153155

154-
// Set our params to the query string.
155-
if !params.is_empty() {
156-
let mut query_string = String::new();
157-
for (key, value) in params {
158-
if !query_string.is_empty() {
159-
query_string.push('&');
156+
// Set our params to the query string.
157+
if !params.is_empty() {
158+
let mut query_string = String::new();
159+
for (key, value) in params {
160+
if !query_string.is_empty() {
161+
query_string.push('&');
162+
}
163+
match &value {
164+
Value::String(s) => query_string.push_str(&format!("{key}={s}")),
165+
Value::Bool(b) => query_string.push_str(&format!("{key}={b}")),
166+
Value::Number(n) => query_string.push_str(&format!("{key}={n}")),
167+
Value::Null => query_string.push_str(&format!("{key}=null")),
168+
Value::Array(_) | Value::Object(_) => {
169+
bail!("invalid query parameter value {}", value)
160170
}
161-
query_string.push_str(&format!("{}={}", key, value));
162171
}
163-
164-
endpoint_with_query = add_query_string(&endpoint_with_query, &query_string);
165172
}
173+
174+
endpoint_with_query = add_query_string(&endpoint_with_query, &query_string);
166175
}
167176

168177
let rclient = client.client();

cli/tests/test_api.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use predicates::prelude::*;
1010
use serde::Serialize;
1111
use serde_json::json;
1212

13-
/// Validate `oxide api` for a simple GET with parameters.
13+
/// Validate `oxide api` for a simple GET with parameters embedded in URI
14+
/// and via the `--raw-field` option.
1415
#[test]
1516
fn test_simple_api_call() {
1617
let server = MockServer::start();
@@ -37,7 +38,23 @@ fn test_simple_api_call() {
3738
.success()
3839
.stdout(predicate::str::diff("{\n \"a\": \"b\"\n}\n"));
3940

40-
mock.assert();
41+
Command::cargo_bin("oxide")
42+
.unwrap()
43+
.env("OXIDE_HOST", server.url(""))
44+
.env("OXIDE_TOKEN", "fake-token")
45+
.arg("api")
46+
.arg("-X")
47+
.arg("GET")
48+
.arg("/simple/test/call")
49+
.arg("--raw-field")
50+
.arg("param1=value1")
51+
.arg("-f")
52+
.arg("param2=value2")
53+
.assert()
54+
.success()
55+
.stdout(predicate::str::diff("{\n \"a\": \"b\"\n}\n"));
56+
57+
mock.assert_hits(2);
4158
}
4259

4360
#[derive(Serialize)]

0 commit comments

Comments
 (0)