HonoRequest
HonoRequest 是从 c.req
获取的对象,它封装了一个 Request 对象。
param()
获取路径参数。
// 获取单个路径参数
app.get('/entry/:id', async (c) => {
const id = c.req.param('id')
// ...
})
// 一次获取全部路径参数
app.get('/entry/:id/comment/:commentId', async (c) => {
const { id, commentId } = c.req.param()
})
query()
获取查询字符串参数。
// 获取单个 query 参数
app.get('/search', async (c) => {
const query = c.req.query('q')
})
// 一次获取所有 query 参数
app.get('/search', async (c) => {
const { q, limit, offset } = c.req.query()
})
queries()
获取同一 query 参数的多个值,例如 /search?tags=A&tags=B
。
app.get('/search', async (c) => {
// tags 是 string[]
const tags = c.req.queries('tags')
// ...
})
header()
获取请求头的值。
app.get('/', (c) => {
const userAgent = c.req.header('User-Agent')
return c.text(`Your user agent is ${userAgent}`)
})
注意:
当 c.req.header()
不传参数时,返回的所有键名都是 小写。
如果需要获取带大写的 Header 名称,应显式传入 Header 名称。
// ❌ 不可用
const headerRecord = c.req.header()
const foo = headerRecord['X-Foo']
// ✅ 可用
const foo = c.req.header('X-Foo')
parseBody()
解析请求体中的 multipart/form-data
或 application/x-www-form-urlencoded
数据。
app.post('/entry', async (c) => {
const body = await c.req.parseBody()
// ...
})
支持的行为
单文件
const body = await c.req.parseBody()
const data = body['foo']
body['foo']
类型是 (string | File)
。
如果上传了多个文件,将只取最后一个。
多文件
const body = await c.req.parseBody()
body['foo[]']
body['foo[]']
总是 (string | File)[]
。
必须使用 []
后缀。
同名多文件或多字段
如果 <input type="file" multiple />
或多个同名复选框 <input type="checkbox" name="favorites" value="Hono"/>
,
可以使用 all: true
选项:
const body = await c.req.parseBody({ all: true })
body['foo']
- 当
body['foo']
是多个文件时,会解析为(string | File)[]
。 - 当是单文件时,解析为
(string | File)
。
Dot notation(点语法)
如果设置 dot: true
,返回值会基于点语法生成结构化对象。
例如:
const data = new FormData()
data.append('obj.key1', 'value1')
data.append('obj.key2', 'value2')
const body = await c.req.parseBody({ dot: true })
// body = { obj: { key1: 'value1', key2: 'value2' } }
json()
解析 application/json
类型的请求体。
app.post('/entry', async (c) => {
const body = await c.req.json()
// ...
})
text()
解析 text/plain
类型的请求体。
app.post('/entry', async (c) => {
const body = await c.req.text()
// ...
})
arrayBuffer()
将请求体解析为 ArrayBuffer。
app.post('/entry', async (c) => {
const body = await c.req.arrayBuffer()
// ...
})
blob()
将请求体解析为 Blob。
app.post('/entry', async (c) => {
const body = await c.req.blob()
// ...
})
formData()
将请求体解析为 FormData。
app.post('/entry', async (c) => {
const body = await c.req.formData()
// ...
})
valid()
获取验证后的数据。
app.post('/posts', async (c) => {
const { title, body } = c.req.valid('form')
// ...
})
可用的验证目标有:
- form
- json
- query
- header
- cookie
- param
具体用法见 Validation 章节。
routePath
警告:
在 v4.8.0 中已弃用,请改用 Route Helper 中的 routePath()
。
app.get('/posts/:id', (c) => {
return c.json({ path: c.req.routePath })
})
当访问 /posts/123
时返回:
{ "path": "/posts/:id" }
matchedRoutes
警告:
在 v4.8.0 中已弃用,请改用 Route Helper 中的 matchedRoutes()
。
它会返回当前请求匹配到的所有路由,常用于调试。
app.use(async function logger(c, next) {
await next()
c.req.matchedRoutes.forEach(({ handler, method, path }, i) => {
const name =
handler.name ||
(handler.length < 2 ? '[handler]' : '[middleware]')
console.log(
method,
' ',
path,
' '.repeat(Math.max(10 - path.length, 0)),
name,
i === c.req.routeIndex ? '<- respond from here' : ''
)
})
})
path
获取请求的 pathname。
app.get('/about/me', async (c) => {
const pathname = c.req.path // `/about/me`
// ...
})
url
获取完整请求 URL 字符串。
app.get('/about/me', async (c) => {
const url = c.req.url // `http://localhost:8787/about/me`
// ...
})
method
获取请求方法名。
app.get('/about/me', async (c) => {
const method = c.req.method // `GET`
// ...
})
raw
获取原始的 Request 对象。
// 在 Cloudflare Workers 中使用
app.post('/', async (c) => {
const metadata = c.req.raw.cf?.hostMetadata?
// ...
})