2 releases
| 0.1.3 | Oct 11, 2025 |
|---|---|
| 0.1.2 | Oct 8, 2025 |
#4 in #dns-cache
Used in 2 crates
(via helia-ipns)
74KB
1K
SLoC
helia-dnslink
DNSLink resolution for Helia - enables domain names to point to IPFS content using DNS TXT records.
Features
- ✅ DNS-over-HTTPS resolution using Google DNS
- ✅ Full DNSLink specification support
- ✅ Handles
_dnslink.subdomain per spec - ✅ Supports multiple namespaces:
/ipfs/,/ipns/,/dnslink/ - ✅ Recursive DNSLink resolution (up to 32 levels)
- ✅ CNAME following for delegated domains
- ✅ Path extraction from DNSLink values
- ✅ Configurable DNS caching
- ✅ TypeScript Helia API-compatible
Installation
Add to your Cargo.toml:
[dependencies]
helia-dnslink = "0.1.2"
Usage
Basic Example
use helia_dnslink::{dns_link, DnsLinkInit, DnsLinkResult};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create DNSLink resolver
let dnslink = dns_link(DnsLinkInit::default())?;
// Resolve a domain with DNSLink record
let result = dnslink.resolve("ipfs.tech").await?;
// Handle the result
match result {
DnsLinkResult::IPFS { cid, path, .. } => {
println!("Resolved to CID: {}", cid);
if !path.is_empty() {
println!("With path: {}", path);
}
}
DnsLinkResult::IPNS { peer_id, path, .. } => {
println!("Resolved to Peer ID: {}", peer_id);
}
DnsLinkResult::Other { namespace, value, .. } => {
println!("Custom namespace: {} -> {}", namespace, value);
}
}
Ok(())
}
With Options
use helia_dnslink::{dns_link, DnsLinkInit, ResolveOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let dnslink = dns_link(DnsLinkInit::default())?;
// Custom resolution options
let options = ResolveOptions {
nocache: true, // Don't use DNS cache
offline: false, // Allow network queries
max_recursive_depth: Some(10), // Limit recursion depth
};
let result = dnslink.resolve_with_options("example.com", options).await?;
Ok(())
}
Custom Configuration
use helia_dnslink::{dns_link, DnsLinkInit};
let dnslink = dns_link(DnsLinkInit {
use_https: true, // Use DNS-over-HTTPS
cache_enabled: true, // Enable DNS caching
})?;
DNSLink Format
DNSLink uses DNS TXT records to point domains to IPFS content:
_dnslink.example.com. 60 IN TXT "dnslink=/ipfs/bafybei..."
Supported formats:
dnslink=/ipfs/<cid>- Points to IPFS contentdnslink=/ipfs/<cid>/path/to/file- With path componentdnslink=/ipns/<peer-id>- Points to IPNS namednslink=/dnslink/other.com- Recursive DNSLink
Result Types
pub enum DnsLinkResult {
IPFS {
answer: TxtRecord, // DNS TXT record
namespace: String, // "ipfs"
cid: Cid, // Resolved CID
path: String, // Optional path
},
IPNS {
answer: TxtRecord,
namespace: String, // "ipns"
peer_id: PeerId, // Resolved peer ID
path: String,
},
Other {
answer: TxtRecord,
namespace: String, // Custom namespace
value: String, // Raw value
},
}
Error Handling
pub enum DnsLinkError {
NotFound(String), // No DNSLink record found
InvalidFormat(String), // Invalid DNSLink format
RecursionLimit(u32), // Recursion limit exceeded
InvalidCid(String), // Invalid CID
InvalidNamespace(String), // Unknown namespace
InvalidPeerId(String), // Invalid peer ID
DnsResolutionFailed(String), // DNS query failed
InvalidDomain(String), // Invalid domain name
OfflineMode, // Offline mode enabled
}
How It Works
- Query DNS: Queries
_dnslink.{domain}TXT records - Fallback: Falls back to bare domain if
_dnslink.fails - Parse Record: Extracts
dnslink=/namespace/valueformat - Handle Namespace:
/ipfs/<cid>→ Parse CID and return/ipns/<peer-id>→ Parse peer ID and return/dnslink/<domain>→ Recursively resolve
- CNAME: Follows CNAME records if no TXT found
- Recursion: Supports up to 32 levels of recursion
Real-World Examples
Successfully resolves:
ipfs.tech→bafybeibb7bijpaz4kp5qrde45ui66lrzeqdb6kjabyorafmfzc6v6cls7qdocs.ipfs.tech→bafybeihc3gzbj642jgt4dkgxebvnzoww53oahwvfbpxbmiiotajrpx6uja
Testing
Run tests:
cargo test -p helia-dnslink
Run network tests:
cargo test -p helia-dnslink -- --ignored --nocapture
Performance
- DNS resolution: ~0.4-0.8 seconds (with DNS-over-HTTPS)
- Caching: Configurable DNS cache for repeated queries
- Async: Non-blocking async/await operations
Compatibility
- ✅ DNSLink Spec: Fully compliant with DNSLink specification
- ✅ TypeScript Helia: API-compatible factory function pattern
- ✅ IPFS Ecosystem: Works with standard IPFS infrastructure
- ✅ DNS-over-HTTPS: Secure DNS resolution
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Resources
Dependencies
~27–44MB
~648K SLoC