Express 请求体解析与参数获取详解

151 阅读3分钟

在 Web 开发中,服务器经常需要解析客户端发送的请求数据,并根据不同参数进行业务处理。Express 框架为开发者提供了强大的请求体解析和参数获取能力,极大简化了开发流程。下面将详细介绍如何在 Express 中解析不同类型的请求体、获取各类请求参数,以及动态路由的最佳实践。

解析请求体(Body)

1. 解析 JSON 格式的请求体

许多前端应用(如 React、Vue、移动App)在与后端通信时,常常以 JSON 格式发送数据。Express 提供了内置中间件 express.json() 用于自动解析 JSON 格式的请求体:

import express from 'express'

const app = express()

// express.json() 返回一个内置中间件
// 作用:解析 Content-Type 为 application/json 的请求体
// 本质:监听 req 的 data 和 end 事件,end 事件触发时反序列化请求体,并挂载到 req.body 上
app.use(express.json())

app.post('/login', (req, res) => {
  // 解析结果会自动挂载到 req.body 上,是一个对象结构
  console.log(req.body)
  res.send('login success')
})

app.listen(3000, () => {
  console.log('Server is running on port 3000')
})

这样,前端通过 fetchaxios 发送的 JSON 数据就能被后端轻松获取和处理。

2. 解析 URL-Encoded 格式的请求体

表单提交或部分前端框架常用 application/x-www-form-urlencoded 格式。Express 也提供了 express.urlencoded() 中间件来解析该格式:

import express from 'express'

const app = express()

// 解析 application/x-www-form-urlencoded 格式的请求体
// 早期 Express 需要设置 extended: true 来使用 qs 模块,最新版本已默认集成,无需额外设置
app.use(express.urlencoded())

app.post('/login', (req, res) => {
  // 解析结果同样挂载到 req.body 上
  console.log(req.body)
  res.send('login success')
})

app.listen(3000, () => {
  console.log('Server is running on port 3000')
})

无论是表单提交还是前端以 URL 编码格式发送的数据,都可以通过 req.body 直接获取。

获取请求参数

Express 提供了多种方式获取请求中的参数,主要包括查询参数路由参数两种。

1. 查询参数(Query)

查询参数通常跟在 URL 的 ? 后面。例如:/users?offset=10&limit=20

import express from 'express'

const app = express()

app.get('/', (req, res) => {
  // req.query 获取查询参数,所有值均为字符串类型
  const { offset, limit } = req.query
  res.json({
    offset,
    limit
  })
})

app.listen(3000, () => {
  console.log('Server is running on port 3000')
})

注意:所有查询参数的值都是字符串类型,如需数值运算需手动转换。

2. 路由参数(Params)

路由参数用于定义动态路由。例如:/user/123 中的 123 就是动态参数。

import express from 'express'

const app = express()

app.get('/:id', (req, res) => {
  // req.params 获取路由参数,同样为字符串类型
  const { id } = req.params
  res.json({
    id
  })
})

app.listen(3000, () => {
  console.log('Server is running on port 3000')
})

动态路由与参数校验

有时候需要对路由参数进行格式校验,比如只允许数字作为 ID。虽然 Express 4 支持通过正则表达式定义路由参数,但 Express 5 及以后版本已不再支持这种写法。推荐如下方式进行参数校验:

import express from 'express'

const app = express()

app.get('/:id', (req, res, next) => {
  const id = req.params.id

  // 如果 id 不是数字,则跳过该中间件,交由后续路由处理
  if (!/^\d+$/.test(id)) {
    return next()
  }

  res.json({ id })
})

// 兜底路由,处理未匹配到的情况
app.use((req, res) => {
  res.status(404).json({ error: 'Not found' })
})

app.listen(3000, () => {
  console.log('Server is running on port 3000')
})

这种方式不仅可读性好,而且兼容性强,适合 Express 的所有主流版本。