Request对象 #

一、Request概述 #

Request对象封装了HTTP请求的所有信息,包括请求参数、请求头、请求体等。

1.1 Request对象结构 #

javascript
fastify.get('/test', async (request, reply) => {
  console.log(request.id)
  console.log(request.method)
  console.log(request.url)
  console.log(request.headers)
  console.log(request.params)
  console.log(request.query)
  console.log(request.body)
  console.log(request.ip)
  console.log(request.ips)
  console.log(request.hostname)
  console.log(request.protocol)
  console.log(request.cookies)
  
  return { ok: true }
})

二、请求标识 #

2.1 请求ID #

javascript
fastify.get('/request-id', async (request, reply) => {
  return { requestId: request.id }
})

自定义请求ID生成:

javascript
const { v4: uuidv4 } = require('uuid')

const fastify = require('fastify')({
  genReqId: (req) => uuidv4()
})

2.2 请求方法 #

javascript
fastify.all('/method', async (request, reply) => {
  return {
    method: request.method,
    isGet: request.method === 'GET',
    isPost: request.method === 'POST'
  }
})

2.3 请求URL #

javascript
fastify.get('/url-info', async (request, reply) => {
  return {
    url: request.url,
    originalUrl: request.originalUrl,
    path: request.url.split('?')[0],
    queryString: request.url.split('?')[1]
  }
})

三、请求参数 #

3.1 路径参数 #

javascript
fastify.get('/users/:id', async (request, reply) => {
  const { id } = request.params
  return { userId: id }
})

fastify.get('/posts/:postId/comments/:commentId', async (request, reply) => {
  const { postId, commentId } = request.params
  return { postId, commentId }
})

3.2 查询参数 #

javascript
fastify.get('/search', async (request, reply) => {
  const { q, page, limit } = request.query
  return {
    query: q,
    page: page || 1,
    limit: limit || 10
  }
})

查询参数验证:

javascript
fastify.get('/search', {
  schema: {
    querystring: {
      type: 'object',
      properties: {
        q: { type: 'string' },
        page: { type: 'integer', minimum: 1 },
        limit: { type: 'integer', minimum: 1, maximum: 100 }
      }
    }
  }
}, async (request, reply) => {
  return request.query
})

3.3 请求体 #

javascript
fastify.post('/users', async (request, reply) => {
  const { name, email, age } = request.body
  return { name, email, age }
})

请求体验证:

javascript
fastify.post('/users', {
  schema: {
    body: {
      type: 'object',
      required: ['name', 'email'],
      properties: {
        name: { type: 'string', minLength: 2 },
        email: { type: 'string', format: 'email' },
        age: { type: 'integer', minimum: 0 }
      }
    }
  }
}, async (request, reply) => {
  return request.body
})

四、请求头 #

4.1 获取请求头 #

javascript
fastify.get('/headers', async (request, reply) => {
  return {
    userAgent: request.headers['user-agent'],
    authorization: request.headers.authorization,
    contentType: request.headers['content-type'],
    accept: request.headers.accept,
    allHeaders: request.headers
  }
})

4.2 常用请求头 #

javascript
fastify.get('/common-headers', async (request, reply) => {
  return {
    host: request.headers.host,
    connection: request.headers.connection,
    cacheControl: request.headers['cache-control'],
    acceptLanguage: request.headers['accept-language'],
    acceptEncoding: request.headers['accept-encoding'],
    referer: request.headers.referer,
    origin: request.headers.origin
  }
})

4.3 自定义请求头 #

javascript
fastify.get('/custom-headers', async (request, reply) => {
  return {
    apiKey: request.headers['x-api-key'],
    requestId: request.headers['x-request-id'],
    apiVersion: request.headers['x-api-version']
  }
})

五、客户端信息 #

5.1 IP地址 #

javascript
fastify.get('/ip', async (request, reply) => {
  return {
    ip: request.ip,
    ips: request.ips,
    realIp: request.headers['x-real-ip'],
    forwardedFor: request.headers['x-forwarded-for']
  }
})

信任代理配置:

javascript
const fastify = require('fastify')({
  trustProxy: true
})

fastify.get('/ip', async (request, reply) => {
  return {
    ip: request.ip,
    ips: request.ips
  }
})

5.2 主机名 #

javascript
fastify.get('/hostname', async (request, reply) => {
  return {
    hostname: request.hostname,
    host: request.headers.host
  }
})

5.3 协议 #

javascript
fastify.get('/protocol', async (request, reply) => {
  return {
    protocol: request.protocol,
    secure: request.protocol === 'https',
    scheme: request.protocol
  }
})

六、Cookie #

6.1 获取Cookie #

javascript
fastify.register(require('@fastify/cookie'))

fastify.get('/cookies', async (request, reply) => {
  return {
    all: request.cookies,
    sessionId: request.cookies.sessionId,
    userId: request.cookies.userId
  }
})

6.2 Cookie验证 #

javascript
fastify.get('/protected', {
  schema: {
    cookies: {
      type: 'object',
      required: ['sessionId'],
      properties: {
        sessionId: { type: 'string', minLength: 10 }
      }
    }
  }
}, async (request, reply) => {
  return { sessionId: request.cookies.sessionId }
})

七、文件上传 #

7.1 单文件上传 #

javascript
fastify.register(require('@fastify/multipart'))

fastify.post('/upload', async (request, reply) => {
  const data = await request.file()
  
  return {
    filename: data.filename,
    mimetype: data.mimetype,
    encoding: data.encoding,
    fields: data.fields
  }
})

7.2 多文件上传 #

javascript
fastify.post('/uploads', async (request, reply) => {
  const files = []
  
  for await (const part of request.parts()) {
    if (part.type === 'file') {
      files.push({
        filename: part.filename,
        mimetype: part.mimetype
      })
    }
  }
  
  return { files }
})

7.3 获取文件内容 #

javascript
fastify.post('/upload-content', async (request, reply) => {
  const data = await request.file()
  const buffer = await data.toBuffer()
  
  return {
    filename: data.filename,
    size: buffer.length,
    content: buffer.toString('base64')
  }
})

八、请求上下文 #

8.1 路由配置 #

javascript
fastify.get('/config', {
  config: {
    customSetting: 'value',
    auth: true
  }
}, async (request, reply) => {
  return {
    routeConfig: request.routeConfig,
    context: request.context
  }
})

8.2 服务器实例 #

javascript
fastify.get('/server', async (request, reply) => {
  return {
    serverAddress: request.server.address(),
    serverConnections: request.server.connections
  }
})

九、自定义属性 #

9.1 装饰Request #

javascript
fastify.decorateRequest('customData', null)

fastify.addHook('onRequest', async (request, reply) => {
  request.customData = {
    timestamp: Date.now(),
    requestId: request.id
  }
})

fastify.get('/custom', async (request, reply) => {
  return { customData: request.customData }
})

9.2 用户信息 #

javascript
fastify.decorateRequest('user', null)

fastify.addHook('preHandler', async (request, reply) => {
  const token = request.headers.authorization
  
  if (token) {
    try {
      request.user = await verifyToken(token)
    } catch (err) {
      request.log.warn('Token verification failed')
    }
  }
})

fastify.get('/profile', async (request, reply) => {
  return { user: request.user }
})

十、请求日志 #

10.1 使用请求日志 #

javascript
fastify.get('/log', async (request, reply) => {
  request.log.info('Info message')
  request.log.warn('Warning message')
  request.log.error('Error message')
  
  return { logged: true }
})

10.2 结构化日志 #

javascript
fastify.get('/structured-log', async (request, reply) => {
  request.log.info({
    action: 'user_action',
    userId: 123,
    data: { key: 'value' }
  })
  
  return { logged: true }
})

十一、Request方法 #

11.1 jwtVerify #

javascript
fastify.register(require('@fastify/jwt'), { secret: 'secret' })

fastify.get('/protected', async (request, reply) => {
  await request.jwtVerify()
  return { user: request.user }
})

11.2 unsignCookie #

javascript
fastify.register(require('@fastify/cookie'), { secret: 'secret' })

fastify.get('/unsign', async (request, reply) => {
  const data = request.unsignCookie(request.cookies.data)
  return {
    valid: data.valid,
    value: data.value
  }
})

十二、最佳实践 #

12.1 参数解构 #

javascript
fastify.post('/users', async (request, reply) => {
  const { name, email, age } = request.body
  const { id } = request.params
  const { page, limit } = request.query
  
  return { id, name, email, age, page, limit }
})

12.2 默认值处理 #

javascript
fastify.get('/search', async (request, reply) => {
  const {
    q = '',
    page = 1,
    limit = 10,
    sort = 'createdAt',
    order = 'desc'
  } = request.query
  
  return { q, page, limit, sort, order }
})

12.3 类型转换 #

javascript
fastify.get('/users/:id', async (request, reply) => {
  const id = parseInt(request.params.id, 10)
  
  if (isNaN(id)) {
    reply.code(400).send({ error: 'Invalid ID' })
    return
  }
  
  return { userId: id }
})

十三、总结 #

本章我们学习了:

  1. 请求标识:请求ID、方法、URL
  2. 请求参数:路径参数、查询参数、请求体
  3. 请求头:获取请求头、常用请求头、自定义请求头
  4. 客户端信息:IP地址、主机名、协议
  5. Cookie:获取Cookie、Cookie验证
  6. 文件上传:单文件、多文件、文件内容
  7. 请求上下文:路由配置、服务器实例
  8. 自定义属性:装饰Request、用户信息
  9. 请求日志:使用日志、结构化日志
  10. Request方法:jwtVerify、unsignCookie

接下来让我们学习Response对象!

最后更新:2026-03-28