diff options
author | Vika <vika@fireburn.ru> | 2024-08-04 21:37:40 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2024-08-17 16:05:41 +0300 |
commit | 5d7e852c078506c30ea5d5d03da659c66a516559 (patch) | |
tree | 344d31c7cfb5bdd4c41b0a6948bfe92e2cbc0f1f | |
parent | 63f56b43e72a602c765f44b71df6615bd5ce139b (diff) | |
download | kittybox-5d7e852c078506c30ea5d5d03da659c66a516559.tar.zst |
kittybox-indieauth: AuthorizationRequest::into_query_pairs()
This is a more efficient way of appending to a query string, as it avoids a needless copy and borrows most things instead. We can't really avoid copying here, since we'll need to write to the query string, but we can avoid an extra copy by borrowing most of our way through.
-rw-r--r-- | indieauth/src/lib.rs | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/indieauth/src/lib.rs b/indieauth/src/lib.rs index 05122b0..741eb81 100644 --- a/indieauth/src/lib.rs +++ b/indieauth/src/lib.rs @@ -18,6 +18,8 @@ //! //! [indieauth]: https://indieauth.spec.indieweb.org/20220212/ //! [`axum`]: https://github.com/tokio-rs/axum +use std::borrow::Cow; + use serde::{Serialize, Deserialize}; use url::Url; @@ -302,7 +304,7 @@ impl AsRef<str> for State { /// .parse() /// .unwrap(); /// -/// url.set_query(Some(&serde_urlencoded::to_string(request).unwrap())); +/// url.query_pairs_mut().extend_pairs(request.as_query_pairs().iter()); /// /// // Open a user's browser to navigate to the authorization endpoint page... /// ``` @@ -336,6 +338,40 @@ pub struct AuthorizationRequest { pub me: Option<Url>, } +impl AuthorizationRequest { + /// Transform this authorization request into a vector of string + /// pairs suitable into serialization into a query string. + /// + /// This is a bit more efficient than using serde, since it avoids + /// a deserialization an borrows where possible. + /// + /// (In the current implementation, only the scope field is owned.) + pub fn as_query_pairs(&'_ self) -> Vec<(&'static str, Cow<'_, str>)> { + let mut v = vec![ + ("response_type", Cow::Borrowed(self.response_type.as_str())), + ("client_id", Cow::Borrowed(self.client_id.as_str())), + ("redirect_uri", Cow::Borrowed(self.redirect_uri.as_str())), + ("code_challenge", Cow::Borrowed(self.code_challenge.as_str())), + ("code_challenge_method", Cow::Borrowed(self.code_challenge.method().as_str())), + ("state", Cow::Borrowed(self.state.as_ref())) + ]; + + if let Some(ref scope) = self.scope { + v.push( + ("scope", Cow::Owned(scope.to_string())) + ); + } + + if let Some(ref me) = self.me { + v.push( + ("me", Cow::Borrowed(me.as_str())) + ); + } + + v + } +} + /// An authorization request that must be POSTed to an IndieAuth /// endpoint together with a token with a scope of /// `request_external_token:<scope>` to request external tokens with |