[fractal] API: Implement (de)serializers for Url and Host types
- From: Daniel Garcia Moreno <danigm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] API: Implement (de)serializers for Url and Host types
- Date: Mon, 21 Oct 2019 09:33:29 +0000 (UTC)
commit 40b7ef9f0e11472dc31c42124c1cf46a1fa9362f
Author: Alejandro DomÃnguez <adomu net-c com>
Date: Wed Oct 2 10:14:26 2019 +0200
API: Implement (de)serializers for Url and Host types
This guarantees that the (de)serialized structs which
contain URLs in any of their fields will always have
a valid URL string and not just a generic one.
fractal-gtk/src/widgets/login.rs | 13 ++--
fractal-matrix-api/src/backend/mod.rs | 9 ++-
fractal-matrix-api/src/backend/user.rs | 34 ++++++++--
fractal-matrix-api/src/de.rs | 76 ++++++++++++++++++++++
fractal-matrix-api/src/lib.rs | 1 +
fractal-matrix-api/src/model/member.rs | 4 +-
fractal-matrix-api/src/model/room.rs | 4 +-
fractal-matrix-api/src/r0.rs | 48 +++++++++++++-
fractal-matrix-api/src/r0/account.rs | 7 +-
.../r0/contact/request_verification_token_email.rs | 7 +-
.../contact/request_verification_token_msisdn.rs | 7 +-
.../src/r0/directory/post_public_rooms.rs | 5 +-
fractal-matrix-api/src/r0/media/create.rs | 4 +-
fractal-matrix-api/src/r0/profile/get_profile.rs | 5 +-
.../src/r0/profile/set_avatar_url.rs | 4 +-
fractal-matrix-api/src/r0/search/user.rs | 4 +-
fractal-matrix-api/src/r0/server/domain_info.rs | 7 +-
.../src/r0/thirdparty/get_supported_protocols.rs | 11 +++-
fractal-matrix-api/src/ser.rs | 18 +++++
fractal-matrix-api/src/util.rs | 7 +-
20 files changed, 237 insertions(+), 38 deletions(-)
---
diff --git a/fractal-gtk/src/widgets/login.rs b/fractal-gtk/src/widgets/login.rs
index 71a1cf72..baef5d61 100644
--- a/fractal-gtk/src/widgets/login.rs
+++ b/fractal-gtk/src/widgets/login.rs
@@ -94,26 +94,23 @@ impl LoginWidget {
if !password.is_empty() && !username.is_empty() {
// take the user's homeserver value if the
// well-known request fails
- let hs_url = Url::parse(&txt);
-
- if hs_url.is_err() {
+ let mut homeserver_url = if let Ok(hs_url) = Url::parse(&txt) {
+ hs_url
+ } else {
let msg = i18n("Malformed server URL");
ErrorDialog::new(false, &msg);
return;
};
- let mut homeserver_url =
- hs_url.expect("hs_url must return earlier if it's Err");
let mut idserver = globals::DEFAULT_IDENTITYSERVER.clone();
match get_well_known(&txt) {
// TODO: Use Url everywhere
Ok(response) => {
info!("Got well-known response from {}: {:#?}", &txt, response);
- homeserver_url =
- Url::parse(&response.homeserver.base_url).unwrap_or(homeserver_url);
+ homeserver_url = response.homeserver.base_url;
idserver = response
.identity_server
- .and_then(|ids| Url::parse(&ids.base_url).ok())
+ .map(|ids| ids.base_url)
.unwrap_or(idserver);
}
Err(e) => info!("Failed to .well-known request: {:#?}", e),
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index d79fdf63..6c863dd2 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -110,16 +110,19 @@ impl Backend {
Ok(BKCommand::SetUserName(name)) => user::set_username(self, name),
Ok(BKCommand::GetThreePID) => user::get_threepid(self),
Ok(BKCommand::GetTokenEmail(identity, email, client_secret)) => {
- user::get_email_token(self, identity, email, client_secret)
+ let r = user::get_email_token(self, identity, email, client_secret);
+ bkerror2!(r, tx, BKResponse::GetTokenEmail);
}
Ok(BKCommand::GetTokenPhone(identity, phone, client_secret)) => {
- user::get_phone_token(self, identity, phone, client_secret)
+ let r = user::get_phone_token(self, identity, phone, client_secret);
+ bkerror2!(r, tx, BKResponse::GetTokenPhone);
}
Ok(BKCommand::SubmitPhoneToken(_, client_secret, sid, token)) => {
user::submit_phone_token(self, client_secret, sid, token)
}
Ok(BKCommand::AddThreePID(identity, client_secret, sid)) => {
- user::add_threepid(self, identity, client_secret, sid)
+ let r = user::add_threepid(self, identity, client_secret, sid);
+ bkerror2!(r, tx, BKResponse::AddThreePID);
}
Ok(BKCommand::DeleteThreePID(medium, address)) => {
user::delete_three_pid(self, medium, address)
diff --git a/fractal-matrix-api/src/backend/user.rs b/fractal-matrix-api/src/backend/user.rs
index e990f782..f8e50d9d 100644
--- a/fractal-matrix-api/src/backend/user.rs
+++ b/fractal-matrix-api/src/backend/user.rs
@@ -12,6 +12,7 @@ use crate::util::ContentType;
use crate::util::ResultExpectLog;
use crate::util::HTTP_CLIENT;
use reqwest::header::HeaderValue;
+use std::convert::TryInto;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use std::thread;
@@ -161,14 +162,19 @@ pub fn get_threepid(bk: &Backend) {
});
}
-pub fn get_email_token(bk: &Backend, identity: String, email: String, client_secret: String) {
+pub fn get_email_token(
+ bk: &Backend,
+ identity: String,
+ email: String,
+ client_secret: String,
+) -> Result<(), Error> {
let tx = bk.tx.clone();
let base = bk.get_base_url();
let access_token = bk.data.lock().unwrap().access_token.clone();
let params = EmailTokenParameters { access_token };
let body = EmailTokenBody {
- id_server: identity[8..].into(),
+ id_server: Url::parse(&identity)?.try_into()?,
client_secret: client_secret.clone(),
email,
send_attempt: 1,
@@ -200,16 +206,23 @@ pub fn get_email_token(bk: &Backend, identity: String, email: String, client_sec
tx.send(BKResponse::GetTokenEmail(query))
.expect_log("Connection closed");
});
+
+ Ok(())
}
-pub fn get_phone_token(bk: &Backend, identity: String, phone: String, client_secret: String) {
+pub fn get_phone_token(
+ bk: &Backend,
+ identity: String,
+ phone: String,
+ client_secret: String,
+) -> Result<(), Error> {
let tx = bk.tx.clone();
let base = bk.get_base_url();
let access_token = bk.data.lock().unwrap().access_token.clone();
let params = PhoneTokenParameters { access_token };
let body = PhoneTokenBody {
- id_server: identity[8..].into(),
+ id_server: Url::parse(&identity)?.try_into()?,
client_secret: client_secret.clone(),
phone_number: phone,
country: String::new(),
@@ -242,9 +255,16 @@ pub fn get_phone_token(bk: &Backend, identity: String, phone: String, client_sec
tx.send(BKResponse::GetTokenPhone(query))
.expect_log("Connection closed");
});
+
+ Ok(())
}
-pub fn add_threepid(bk: &Backend, identity: String, client_secret: String, sid: String) {
+pub fn add_threepid(
+ bk: &Backend,
+ identity: String,
+ client_secret: String,
+ sid: String,
+) -> Result<(), Error> {
let tx = bk.tx.clone();
let base = bk.get_base_url();
@@ -252,7 +272,7 @@ pub fn add_threepid(bk: &Backend, identity: String, client_secret: String, sid:
let params = AddThreePIDParameters { access_token };
let body = AddThreePIDBody {
three_pid_creds: ThreePIDCredentials {
- id_server: identity[8..].into(),
+ id_server: Url::parse(&identity)?.try_into()?,
sid: sid.clone(),
client_secret,
},
@@ -273,6 +293,8 @@ pub fn add_threepid(bk: &Backend, identity: String, client_secret: String, sid:
tx.send(BKResponse::AddThreePID(query))
.expect_log("Connection closed");
});
+
+ Ok(())
}
pub fn submit_phone_token(bk: &Backend, client_secret: String, sid: String, token: String) {
diff --git a/fractal-matrix-api/src/de.rs b/fractal-matrix-api/src/de.rs
new file mode 100644
index 00000000..e2b213d1
--- /dev/null
+++ b/fractal-matrix-api/src/de.rs
@@ -0,0 +1,76 @@
+pub mod url {
+ use serde::de::{Error, Visitor};
+ use serde::Deserializer;
+ use std::fmt::{self, Formatter};
+ use url::Url;
+
+ pub(super) struct UrlVisitor;
+
+ impl<'de> Visitor<'de> for UrlVisitor {
+ type Value = Url;
+
+ fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
+ write!(formatter, "a valid URL")
+ }
+
+ fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ Url::parse(v).map_err(E::custom)
+ }
+ }
+
+ pub fn deserialize<'de, D>(de: D) -> Result<Url, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ de.deserialize_str(UrlVisitor)
+ }
+}
+
+pub mod option_url {
+ use super::url as serde_url;
+ use serde::de::{Error, Visitor};
+ use serde::Deserializer;
+ use std::fmt::{self, Formatter};
+ use url::Url;
+
+ struct OptionUrlVisitor;
+
+ impl<'de> Visitor<'de> for OptionUrlVisitor {
+ type Value = Option<Url>;
+
+ fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
+ serde_url::UrlVisitor.expecting(formatter)
+ }
+
+ fn visit_unit<E>(self) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ Ok(None)
+ }
+
+ fn visit_none<E>(self) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ Ok(None)
+ }
+
+ fn visit_some<D>(self, de: D) -> Result<Self::Value, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ serde_url::deserialize(de).map(Some)
+ }
+ }
+
+ pub fn deserialize<'de, D>(de: D) -> Result<Option<Url>, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ de.deserialize_option(OptionUrlVisitor)
+ }
+}
diff --git a/fractal-matrix-api/src/lib.rs b/fractal-matrix-api/src/lib.rs
index bc71a688..5b633847 100644
--- a/fractal-matrix-api/src/lib.rs
+++ b/fractal-matrix-api/src/lib.rs
@@ -6,6 +6,7 @@ pub mod globals;
pub mod backend;
pub mod cache;
mod client;
+mod de;
pub mod identity;
mod model;
pub mod r0;
diff --git a/fractal-matrix-api/src/model/member.rs b/fractal-matrix-api/src/model/member.rs
index fd1fbfd5..3f9ae5cd 100644
--- a/fractal-matrix-api/src/model/member.rs
+++ b/fractal-matrix-api/src/model/member.rs
@@ -1,7 +1,9 @@
use crate::r0::search::user::User;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
+use url::Url;
+// TODO: Remove this and use only crate::r0::search::user::User
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Member {
// The mxid is either inside the json object, or outside of it.
@@ -36,7 +38,7 @@ impl From<User> for Member {
Self {
uid: user.user_id,
alias: user.display_name,
- avatar: user.avatar_url,
+ avatar: user.avatar_url.map(Url::into_string),
}
}
}
diff --git a/fractal-matrix-api/src/model/room.rs b/fractal-matrix-api/src/model/room.rs
index a7f9fe1a..c433080e 100644
--- a/fractal-matrix-api/src/model/room.rs
+++ b/fractal-matrix-api/src/model/room.rs
@@ -79,7 +79,7 @@ pub enum RoomTag {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Room {
pub id: String,
- pub avatar: Option<String>,
+ pub avatar: Option<String>, // TODO: Use Option<Url>
pub name: Option<String>,
pub topic: Option<String>,
pub alias: Option<String>,
@@ -282,7 +282,7 @@ impl From<PublicRoomsChunk> for Room {
Self {
alias: input.canonical_alias,
name: input.name,
- avatar: input.avatar_url,
+ avatar: input.avatar_url.map(Url::into_string),
topic: input.topic,
n_members: input.num_joined_members,
world_readable: input.world_readable,
diff --git a/fractal-matrix-api/src/r0.rs b/fractal-matrix-api/src/r0.rs
index 9b1f1bf2..7acfc49e 100644
--- a/fractal-matrix-api/src/r0.rs
+++ b/fractal-matrix-api/src/r0.rs
@@ -9,7 +9,12 @@ pub mod server;
pub mod sync;
pub mod thirdparty;
-use serde::{Deserialize, Serialize};
+use serde::{Deserialize, Serialize, Serializer};
+use std::convert::TryFrom;
+use std::fmt::{self, Display, Formatter};
+use url::Host;
+use url::ParseError;
+use url::Url;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
@@ -21,6 +26,45 @@ pub enum Medium {
#[derive(Clone, Debug, Serialize)]
pub struct ThreePIDCredentials {
pub client_secret: String,
- pub id_server: String,
+ pub id_server: HostAndPort<String>,
pub sid: String,
}
+
+#[derive(Clone, Debug)]
+pub struct HostAndPort<T> {
+ pub host: Host<T>,
+ pub port: Option<u16>,
+}
+
+impl TryFrom<Url> for HostAndPort<String> {
+ type Error = ParseError;
+
+ fn try_from(url: Url) -> Result<Self, Self::Error> {
+ Ok(Self {
+ host: url
+ .host()
+ .ok_or(ParseError::SetHostOnCannotBeABaseUrl)?
+ .to_owned(),
+ port: url.port(),
+ })
+ }
+}
+
+impl<T: AsRef<str>> Display for HostAndPort<T> {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ if let Some(port) = self.port {
+ write!(f, "{}:{}", self.host, port)
+ } else {
+ write!(f, "{}", self.host)
+ }
+ }
+}
+
+impl<T: AsRef<str>> Serialize for HostAndPort<T> {
+ fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ ser.serialize_str(&self.to_string())
+ }
+}
diff --git a/fractal-matrix-api/src/r0/account.rs b/fractal-matrix-api/src/r0/account.rs
index 9e4b667d..1718d71b 100644
--- a/fractal-matrix-api/src/r0/account.rs
+++ b/fractal-matrix-api/src/r0/account.rs
@@ -5,7 +5,9 @@ pub mod logout;
pub mod register;
use crate::r0::{Medium, ThreePIDCredentials};
+use crate::ser::serialize_url;
use serde::Serialize;
+use url::Url;
#[derive(Clone, Debug, Serialize)]
#[serde(tag = "type")]
@@ -86,7 +88,10 @@ pub enum AuthenticationData {
session: Option<String>,
},
#[serde(rename = "m.login.oauth2")]
- OAuth2 { uri: String },
+ OAuth2 {
+ #[serde(serialize_with = "serialize_url")]
+ uri: Url,
+ },
#[serde(rename = "m.login.email.identity")]
Email {
threepid_creds: ThreePIDCredentials,
diff --git a/fractal-matrix-api/src/r0/contact/request_verification_token_email.rs
b/fractal-matrix-api/src/r0/contact/request_verification_token_email.rs
index 7776950a..62482512 100644
--- a/fractal-matrix-api/src/r0/contact/request_verification_token_email.rs
+++ b/fractal-matrix-api/src/r0/contact/request_verification_token_email.rs
@@ -1,3 +1,5 @@
+use crate::r0::HostAndPort;
+use crate::ser::serialize_option_url;
use reqwest::Client;
use reqwest::Error;
use reqwest::Request;
@@ -13,10 +15,11 @@ pub struct Parameters {
pub struct Body {
pub client_secret: String,
pub email: String,
- pub id_server: String,
+ pub id_server: HostAndPort<String>,
pub send_attempt: u64,
+ #[serde(serialize_with = "serialize_option_url")]
#[serde(skip_serializing_if = "Option::is_none")]
- pub next_link: Option<String>,
+ pub next_link: Option<Url>,
}
#[derive(Clone, Debug, Deserialize)]
diff --git a/fractal-matrix-api/src/r0/contact/request_verification_token_msisdn.rs
b/fractal-matrix-api/src/r0/contact/request_verification_token_msisdn.rs
index b95bbea0..22ce283a 100644
--- a/fractal-matrix-api/src/r0/contact/request_verification_token_msisdn.rs
+++ b/fractal-matrix-api/src/r0/contact/request_verification_token_msisdn.rs
@@ -1,3 +1,5 @@
+use crate::r0::HostAndPort;
+use crate::ser::serialize_option_url;
use reqwest::Client;
use reqwest::Error;
use reqwest::Request;
@@ -14,10 +16,11 @@ pub struct Body {
pub client_secret: String,
pub phone_number: String,
pub country: String,
- pub id_server: String,
+ pub id_server: HostAndPort<String>,
pub send_attempt: u64,
+ #[serde(serialize_with = "serialize_option_url")]
#[serde(skip_serializing_if = "Option::is_none")]
- pub next_link: Option<String>,
+ pub next_link: Option<Url>,
}
#[derive(Clone, Debug, Deserialize)]
diff --git a/fractal-matrix-api/src/r0/directory/post_public_rooms.rs
b/fractal-matrix-api/src/r0/directory/post_public_rooms.rs
index 145b7acb..5f341a7a 100644
--- a/fractal-matrix-api/src/r0/directory/post_public_rooms.rs
+++ b/fractal-matrix-api/src/r0/directory/post_public_rooms.rs
@@ -1,3 +1,4 @@
+use crate::de::option_url;
use crate::ser::serialize_option_host;
use reqwest::Client;
use reqwest::Error;
@@ -61,7 +62,9 @@ pub struct Response {
#[derive(Clone, Debug, Deserialize)]
pub struct Chunk {
pub aliases: Option<Vec<String>>,
- pub avatar_url: Option<String>,
+ #[serde(deserialize_with = "option_url::deserialize")]
+ #[serde(default)]
+ pub avatar_url: Option<Url>,
pub canonical_alias: Option<String>,
pub guest_can_join: bool,
pub name: Option<String>,
diff --git a/fractal-matrix-api/src/r0/media/create.rs b/fractal-matrix-api/src/r0/media/create.rs
index 8e8b0fc8..8410e541 100644
--- a/fractal-matrix-api/src/r0/media/create.rs
+++ b/fractal-matrix-api/src/r0/media/create.rs
@@ -1,3 +1,4 @@
+use crate::de::url as serde_url;
use reqwest::header::{HeaderValue, CONTENT_TYPE};
use reqwest::Client;
use reqwest::Error;
@@ -13,7 +14,8 @@ pub struct Parameters {
#[derive(Clone, Debug, Deserialize)]
pub struct Response {
- pub content_uri: String,
+ #[serde(deserialize_with = "serde_url::deserialize")]
+ pub content_uri: Url,
}
pub fn request(
diff --git a/fractal-matrix-api/src/r0/profile/get_profile.rs
b/fractal-matrix-api/src/r0/profile/get_profile.rs
index 50afd968..d27f7358 100644
--- a/fractal-matrix-api/src/r0/profile/get_profile.rs
+++ b/fractal-matrix-api/src/r0/profile/get_profile.rs
@@ -1,3 +1,4 @@
+use crate::de::option_url;
use reqwest::Client;
use reqwest::Error;
use reqwest::Request;
@@ -6,7 +7,9 @@ use url::Url;
#[derive(Clone, Debug, Deserialize)]
pub struct Response {
- pub avatar_url: Option<String>,
+ #[serde(deserialize_with = "option_url::deserialize")]
+ #[serde(default)]
+ pub avatar_url: Option<Url>,
pub displayname: Option<String>,
}
diff --git a/fractal-matrix-api/src/r0/profile/set_avatar_url.rs
b/fractal-matrix-api/src/r0/profile/set_avatar_url.rs
index 0d2a87ce..05ed46b5 100644
--- a/fractal-matrix-api/src/r0/profile/set_avatar_url.rs
+++ b/fractal-matrix-api/src/r0/profile/set_avatar_url.rs
@@ -1,3 +1,4 @@
+use crate::ser::serialize_option_url;
use reqwest::Client;
use reqwest::Error;
use reqwest::Request;
@@ -11,7 +12,8 @@ pub struct Parameters {
#[derive(Clone, Debug, Serialize)]
pub struct Body {
- pub avatar_url: Option<String>,
+ #[serde(serialize_with = "serialize_option_url")]
+ pub avatar_url: Option<Url>,
}
pub fn request(
diff --git a/fractal-matrix-api/src/r0/search/user.rs b/fractal-matrix-api/src/r0/search/user.rs
index 65ad510c..0703f51a 100644
--- a/fractal-matrix-api/src/r0/search/user.rs
+++ b/fractal-matrix-api/src/r0/search/user.rs
@@ -1,3 +1,4 @@
+use crate::de::option_url;
use reqwest::Client;
use reqwest::Error;
use reqwest::Request;
@@ -36,8 +37,9 @@ pub struct User {
pub user_id: String,
#[serde(default)]
pub display_name: Option<String>,
+ #[serde(deserialize_with = "option_url::deserialize")]
#[serde(default)]
- pub avatar_url: Option<String>,
+ pub avatar_url: Option<Url>,
}
fn u64_is_10(number: &u64) -> bool {
diff --git a/fractal-matrix-api/src/r0/server/domain_info.rs b/fractal-matrix-api/src/r0/server/domain_info.rs
index d9e0c361..1c298366 100644
--- a/fractal-matrix-api/src/r0/server/domain_info.rs
+++ b/fractal-matrix-api/src/r0/server/domain_info.rs
@@ -1,3 +1,4 @@
+use crate::de::url as serde_url;
use reqwest::Client;
use reqwest::Error;
use reqwest::Request;
@@ -14,12 +15,14 @@ pub struct Response {
#[derive(Clone, Debug, Deserialize)]
pub struct HomeserverInfo {
- pub base_url: String,
+ #[serde(deserialize_with = "serde_url::deserialize")]
+ pub base_url: Url,
}
#[derive(Clone, Debug, Deserialize)]
pub struct IDServerInfo {
- pub base_url: String,
+ #[serde(deserialize_with = "serde_url::deserialize")]
+ pub base_url: Url,
}
pub fn request(base: Url) -> Result<Request, Error> {
diff --git a/fractal-matrix-api/src/r0/thirdparty/get_supported_protocols.rs
b/fractal-matrix-api/src/r0/thirdparty/get_supported_protocols.rs
index 65100d34..07df1978 100644
--- a/fractal-matrix-api/src/r0/thirdparty/get_supported_protocols.rs
+++ b/fractal-matrix-api/src/r0/thirdparty/get_supported_protocols.rs
@@ -1,3 +1,4 @@
+use crate::de::option_url;
use reqwest::Client;
use reqwest::Error;
use reqwest::Request;
@@ -19,14 +20,16 @@ pub struct Protocol {
pub location_fields: Vec<String>,
// This field is documented as "required",
// but for some reason matrix.org does not send this
- pub icon: Option<String>,
+ #[serde(deserialize_with = "option_url::deserialize")]
+ #[serde(default)]
+ pub icon: Option<Url>,
pub field_types: BTreeMap<String, FieldType>,
pub instances: Vec<ProtocolInstance>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct FieldType {
- pub regexp: String,
+ pub regexp: String, // TODO: Change type to Regex
pub placeholder: String,
}
@@ -36,7 +39,9 @@ pub struct ProtocolInstance {
#[serde(rename = "network_id")]
pub id: String,
pub desc: String,
- pub icon: Option<String>,
+ #[serde(deserialize_with = "option_url::deserialize")]
+ #[serde(default)]
+ pub icon: Option<Url>,
pub fields: JsonValue,
}
diff --git a/fractal-matrix-api/src/ser.rs b/fractal-matrix-api/src/ser.rs
index 0bb56e88..2c69fd20 100644
--- a/fractal-matrix-api/src/ser.rs
+++ b/fractal-matrix-api/src/ser.rs
@@ -1,6 +1,7 @@
use serde::Serializer;
use std::time::Duration;
use url::Host;
+use url::Url;
pub fn serialize_option_host<S>(host: &Option<Host>, ser: S) -> Result<S::Ok, S::Error>
where
@@ -19,3 +20,20 @@ where
{
ser.serialize_u64(duration.as_secs() * 1000 + (duration.subsec_millis() as u64))
}
+
+pub fn serialize_url<S>(url: &Url, ser: S) -> Result<S::Ok, S::Error>
+where
+ S: Serializer,
+{
+ ser.serialize_str(url.as_str())
+}
+
+pub fn serialize_option_url<S>(url: &Option<Url>, ser: S) -> Result<S::Ok, S::Error>
+where
+ S: Serializer,
+{
+ match url {
+ Some(u) => ser.serialize_str(u.as_str()),
+ None => ser.serialize_none(),
+ }
+}
diff --git a/fractal-matrix-api/src/util.rs b/fractal-matrix-api/src/util.rs
index 0b798b91..c293acd6 100644
--- a/fractal-matrix-api/src/util.rs
+++ b/fractal-matrix-api/src/util.rs
@@ -349,7 +349,12 @@ pub fn get_user_avatar(base: &Url, userid: &str) -> Result<(String, String), Err
.avatar_url
.map(|url| {
let dest = cache_dir_path(None, userid)?;
- dw_media(base, &url, ContentType::default_thumbnail(), Some(&dest))
+ dw_media(
+ base,
+ url.as_str(),
+ ContentType::default_thumbnail(),
+ Some(&dest),
+ )
})
.unwrap_or(Ok(Default::default()))?;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]