Skip to content

Commit fe6ecad

Browse files
committed
Propagate errors when retrieving ohttp parameter
1 parent 52d19ae commit fe6ecad

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

payjoin/src/send/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ impl Sender {
306306
)
307307
.map_err(InternalCreateRequestError::Hpke)?;
308308
let mut ohttp =
309-
self.endpoint.ohttp().ok_or(InternalCreateRequestError::MissingOhttpConfig)?;
309+
self.endpoint.ohttp().map_err(|_| InternalCreateRequestError::MissingOhttpConfig)?;
310310
let (body, ohttp_ctx) = ohttp_encapsulate(&mut ohttp, "POST", url.as_str(), Some(&body))
311311
.map_err(InternalCreateRequestError::OhttpEncapsulation)?;
312312
log::debug!("ohttp_relay_url: {:?}", ohttp_relay);
@@ -418,7 +418,7 @@ impl V2GetContext {
418418
)
419419
.map_err(InternalCreateRequestError::Hpke)?;
420420
let mut ohttp =
421-
self.endpoint.ohttp().ok_or(InternalCreateRequestError::MissingOhttpConfig)?;
421+
self.endpoint.ohttp().map_err(|_| InternalCreateRequestError::MissingOhttpConfig)?;
422422
let (body, ohttp_ctx) = ohttp_encapsulate(&mut ohttp, "GET", url.as_str(), Some(&body))
423423
.map_err(InternalCreateRequestError::OhttpEncapsulation)?;
424424

payjoin/src/uri/error.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,25 @@ pub(crate) enum InternalPjParseError {
1111
UnsecureEndpoint,
1212
}
1313

14+
#[cfg(feature = "v2")]
15+
#[derive(Debug)]
16+
pub(crate) enum ParseOhttpKeysParamError {
17+
MissingOhttpKeys,
18+
InvalidOhttpKeys(crate::ohttp::ParseOhttpKeysError)
19+
}
20+
21+
#[cfg(feature = "v2")]
22+
impl std::fmt::Display for ParseOhttpKeysParamError {
23+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24+
use ParseOhttpKeysParamError::*;
25+
26+
match &self {
27+
MissingOhttpKeys => write!(f, "ohttp keys are missing"),
28+
InvalidOhttpKeys(o) => write!(f, "invalid ohttp keys: {}", o)
29+
}
30+
}
31+
}
32+
1433
#[cfg(feature = "v2")]
1534
#[derive(Debug)]
1635
pub(crate) enum ParseReceiverPubkeyError {

payjoin/src/uri/url_ext.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ use bitcoin::consensus::encode::Decodable;
55
use bitcoin::consensus::Encodable;
66
use url::Url;
77

8-
use super::error::ParseReceiverPubkeyError;
8+
use super::error::{ParseOhttpKeysParamError, ParseReceiverPubkeyError};
99
use crate::hpke::HpkePublicKey;
10-
use crate::OhttpKeys;
10+
use crate::ohttp::OhttpKeys;
1111

1212
/// Parse and set fragment parameters from `&pj=` URI parameter URLs
1313
pub(crate) trait UrlExt {
1414
fn receiver_pubkey(&self) -> Result<HpkePublicKey, ParseReceiverPubkeyError>;
1515
fn set_receiver_pubkey(&mut self, exp: HpkePublicKey);
16-
fn ohttp(&self) -> Option<OhttpKeys>;
16+
fn ohttp(&self) -> Result<OhttpKeys, ParseOhttpKeysParamError>;
1717
fn set_ohttp(&mut self, ohttp: OhttpKeys);
1818
fn exp(&self) -> Option<std::time::SystemTime>;
1919
fn set_exp(&mut self, exp: std::time::SystemTime);
@@ -50,8 +50,10 @@ impl UrlExt for Url {
5050
}
5151

5252
/// Retrieve the ohttp parameter from the URL fragment
53-
fn ohttp(&self) -> Option<OhttpKeys> {
54-
get_param(self, "OH1", |value| OhttpKeys::from_str(value).ok())
53+
fn ohttp(&self) -> Result<OhttpKeys, ParseOhttpKeysParamError> {
54+
let value = get_param(self, "OH1", |v| Some(v.to_owned()))
55+
.ok_or(ParseOhttpKeysParamError::MissingOhttpKeys)?;
56+
OhttpKeys::from_str(&value).map_err(ParseOhttpKeysParamError::InvalidOhttpKeys)
5557
}
5658

5759
/// Set the ohttp parameter in the URL fragment
@@ -142,7 +144,16 @@ mod tests {
142144
url.set_ohttp(ohttp_keys.clone());
143145

144146
assert_eq!(url.fragment(), Some(serialized));
145-
assert_eq!(url.ohttp(), Some(ohttp_keys));
147+
assert_eq!(url.ohttp().unwrap(), ohttp_keys);
148+
}
149+
150+
#[test]
151+
fn test_errors_when_parsing_ohttp() {
152+
let missing_ohttp_url = Url::parse("https://example.com").unwrap();
153+
assert!(matches!(missing_ohttp_url.ohttp(), Err(ParseOhttpKeysParamError::MissingOhttpKeys)));
154+
155+
let invalid_ohttp_url = Url::parse("https://example.com?pj=https://test-payjoin-url#OH1invalid_bech_32").unwrap();
156+
assert!(matches!(invalid_ohttp_url.ohttp(), Err(ParseOhttpKeysParamError::InvalidOhttpKeys(_))));
146157
}
147158

148159
#[test]
@@ -163,7 +174,7 @@ mod tests {
163174
&pjos=0&pj=HTTPS://EXAMPLE.COM/\
164175
%23OH1QYPM5JXYNS754Y4R45QWE336QFX6ZR8DQGVQCULVZTV20TFVEYDMFQC";
165176
let pjuri = Uri::try_from(uri).unwrap().assume_checked().check_pj_supported().unwrap();
166-
assert!(pjuri.extras.endpoint().ohttp().is_some());
177+
assert!(pjuri.extras.endpoint().ohttp().is_ok());
167178
assert_eq!(format!("{}", pjuri), uri);
168179

169180
let reordered = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=0.01\
@@ -172,7 +183,7 @@ mod tests {
172183
&pjos=0";
173184
let pjuri =
174185
Uri::try_from(reordered).unwrap().assume_checked().check_pj_supported().unwrap();
175-
assert!(pjuri.extras.endpoint().ohttp().is_some());
186+
assert!(pjuri.extras.endpoint().ohttp().is_ok());
176187
assert_eq!(format!("{}", pjuri), uri);
177188
}
178189
}

0 commit comments

Comments
 (0)