Skip to content

Commit

Permalink
fix: redirect to proper encoded dnslink subdomain
Browse files Browse the repository at this point in the history
  • Loading branch information
SgtPooki committed Mar 11, 2024
1 parent 55530cf commit 0bfff97
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
32 changes: 27 additions & 5 deletions src/dns-link-labels.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
import { CID } from 'multiformats/cid'

/**
* For dnslinks see https://specs.ipfs.tech/http-gateways/subdomain-gateway/#host-request-header
* DNSLink names include . which means they must be inlined into a single DNS label to provide unique origin and work with wildcard TLS certificates.
*/

// DNS label can have up to 63 characters, consisting of alphanumeric
// characters or hyphens -, but it must not start or end with a hyphen.
const dnsLabelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/

/**
* We can receive either IPNS Name string or DNSLink label string here.
* IPNS Names do not have dots or dashes.
*/
export function isValidDnsLabel (label: string): boolean {
// If string is not a valid IPNS Name (CID)
// then we assume it may be a valid DNSLabel.
try {
CID.parse(label)
return false
} catch {
return dnsLabelRegex.test(label)
}
}

/**
* We can receive either a peerId string or dnsLink label string here. PeerId strings do not have dots or dashes.
* Checks if label looks like inlined DNSLink.
* (https://specs.ipfs.tech/http-gateways/subdomain-gateway/#host-request-header)
*/
export function isDnsLabel (label: string): boolean {
return ['-', '.'].some((char) => label.includes(char))
export function isInlinedDnsLink (label: string): boolean {
return isValidDnsLabel(label) && label.includes('-') && !label.includes('.')
}

/**
Expand All @@ -18,7 +40,7 @@ export function isDnsLabel (label: string): boolean {
* @example en-wikipedia--on--ipfs-org.ipns.example.net -> example.net/ipns/en.wikipedia-on-ipfs.org
*/
export function dnsLinkLabelDecoder (linkLabel: string): string {
return linkLabel.replace(/--/g, '-').replace(/-/g, '.')
return linkLabel.replace(/--/g, '%').replace(/-/g, '.').replace(/%/g, '-')
}

/**
Expand All @@ -29,5 +51,5 @@ export function dnsLinkLabelDecoder (linkLabel: string): string {
* @example example.net/ipns/en.wikipedia-on-ipfs.org → Host: en-wikipedia--on--ipfs-org.ipns.example.net
*/
export function dnsLinkLabelEncoder (linkLabel: string): string {
return linkLabel.replace(/\./g, '-').replace(/-/g, '--')
return linkLabel.replace(/-/g, '--').replace(/\./g, '-')
}
7 changes: 6 additions & 1 deletion src/heliaServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createVerifiedFetch, type VerifiedFetch } from '@helia/verified-fetch'
import { type FastifyReply, type FastifyRequest, type RouteGenericInterface } from 'fastify'
import { USE_SUBDOMAINS } from './constants.js'
import { contentTypeParser } from './content-type-parser.js'
import { dnsLinkLabelEncoder, isInlinedDnsLink } from './dns-link-labels.js'
import { getCustomHelia } from './getCustomHelia.js'
import { getIpnsAddressDetails } from './ipns-address-utils.js'
import type { ComponentLogger, Logger } from '@libp2p/interface'
Expand Down Expand Up @@ -152,8 +153,12 @@ export class HeliaServer {
// }
// finalUrl += encodeURIComponent(`?${new URLSearchParams(request.query).toString()}`)
}
let encodedDnsLink = address
if (!isInlinedDnsLink(address)) {
encodedDnsLink = dnsLinkLabelEncoder(address)
}

const finalUrl = `//${cidv1Address ?? address}.${namespace}.${request.hostname}/${relativePath ?? ''}`
const finalUrl = `//${cidv1Address ?? encodedDnsLink}.${namespace}.${request.hostname}/${relativePath ?? ''}`
this.log('redirecting to final URL:', finalUrl)
await reply
.headers({
Expand Down

0 comments on commit 0bfff97

Please sign in to comment.