Skip to content

Instantly share code, notes, and snippets.

@sethlopezme
Last active August 4, 2017 21:49
Show Gist options
  • Save sethlopezme/ea921ab51ef2c94d8de4fe8f9e7dd548 to your computer and use it in GitHub Desktop.
Save sethlopezme/ea921ab51ef2c94d8de4fe8f9e7dd548 to your computer and use it in GitHub Desktop.
extern crate reqwest;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_urlencoded;
use std::collections::HashSet;
use std::fmt;
use serde::Serializer;
#[derive(Debug)]
pub struct Client;
impl Client {
pub fn code_authorization_url_builder() -> AuthorizationUrlBuilder {
AuthorizationUrlBuilder {
client_id: None,
compact: false,
origin: None,
duration: None,
redirect_uri: None,
response_type: AuthorizationResponseType::Code,
scope: None,
state: None,
}
}
}
#[derive(Debug)]
pub struct AuthorizationUrlBuilder {
client_id: Option<String>,
compact: bool,
duration: Option<AuthorizationDuration>,
origin: Option<String>,
redirect_uri: Option<String>,
response_type: AuthorizationResponseType,
scope: Option<HashSet<Scope>>,
state: Option<String>,
}
impl AuthorizationUrlBuilder {
pub fn client_id(&mut self, client_id: String) -> &mut Self {
self.client_id = Some(client_id);
self
}
pub fn compact(&mut self, compact: bool) -> &mut Self {
self.compact = compact;
self
}
pub fn duration(&mut self, duration: AuthorizationDuration) -> &mut Self {
self.duration = Some(duration);
self
}
pub fn origin(&mut self, origin: String) -> &mut Self {
self.origin = Some(origin);
self
}
pub fn redirect_uri(&mut self, redirect_uri: String) -> &mut Self {
self.redirect_uri = Some(redirect_uri);
self
}
pub fn scope(&mut self, scope: HashSet<Scope>) -> &mut Self {
self.scope = Some(scope);
self
}
pub fn state(&mut self, state: String) -> &mut Self {
self.state = Some(state);
self
}
pub fn build(&self) -> Result<String, String> {
let client_id = Clone::clone(self.client_id.as_ref().ok_or(String::from(
"client_id must be initialized",
))?);
let compact = if self.compact { ".compact" } else { "" };
let duration = match self.response_type {
AuthorizationResponseType::Code => {
Clone::clone(&self.duration).or(Some(AuthorizationDuration::Temporary))
}
_ => None,
};
let origin = Clone::clone(self.origin.as_ref().unwrap_or(
&String::from("localhost"),
));
let redirect_uri = Clone::clone(self.redirect_uri.as_ref().ok_or(String::from(
"redirect_uri must be initialized",
))?);
let response_type = Clone::clone(&self.response_type);
let scope = Clone::clone(self.scope.as_ref().unwrap_or(
&[Scope::Identity].iter().cloned().collect(),
));
let state = Clone::clone(self.state.as_ref().ok_or(
String::from("state must be initialized"),
)?);
let query_parameters = serde_urlencoded::to_string(AuthorizationUrlQueryParameters {
client_id: client_id,
duration: duration,
redirect_uri: redirect_uri,
response_type: response_type,
scope: scope,
state: state,
}).unwrap();
Ok(format!(
"{}/api/v1/authorize{}?{}",
origin,
compact,
query_parameters
))
}
}
// ...
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builds_valid_code_authorization_urls() {
let mut builder = Client::code_authorization_url_builder()
.client_id(String::from("abc123"))
.redirect_uri(String::from("localhost"))
.scope(
[Scope::Identity, Scope::Subscribe]
.iter()
.cloned()
.collect::<HashSet<Scope>>(),
)
.state(String::from("random_state_123"));
let expected = Ok(String::from(
"https://localhost/api/v1/authorize\
?client_id=abc123\
&duration=temporary\
&redirect_uri=localhost\
&response_type=code\
&scope=*\
&state=random_state_123",
));
let actual = builder.build();
assert_eq!(expected, actual);
// changes to the builder values and more asserts here
}
}
@sethlopezme
Copy link
Author

sethlopezme commented Aug 4, 2017

I've included the error below. I've removed irrelevant code, so the line numbers are different. Line 256 in the error is line 128 in the gist above.

error[E0597]: borrowed value does not live long enough
   --> src/lib.rs:265:53
    |
256 |         let mut builder = Client::code_authorization_url_builder()
    |                           ---------------------------------------- temporary value created here
...
265 |             .state(String::from("random_state_123"));
    |                                                     ^ temporary value dropped here while still borrowed
...
314 |     }
    |     - temporary value needs to live until here
    |
    = note: consider using a `let` binding to increase its lifetime

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment