一、解析与默认策略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`;路由映射按版本选择。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部