Files
skills/docs/api-stack/api/api-plugin-site/src/service/normalize-domain.md
2026-05-29 08:20:56 +01:00

2.4 KiB

service/normalize-domain.ts

Purpose

Pure helper that mirrors the SurrealDB fn::site::domain::normalize function in TypeScript so application-tier code (the resolver, the route layer, the site service's addDomain / removeDomain paths) and database-tier code (the surql function) agree on the canonical form of a domain. Without this parity, a site stored with "acme.example.com" would be unreachable when an integrator naively passed "HTTPS://WWW.Acme.Example.Com/" from a Host header.

Features

  • Lower-cases, trims whitespace, strips http:///https://, strips www., strips a single trailing slash.
  • Pure function, zero deps, zero side effects.
  • Single source of truth for normalisation — services and middleware call this exclusively.

Usage: Basic

import { normalizeDomain } from "@suaveplan/api-plugin-site/service/normalize-domain";

normalizeDomain("HTTPS://WWW.Acme.Example.Com/");
// → "acme.example.com"

Usage: Advanced

import { normalizeDomain } from "@suaveplan/api-plugin-site/service/normalize-domain";

// Use inside a middleware to canonicalise the request domain before
// hitting the DomainResolverService.
const host = c.req.header("host") ?? c.req.header("x-forwarded-host") ?? "";
const domain = normalizeDomain(host.split(":")[0] ?? host);
const resolved = await resolver.resolve(domain);

API Reference

  • normalizeDomain(domain: string): string

Implementation Notes

  • The order matters: http(s):// MUST be stripped before www. so that https://www.example.com reduces correctly.
  • The trailing-slash strip is a single character — paths beyond the host are preserved by the caller's split (the middleware uses host.split(":") and the route layer uses the URL parser).
  • Internationalised domains (xn--) are passed through untouched; callers needing IDNA normalisation must run punycode normalisation separately.
  • The function is intentionally tolerant of leading whitespace and mixed case; in practice the Host header is canonical at the wire layer, but reverse proxies and edge workers occasionally pass through a value pulled from a configuration file that has neither been trimmed nor downcased. Normalisation here means the rest of the plugin can assume a single form.
  • Because the function is pure and synchronous, it is safe to call inside hot paths (e.g. inside the Hono middleware) without any concern over async ordering or external I/O.