Skip to content

Commit 52f8e90

Browse files
committed
doc(dispatch, urlbuilder): document subdomain-based routing support
Expand documentation to cover subdomain parsing (`SubdomainFromHost`) and URL generation (`SubdomainURL`) in `urlbuilder`. Update `dispatch` package docs to explain `HostHasSubdomain` matcher for subdomain-based request routing. This enables flexible routing scenarios such as S3 virtual-hosted-style addressing.
1 parent cdebbfb commit 52f8e90

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

pkg/dispatch/dispatch.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Package dispatch provides a router-agnostic HTTP request dispatcher that
2-
// routes to handlers based on Matcher conditions (query parameters, and
3-
// eventually other request attributes like headers).
2+
// routes to handlers based on Matcher conditions query parameters, headers,
3+
// and Host-header subdomain checks.
44
//
55
// A Dispatcher implements http.Handler and can be used with any Go HTTP router.
66
// Routes are evaluated in specificity order — the first route whose matchers
@@ -15,6 +15,20 @@
1515
// })
1616
//
1717
// http.Handle("/bucket", d) // works with any router
18+
//
19+
// # Host-based dispatch
20+
//
21+
// HostHasSubdomain matches when the request's Host header is a subdomain of
22+
// a configured canonical domain (see pkg/urlbuilder's SubdomainFromHost for
23+
// exact semantics). This is the building block for serving two addressing
24+
// styles from one process — e.g. S3 path-style vs. virtual-hosted-style
25+
// requests, or per-tenant subdomains — by routing the subdomain case to one
26+
// handler and falling through to Default for everything else:
27+
//
28+
// d := dispatch.New(func(b *dispatch.Builder) {
29+
// b.When(dispatch.HostHasSubdomain("s3.example.com")).Do(vhostRouter.ServeHTTP)
30+
// b.Default(pathRouter.ServeHTTP)
31+
// })
1832
package dispatch
1933

2034
import (

pkg/urlbuilder/doc.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,26 @@
6969
// // Development: S3_CANONICAL_DOMAIN=""
7070
// // Production: S3_CANONICAL_DOMAIN="s3.example.com"
7171
//
72+
// # Subdomain-Style Addressing
73+
//
74+
// SubdomainFromHost and Builder.SubdomainURL are general host-based routing
75+
// primitives for apps that address a resource via a subdomain label rather
76+
// than (or in addition to) a URL path — e.g. S3 virtual-hosted-style bucket
77+
// access ("mybucket.s3.example.com") or per-tenant subdomains.
78+
//
79+
// // Resolve a label from an inbound request's Host header.
80+
// label, ok := urlbuilder.SubdomainFromHost(r.Host, "s3.example.com")
81+
// // label == "mybucket", ok == true for Host: mybucket.s3.example.com
82+
//
83+
// // Build a subdomain-style URL for a given label.
84+
// urls := urlbuilder.New("s3.example.com")
85+
// url, ok := urls.SubdomainURL("mybucket", "/path/to/object.txt")
86+
// // url == "https://mybucket.s3.example.com/path/to/object.txt"
87+
//
88+
// Pairing SubdomainFromHost with pkg/dispatch's HostHasSubdomain matcher lets
89+
// a single process serve both addressing styles, dispatching per request
90+
// based on whether Host resolves to a subdomain.
91+
//
7292
// For complete documentation and examples, see:
7393
// https://github.com/mallardduck/teapot-router/blob/main/docs/URLBUILDER.md
7494
package urlbuilder

0 commit comments

Comments
 (0)