一、解析与默认策略type Req = { headers: Record<string, string | undefined>; path: string }
type Res = { setHeader: (k: string, v: string) => void; status: (n: number) => Res; end: (b?: string) => void }
function parseAccept(accept: string | undefined): { type: string; version?: number } {
const a = accept || ''
const m = a.match(/application\/vnd\.app\+json;\s*version=(\d+)/i)
if (m) return { type: 'application/vnd.app+json', version: Number(m[1]) }
if (a.includes('application/json')) return { type: 'application/json' }
return { type: '' }
}
const DEFAULT_VERSION = 1
const MAX_VERSION = 3
二、版本选择与校验function selectVersion(acc: { type: string; version?: number }): number {
if (acc.version && acc.version >= 1 && acc.version <= MAX_VERSION) return acc.version
return DEFAULT_VERSION
}
function unsupported(acc: { type: string; version?: number }): boolean {
if (acc.type === '') return true
if (acc.version && (acc.version < 1 || acc.version > MAX_VERSION)) return true
return false
}
三、路由映射与响应type Handler = (req: Req, res: Res) => void
const routes: Record<string, Record<number, Handler>> = {
'/users': {
1: (req, res) => { res.setHeader('Content-Type', 'application/vnd.app+json; version=1'); res.end(JSON.stringify({ users: [{ id: 1, name: 'a' }] })) },
2: (req, res) => { res.setHeader('Content-Type', 'application/vnd.app+json; version=2'); res.end(JSON.stringify({ data: { users: [{ id: 1, name: 'a', email: 'x@y' }] } })) },
3: (req, res) => { res.setHeader('Content-Type', 'application/vnd.app+json; version=3'); res.end(JSON.stringify({ result: { items: [{ id: 1, name: 'a', email: 'x@y', roles: ['user'] }] } })) }
}
}
四、协商流程与验收function handle(req: Req, res: Res) {
const acc = parseAccept(req.headers['accept'])
if (unsupported(acc)) return res.status(406).end('not_acceptable')
const v = selectVersion(acc)
const table = routes[req.path]
const h = table?.[v]
if (!h) return res.status(404).end('not_found')
h(req, res)
}
Accept解析支持`application/vnd.app+json; version=N`与`application/json`;默认版本回退到`1`;最大版本为`3`。不支持版本或类型返回`406`;响应头包含版本化`Content-Type`;路由映射按版本选择。

发表评论 取消回复