Skip to content

Commit f9e5fb0

Browse files
authored
Merge pull request #7 from benthecarman/better-http
Allow for custom HTTPHrnResolvers
2 parents 0e9af05 + d4af94b commit f9e5fb0

File tree

2 files changed

+53
-22
lines changed

2 files changed

+53
-22
lines changed

src/http_resolver.rs

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,28 @@ const DOH_ENDPOINT: &'static str = "https://dns.google/dns-query?dns=";
2929
///
3030
/// Note that using this may reveal our IP address to the recipient and information about who we're
3131
/// paying to Google (via `dns.google`).
32-
pub struct HTTPHrnResolver;
32+
#[derive(Debug, Clone)]
33+
pub struct HTTPHrnResolver {
34+
client: reqwest::Client,
35+
}
36+
37+
impl HTTPHrnResolver {
38+
/// Create a new `HTTPHrnResolver` with a default `reqwest::Client`.
39+
pub fn new() -> Self {
40+
HTTPHrnResolver::default()
41+
}
42+
43+
/// Create a new `HTTPHrnResolver` with a custom `reqwest::Client`.
44+
pub fn with_client(client: reqwest::Client) -> Self {
45+
HTTPHrnResolver { client }
46+
}
47+
}
48+
49+
impl Default for HTTPHrnResolver {
50+
fn default() -> Self {
51+
HTTPHrnResolver { client: reqwest::Client::new() }
52+
}
53+
}
3354

3455
const B64_CHAR: [u8; 64] = [
3556
b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P',
@@ -107,11 +128,10 @@ impl HTTPHrnResolver {
107128
let mut pending_queries = vec![initial_query];
108129

109130
while let Some(query) = pending_queries.pop() {
110-
let client = reqwest::Client::new();
111-
112131
let request_url = query_to_url(query);
113-
let req = client.get(request_url).header("accept", "application/dns-message").build();
114-
let resp = client.execute(req.map_err(|_| DNS_ERR)?).await.map_err(|_| DNS_ERR)?;
132+
let req =
133+
self.client.get(request_url).header("accept", "application/dns-message").build();
134+
let resp = self.client.execute(req.map_err(|_| DNS_ERR)?).await.map_err(|_| DNS_ERR)?;
115135
let body = resp.bytes().await.map_err(|_| DNS_ERR)?;
116136

117137
let mut answer = QueryBuf::new_zeroed(0);
@@ -136,8 +156,15 @@ impl HTTPHrnResolver {
136156

137157
async fn resolve_lnurl_impl(&self, lnurl_url: &str) -> Result<HrnResolution, &'static str> {
138158
let err = "Failed to fetch LN-Address initial well-known endpoint";
139-
let init: LNURLInitResponse =
140-
reqwest::get(lnurl_url).await.map_err(|_| err)?.json().await.map_err(|_| err)?;
159+
let init: LNURLInitResponse = self
160+
.client
161+
.get(lnurl_url)
162+
.send()
163+
.await
164+
.map_err(|_| err)?
165+
.json()
166+
.await
167+
.map_err(|_| err)?;
141168

142169
if init.tag != "payRequest" {
143170
return Err("LNURL initial init_response had an incorrect tag value");
@@ -198,8 +225,15 @@ impl HrnResolver for HTTPHrnResolver {
198225
} else {
199226
write!(&mut callback, "?amount={}", amt.milli_sats()).expect("Write to String");
200227
}
201-
let callback_response: LNURLCallbackResponse =
202-
reqwest::get(callback).await.map_err(|_| err)?.json().await.map_err(|_| err)?;
228+
let callback_response: LNURLCallbackResponse = self
229+
.client
230+
.get(callback)
231+
.send()
232+
.await
233+
.map_err(|_| err)?
234+
.json()
235+
.await
236+
.map_err(|_| err)?;
203237

204238
if !callback_response.routes.is_empty() {
205239
return Err("LNURL callback response contained a non-empty routes array");
@@ -257,7 +291,7 @@ mod tests {
257291

258292
#[tokio::test]
259293
async fn test_dns_via_http_hrn_resolver() {
260-
let resolver = HTTPHrnResolver;
294+
let resolver = HTTPHrnResolver::default();
261295
let instructions = PaymentInstructions::parse(
262296
263297
bitcoin::Network::Bitcoin,
@@ -303,10 +337,11 @@ mod tests {
303337

304338
#[tokio::test]
305339
async fn test_http_hrn_resolver() {
340+
let resolver = HTTPHrnResolver::default();
306341
let instructions = PaymentInstructions::parse(
307342
308343
bitcoin::Network::Bitcoin,
309-
&HTTPHrnResolver,
344+
&resolver,
310345
true,
311346
)
312347
.await
@@ -323,7 +358,7 @@ mod tests {
323358
assert_eq!(hrn.user(), "lnurltest");
324359
assert_eq!(hrn.domain(), "bitcoin.ninja");
325360

326-
instr.set_amount(Amount::from_sats(100_000).unwrap(), &HTTPHrnResolver).await.unwrap()
361+
instr.set_amount(Amount::from_sats(100_000).unwrap(), &resolver).await.unwrap()
327362
} else {
328363
panic!();
329364
};
@@ -348,11 +383,12 @@ mod tests {
348383

349384
#[tokio::test]
350385
async fn test_http_lnurl_resolver() {
386+
let resolver = HTTPHrnResolver::default();
351387
let instructions = PaymentInstructions::parse(
352388
// lnurl encoding for [email protected]
353389
"lnurl1dp68gurn8ghj7cnfw33k76tw9ehxjmn2vyhjuam9d3kz66mwdamkutmvde6hymrs9akxuatjd36x2um5ahcq39",
354390
Network::Bitcoin,
355-
&HTTPHrnResolver,
391+
&resolver,
356392
true,
357393
)
358394
.await
@@ -365,7 +401,7 @@ mod tests {
365401
assert_eq!(instr.pop_callback(), None);
366402
assert!(instr.bip_353_dnssec_proof().is_none());
367403

368-
instr.set_amount(Amount::from_sats(100_000).unwrap(), &HTTPHrnResolver).await.unwrap()
404+
instr.set_amount(Amount::from_sats(100_000).unwrap(), &resolver).await.unwrap()
369405
} else {
370406
panic!();
371407
};

src/lib.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,14 +1351,9 @@ mod tests {
13511351

13521352
#[cfg(feature = "http")]
13531353
async fn test_lnurl(str: &str) {
1354-
let parsed = PaymentInstructions::parse(
1355-
str,
1356-
Network::Signet,
1357-
&http_resolver::HTTPHrnResolver,
1358-
false,
1359-
)
1360-
.await
1361-
.unwrap();
1354+
let resolver = http_resolver::HTTPHrnResolver::default();
1355+
let parsed =
1356+
PaymentInstructions::parse(str, Network::Signet, &resolver, false).await.unwrap();
13621357

13631358
let parsed = match parsed {
13641359
PaymentInstructions::ConfigurableAmount(parsed) => parsed,

0 commit comments

Comments
 (0)