Summary
node.dial(peer) currently accepts a PublicKey instance or a base32 public-key string. Extend it to also accept a full httpi:// URL and extract the public key from the hostname — matching what node.fetch() already does.
Evidence
IrohNode.dial() calls resolveNodeId(peer) which only handles the PublicKey | string union (packages/iroh-http-shared/src/PublicKey.ts#L139-L142). A user passing node.dial("httpi://tvtswinq.../something") will get an invalid base32 string error from the Rust side because the whole URL is forwarded as a node-id. Meanwhile node.fetch(input) accepts httpi:// URLs natively via new URL(raw); nodeId = parsed.hostname; (packages/iroh-http-shared/src/fetch.ts#L48-L60).
Impact
Inconsistent UX between fetch and dial. Users who already have an httpi:// URL (e.g. the peer.toURL() return value, or a copy-pasted address) currently have to strip the scheme manually before calling dial.
Remediation
Extend resolveNodeId(peer: PublicKey | string) (or add a sibling helper used by dial) to:
- If the string starts with
httpi:// (case-insensitive), parse via WHATWG URL and use .hostname.
- Otherwise treat as a bare base32 string (existing behaviour).
- Reject
http:// / https:// with a clear error (mirror the rejection in fetch.ts).
Apply to dial() and any other call site that takes a peer identity string.
Acceptance criteria
node.dial("httpi://<base32-key>") works end-to-end.
node.dial("httpi://<base32-key>/some/path") works (path ignored — dial opens a session, not a request).
node.dial(peer.toURL()) works (interop with PublicKey.toURL()).
node.dial("https://example.com") throws a clear error.
node.dial(<bare-base32>) continues to work (no regression).
- Test added to
tests/suites/sessions.mjs covering all four cases.
Summary
node.dial(peer)currently accepts aPublicKeyinstance or a base32 public-key string. Extend it to also accept a fullhttpi://URL and extract the public key from the hostname — matching whatnode.fetch()already does.Evidence
IrohNode.dial()callsresolveNodeId(peer)which only handles thePublicKey | stringunion (packages/iroh-http-shared/src/PublicKey.ts#L139-L142). A user passingnode.dial("httpi://tvtswinq.../something")will get aninvalid base32 stringerror from the Rust side because the whole URL is forwarded as a node-id. Meanwhilenode.fetch(input)acceptshttpi://URLs natively vianew URL(raw); nodeId = parsed.hostname;(packages/iroh-http-shared/src/fetch.ts#L48-L60).Impact
Inconsistent UX between
fetchanddial. Users who already have anhttpi://URL (e.g. thepeer.toURL()return value, or a copy-pasted address) currently have to strip the scheme manually before callingdial.Remediation
Extend
resolveNodeId(peer: PublicKey | string)(or add a sibling helper used bydial) to:httpi://(case-insensitive), parse via WHATWGURLand use.hostname.http:///https://with a clear error (mirror the rejection infetch.ts).Apply to
dial()and any other call site that takes a peer identity string.Acceptance criteria
node.dial("httpi://<base32-key>")works end-to-end.node.dial("httpi://<base32-key>/some/path")works (path ignored —dialopens a session, not a request).node.dial(peer.toURL())works (interop withPublicKey.toURL()).node.dial("https://example.com")throws a clear error.node.dial(<bare-base32>)continues to work (no regression).tests/suites/sessions.mjscovering all four cases.