construct the URI path and query via typed Url

this probably either does too much or too little:
- could have fixed the double-slash thing by stripping trailing slash from the base uri or,
- if you like typed URLs, it probably makes sense to do a bigger refactor toward them.

...sidestepping adding the actual `url` dependency by using the one included with `reqwest`. maybe this is not what you want.

currently using `EncodeError::Other` instead of adding a variant to `EncodeError` itself because the parse error comes from `Url`, which we snuck in from `reqwest`, which isn't a dependency of the `-common` crate.

Changed files
+9 -6
crates
jacquard
src
+9 -6
crates/jacquard/src/client.rs
··· 10 10 use std::future::Future; 11 11 12 12 use bytes::Bytes; 13 - pub use error::{ClientError, Result}; 13 + pub use error::{ClientError, Result, TransportError}; 14 14 use http::{ 15 15 HeaderName, HeaderValue, Request, 16 16 header::{AUTHORIZATION, CONTENT_TYPE, InvalidHeaderValue}, ··· 152 152 R: XrpcRequest, 153 153 C: XrpcClient + ?Sized, 154 154 { 155 - // Build URI: base_uri + /xrpc/ + NSID 156 - let mut uri = format!("{}/xrpc/{}", client.base_uri(), R::NSID); 155 + // Configure the XRPC endpoint 156 + let mut url: reqwest::Url = client 157 + .base_uri() 158 + .parse() 159 + .map_err(|e| error::EncodeError::Other(format!("failed to parse base_uri: {e}").into()))?; 160 + url.set_path(&format!("/xrpc/{}", R::NSID)); 157 161 158 162 // Add query parameters for Query methods 159 163 if let XrpcMethod::Query = R::METHOD { 160 164 let qs = serde_html_form::to_string(&request).map_err(error::EncodeError::from)?; 161 165 if !qs.is_empty() { 162 - uri.push('?'); 163 - uri.push_str(&qs); 166 + url.set_query(Some(&qs)) 164 167 } 165 168 } 166 169 ··· 170 173 XrpcMethod::Procedure(_) => http::Method::POST, 171 174 }; 172 175 173 - let mut builder = Request::builder().method(method).uri(&uri); 176 + let mut builder = Request::builder().method(method).uri(&url.to_string()); 174 177 175 178 // Add Content-Type for procedures 176 179 if let XrpcMethod::Procedure(encoding) = R::METHOD {