From d60e3ebc77c7833db917c3030c145883b8f0ee62 Mon Sep 17 00:00:00 2001 From: Mario Zupan Date: Tue, 15 Sep 2026 11:28:56 +0200 Subject: [PATCH 1/2] sdk(local_relay): Add relay_url to LocalRelayBuilderNip42 --- nostr-sdk/CHANGELOG.md | 4 ++++ nostr-sdk/src/local_relay/builder.rs | 18 ++++++++++++++++++ nostr-sdk/src/local_relay/local/inner.rs | 10 +++++++++- nostr-sdk/src/relay/api/send_event.rs | 2 ++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/nostr-sdk/CHANGELOG.md b/nostr-sdk/CHANGELOG.md index 822d77b4f..28ec27040 100644 --- a/nostr-sdk/CHANGELOG.md +++ b/nostr-sdk/CHANGELOG.md @@ -29,6 +29,10 @@ ## Unreleased +### Added + +- local-relay: Add `LocalRelayBuilderNip42::relay_url` (https://github.com/nostrdevkit/nostr/pull/1476) to make it possible to configure a custom `relay_url` for the nip42 challenge validation + ### Deprecated - Deprecate `LocalRelayBuilder::max_query_results` and `LocalRelayBuilder::default_filter_limit` (https://github.com/nostrdevkit/nostr/pull/1461) diff --git a/nostr-sdk/src/local_relay/builder.rs b/nostr-sdk/src/local_relay/builder.rs index 8c9916d81..a8d83c0e7 100644 --- a/nostr-sdk/src/local_relay/builder.rs +++ b/nostr-sdk/src/local_relay/builder.rs @@ -230,6 +230,10 @@ pub struct LocalRelayBuilderNip42 { pub mode: LocalRelayBuilderNip42Mode, // /// Allowed public keys // pub allowed: HashSet, + /// Relay URL expected in NIP-42 authentication events. + /// + /// If not set, the local relay's listening URL is used. + pub relay_url: Option, } impl LocalRelayBuilderNip42 { @@ -238,6 +242,7 @@ impl LocalRelayBuilderNip42 { pub fn write() -> Self { Self { mode: LocalRelayBuilderNip42Mode::Write, + relay_url: None, } } @@ -246,6 +251,7 @@ impl LocalRelayBuilderNip42 { pub fn read() -> Self { Self { mode: LocalRelayBuilderNip42Mode::Read, + relay_url: None, } } @@ -254,8 +260,20 @@ impl LocalRelayBuilderNip42 { pub fn read_and_write() -> Self { Self { mode: LocalRelayBuilderNip42Mode::Both, + relay_url: None, } } + + /// Set the relay URL expected in NIP-42 authentication events. + /// + /// This is useful when the local relay is embedded behind another + /// WebSocket server, reverse proxy, or TLS terminator and its public + /// URL differs from its listening URL. + #[inline] + pub fn relay_url(mut self, url: RelayUrl) -> Self { + self.relay_url = Some(url); + self + } } #[allow(missing_docs)] diff --git a/nostr-sdk/src/local_relay/local/inner.rs b/nostr-sdk/src/local_relay/local/inner.rs index a49036972..d643fe182 100644 --- a/nostr-sdk/src/local_relay/local/inner.rs +++ b/nostr-sdk/src/local_relay/local/inner.rs @@ -917,7 +917,15 @@ impl InnerLocalRelay { .await; } - match session.nip42.check_challenge(&event, &self.url().await) { + let relay_url: RelayUrl = match self + .nip42 + .as_ref() + .and_then(|opts| opts.relay_url.as_ref()) + { + Some(url) => url.clone(), + None => self.url().await, + }; + match session.nip42.check_challenge(&event, &relay_url) { Ok(()) => { send_msg( ws_tx, diff --git a/nostr-sdk/src/relay/api/send_event.rs b/nostr-sdk/src/relay/api/send_event.rs index 416496f5f..030da55f5 100644 --- a/nostr-sdk/src/relay/api/send_event.rs +++ b/nostr-sdk/src/relay/api/send_event.rs @@ -342,6 +342,7 @@ mod tests { // Mock relay let opts = LocalRelayBuilderNip42 { mode: LocalRelayBuilderNip42Mode::Write, + relay_url: None, }; let mock = LocalRelay::builder().nip42(opts).build(); mock.run().await.unwrap(); @@ -370,6 +371,7 @@ mod tests { // Mock relay let opts = LocalRelayBuilderNip42 { mode: LocalRelayBuilderNip42Mode::Write, + relay_url: None, }; let mock = LocalRelay::builder().nip42(opts).build(); mock.run().await.unwrap(); From ebcbb2ef86428c3efda6b38499f2a63fb9e1786f Mon Sep 17 00:00:00 2001 From: Mario Zupan Date: Wed, 16 Sep 2026 09:18:07 +0200 Subject: [PATCH 2/2] review fixes --- nostr-sdk/src/local_relay/builder.rs | 4 ---- nostr-sdk/src/local_relay/local/inner.rs | 13 +++++-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/nostr-sdk/src/local_relay/builder.rs b/nostr-sdk/src/local_relay/builder.rs index a8d83c0e7..8356ccc7f 100644 --- a/nostr-sdk/src/local_relay/builder.rs +++ b/nostr-sdk/src/local_relay/builder.rs @@ -265,10 +265,6 @@ impl LocalRelayBuilderNip42 { } /// Set the relay URL expected in NIP-42 authentication events. - /// - /// This is useful when the local relay is embedded behind another - /// WebSocket server, reverse proxy, or TLS terminator and its public - /// URL differs from its listening URL. #[inline] pub fn relay_url(mut self, url: RelayUrl) -> Self { self.relay_url = Some(url); diff --git a/nostr-sdk/src/local_relay/local/inner.rs b/nostr-sdk/src/local_relay/local/inner.rs index d643fe182..397935e31 100644 --- a/nostr-sdk/src/local_relay/local/inner.rs +++ b/nostr-sdk/src/local_relay/local/inner.rs @@ -917,14 +917,11 @@ impl InnerLocalRelay { .await; } - let relay_url: RelayUrl = match self - .nip42 - .as_ref() - .and_then(|opts| opts.relay_url.as_ref()) - { - Some(url) => url.clone(), - None => self.url().await, - }; + let relay_url: RelayUrl = + match self.nip42.as_ref().and_then(|opts| opts.relay_url.as_ref()) { + Some(url) => url.clone(), + None => self.url().await, + }; match session.nip42.check_challenge(&event, &relay_url) { Ok(()) => { send_msg(