Skip to content

Commit d4116ea

Browse files
sachiniyerclaude
andcommitted
refactor: use serde_urlencoded for query parameters
Replace manual url.query_pairs_mut().append_pair(...) pattern in list_bugs and list_repos with typed query structs serialized via serde_urlencoded. This makes the query parameter contract explicit and type-checked, and removes the direct url crate dependency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c25f024 commit d4116ea

3 files changed

Lines changed: 29 additions & 27 deletions

File tree

‎Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ clap = { version = "4.5", features = ["derive", "cargo", "env"] }
1919
# HTTP client
2020
reqwest = { version = "0.13", features = ["json"] }
2121
tokio = { version = "1.0", features = ["rt-multi-thread", "macros"] }
22-
url = "2.5"
2322

2423
# Serialization
2524
serde = { version = "1.0", features = ["derive"] }
2625
serde_json = "1.0"
26+
serde_urlencoded = "0.7"
2727
csv = "1.4"
2828

2929
# Error handling

‎src/api/client.rs‎

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use anyhow::{bail, Context, Result};
22
use colored::*;
33
use semver::{Version, VersionReq};
4-
use serde::Deserialize;
5-
use url::Url;
4+
use serde::{Deserialize, Serialize};
65

76
use super::types::*;
87

@@ -140,22 +139,24 @@ impl ApiClient {
140139
limit: u32,
141140
offset: u32,
142141
) -> Result<BugsResponse> {
143-
let mut url = Url::parse(&format!("{}/public/v1/bugs", self.base_url))?;
144-
{
145-
let mut query = url.query_pairs_mut();
146-
query.append_pair("repo_id", &repo_id.to_string());
147-
query.append_pair("limit", &limit.to_string());
148-
query.append_pair("offset", &offset.to_string());
149-
if let Some(s) = status {
150-
let value = serde_json::to_value(s)?;
151-
if let Some(status_str) = value.as_str() {
152-
query.append_pair("status", status_str);
153-
}
154-
}
142+
#[derive(Serialize)]
143+
struct ListBugsQuery<'a> {
144+
repo_id: &'a str,
145+
limit: u32,
146+
offset: u32,
147+
#[serde(skip_serializing_if = "Option::is_none")]
148+
status: Option<&'a BugReviewState>,
155149
}
156-
let path_and_query = format!("{}?{}", url.path(), url.query().unwrap_or(""));
157-
self.request(reqwest::Method::GET, &path_and_query, None)
158-
.await
150+
151+
let query = ListBugsQuery {
152+
repo_id: repo_id.as_str(),
153+
limit,
154+
offset,
155+
status,
156+
};
157+
let query_string = serde_urlencoded::to_string(&query)?;
158+
let path = format!("/public/v1/bugs?{}", query_string);
159+
self.request(reqwest::Method::GET, &path, None).await
159160
}
160161

161162
pub async fn get_bug(&self, bug_id: &BugId) -> Result<Bug> {
@@ -181,15 +182,16 @@ impl ApiClient {
181182
}
182183

183184
pub async fn list_repos(&self, limit: u32, offset: u32) -> Result<ReposResponse> {
184-
let mut url = Url::parse(&format!("{}/public/v1/repos", self.base_url))?;
185-
{
186-
let mut query = url.query_pairs_mut();
187-
query.append_pair("limit", &limit.to_string());
188-
query.append_pair("offset", &offset.to_string());
185+
#[derive(Serialize)]
186+
struct ListReposQuery {
187+
limit: u32,
188+
offset: u32,
189189
}
190-
let path_and_query = format!("{}?{}", url.path(), url.query().unwrap_or(""));
191-
self.request(reqwest::Method::GET, &path_and_query, None)
192-
.await
190+
191+
let query = ListReposQuery { limit, offset };
192+
let query_string = serde_urlencoded::to_string(&query)?;
193+
let path = format!("/public/v1/repos?{}", query_string);
194+
self.request(reqwest::Method::GET, &path, None).await
193195
}
194196
}
195197

0 commit comments

Comments
 (0)