|
@@ -24,9 +24,30 @@ pub enum Error {
|
|
}
|
|
}
|
|
|
|
|
|
/// MintUrl Url
|
|
/// MintUrl Url
|
|
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
|
|
|
|
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub struct MintUrl(String);
|
|
pub struct MintUrl(String);
|
|
|
|
|
|
|
|
+impl Serialize for MintUrl {
|
|
|
|
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
+ where
|
|
|
|
+ S: serde::Serializer,
|
|
|
|
+ {
|
|
|
|
+ // Use the to_string implementation to get the correctly formatted URL
|
|
|
|
+ serializer.serialize_str(&self.to_string())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<'de> Deserialize<'de> for MintUrl {
|
|
|
|
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
|
|
+ where
|
|
|
|
+ D: serde::Deserializer<'de>,
|
|
|
|
+ {
|
|
|
|
+ // Deserialize as a string and then use from_str to parse it correctly
|
|
|
|
+ let s = String::deserialize(deserializer)?;
|
|
|
|
+ MintUrl::from_str(&s).map_err(serde::de::Error::custom)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
impl MintUrl {
|
|
impl MintUrl {
|
|
fn format_url(url: &str) -> Result<String, Error> {
|
|
fn format_url(url: &str) -> Result<String, Error> {
|
|
ensure_cdk!(!url.is_empty(), Error::InvalidUrl);
|
|
ensure_cdk!(!url.is_empty(), Error::InvalidUrl);
|
|
@@ -56,16 +77,29 @@ impl MintUrl {
|
|
.join("/");
|
|
.join("/");
|
|
let mut formatted_url = format!("{protocol}://{host}");
|
|
let mut formatted_url = format!("{protocol}://{host}");
|
|
if !path.is_empty() {
|
|
if !path.is_empty() {
|
|
- formatted_url.push_str(&format!("/{path}/"));
|
|
|
|
|
|
+ formatted_url.push_str(&format!("/{}", path));
|
|
}
|
|
}
|
|
Ok(formatted_url)
|
|
Ok(formatted_url)
|
|
}
|
|
}
|
|
|
|
|
|
/// Join onto url
|
|
/// Join onto url
|
|
pub fn join(&self, path: &str) -> Result<Url, Error> {
|
|
pub fn join(&self, path: &str) -> Result<Url, Error> {
|
|
- Url::parse(&self.0)
|
|
|
|
- .and_then(|url| url.join(path))
|
|
|
|
- .map_err(Into::into)
|
|
|
|
|
|
+ let url = Url::parse(&self.0)?;
|
|
|
|
+
|
|
|
|
+ // Get the current path segments
|
|
|
|
+ let base_path = url.path();
|
|
|
|
+
|
|
|
|
+ // Check if the path has a trailing slash to avoid double slashes
|
|
|
|
+ let normalized_path = if base_path.ends_with('/') {
|
|
|
|
+ format!("{}{}", base_path, path)
|
|
|
|
+ } else {
|
|
|
|
+ format!("{}/{}", base_path, path)
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Create a new URL with the combined path
|
|
|
|
+ let mut result = url.clone();
|
|
|
|
+ result.set_path(&normalized_path);
|
|
|
|
+ Ok(result)
|
|
}
|
|
}
|
|
|
|
|
|
/// Append path elements onto the URL
|
|
/// Append path elements onto the URL
|
|
@@ -96,6 +130,7 @@ impl fmt::Display for MintUrl {
|
|
mod tests {
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
|
use super::*;
|
|
|
|
+ use crate::Token;
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn test_trim_trailing_slashes() {
|
|
fn test_trim_trailing_slashes() {
|
|
@@ -121,7 +156,7 @@ mod tests {
|
|
assert_eq!(correct_cased_url, cased_url_formatted.to_string());
|
|
assert_eq!(correct_cased_url, cased_url_formatted.to_string());
|
|
|
|
|
|
let wrong_cased_url_with_path = "http://URL-to-check.com/PATH/to/check";
|
|
let wrong_cased_url_with_path = "http://URL-to-check.com/PATH/to/check";
|
|
- let correct_cased_url_with_path = "http://url-to-check.com/PATH/to/check/";
|
|
|
|
|
|
+ let correct_cased_url_with_path = "http://url-to-check.com/PATH/to/check";
|
|
|
|
|
|
let cased_url_with_path_formatted = MintUrl::from_str(wrong_cased_url_with_path).unwrap();
|
|
let cased_url_with_path_formatted = MintUrl::from_str(wrong_cased_url_with_path).unwrap();
|
|
assert_eq!(
|
|
assert_eq!(
|
|
@@ -164,4 +199,32 @@ mod tests {
|
|
url.join_paths(&["hello", "world"]).unwrap().to_string()
|
|
url.join_paths(&["hello", "world"]).unwrap().to_string()
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ #[test]
|
|
|
|
+ fn test_mint_url_slash_eqality() {
|
|
|
|
+ let mint_url_with_slash_str = "https://mint.minibits.cash/Bitcoin/";
|
|
|
|
+ let mint_url_with_slash = MintUrl::from_str(mint_url_with_slash_str).unwrap();
|
|
|
|
+
|
|
|
|
+ let mint_url_without_slash_str = "https://mint.minibits.cash/Bitcoin";
|
|
|
|
+ let mint_url_without_slash = MintUrl::from_str(mint_url_without_slash_str).unwrap();
|
|
|
|
+
|
|
|
|
+ assert_eq!(mint_url_with_slash, mint_url_without_slash);
|
|
|
|
+ assert_eq!(
|
|
|
|
+ mint_url_with_slash.to_string(),
|
|
|
|
+ mint_url_without_slash_str.to_string()
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #[test]
|
|
|
|
+ fn test_token_equality_trailing_slash() {
|
|
|
|
+ let token_with_slash = Token::from_str("cashuBo2FteCNodHRwczovL21pbnQubWluaWJpdHMuY2FzaC9CaXRjb2luL2F1Y3NhdGF0gaJhaUgAUAVQ8ElBRmFwgqRhYQhhc3hAYzg2NTZhZDg4MzVmOWVmMzVkYWQ1MTZjNGU5ZTU5ZjA3YzFmODg0NTc2NWY3M2FhNWMyMjVhOGI4MGM0ZGM0ZmFjWCECNpnvLdFcsaVbCPUlOzr78XtBoD3mm3jQcldsQ6iKUBFhZKNhZVggrER4tfjjiH0e-lf9H---us1yjQQi__ZCFB9yFwH4jDphc1ggZfP2KcQOWA110vLz11caZF1PuXN606caPO2ZCAhfdvphclggadgz0psQELNif3xJ5J2d_TJWtRKfDFSj7h2ZD4WSFeykYWECYXN4QGZlNjAzNjA1NWM1MzVlZTBlYjI3MjQ1NmUzNjJlNmNkOWViNDNkMWQxODg0M2MzMDQ4MGU0YzE2YjI0MDY5MDZhY1ghAilA3g2_NriE94uTPISd2CM-90x53mK5QNM2iyTFDlnTYWSjYWVYIExR7bUzqM6-lRU7PbbEfnPW1vnSzCEN4SArmJZqp_7bYXNYIJMKRTSlXumUjPWXX5V8-hGPSZ-OXZJiEWm6_IB93OUDYXJYIB8YsigK7dMX59Oiy4Rh05xU0n0rVAPV7g_YFx564ZVa").unwrap();
|
|
|
|
+
|
|
|
|
+ let token_without_slash = Token::from_str("cashuBo2FteCJodHRwczovL21pbnQubWluaWJpdHMuY2FzaC9CaXRjb2luYXVjc2F0YXSBomFpSABQBVDwSUFGYXCCpGFhCGFzeEBjODY1NmFkODgzNWY5ZWYzNWRhZDUxNmM0ZTllNTlmMDdjMWY4ODQ1NzY1ZjczYWE1YzIyNWE4YjgwYzRkYzRmYWNYIQI2me8t0VyxpVsI9SU7Ovvxe0GgPeabeNByV2xDqIpQEWFko2FlWCCsRHi1-OOIfR76V_0f7766zXKNBCL_9kIUH3IXAfiMOmFzWCBl8_YpxA5YDXXS8vPXVxpkXU-5c3rTpxo87ZkICF92-mFyWCBp2DPSmxAQs2J_fEnknZ39Mla1Ep8MVKPuHZkPhZIV7KRhYQJhc3hAZmU2MDM2MDU1YzUzNWVlMGViMjcyNDU2ZTM2MmU2Y2Q5ZWI0M2QxZDE4ODQzYzMwNDgwZTRjMTZiMjQwNjkwNmFjWCECKUDeDb82uIT3i5M8hJ3YIz73THneYrlA0zaLJMUOWdNhZKNhZVggTFHttTOozr6VFTs9tsR-c9bW-dLMIQ3hICuYlmqn_tthc1ggkwpFNKVe6ZSM9ZdflXz6EY9Jn45dkmIRabr8gH3c5QNhclggHxiyKArt0xfn06LLhGHTnFTSfStUA9XuD9gXHnrhlVo").unwrap();
|
|
|
|
+
|
|
|
|
+ let url_with_slash = token_with_slash.mint_url().unwrap();
|
|
|
|
+ let url_without_slash = token_without_slash.mint_url().unwrap();
|
|
|
|
+
|
|
|
|
+ assert_eq!(url_without_slash.to_string(), url_with_slash.to_string());
|
|
|
|
+ assert_eq!(url_without_slash, url_with_slash);
|
|
|
|
+ }
|
|
}
|
|
}
|