4. 路径与操作定义:路径模板、HTTP方法映射、operationId、参数定义、请求体定义

路径与操作是OpenAPI契约的核心骨架。一个API端点由路径模板和HTTP方法共同唯一标识,而operationId、参数定义和请求体定义则精确描述了该操作的行为与数据约束。本章将逐一拆解这些要素,并展示它们在契约校验中的关键作用。

4.1 路径模板:从静态路径到动态参数化

路径模板使用花括号 {} 声明路径参数,允许客户端在请求时传入动态值。路径模板必须遵循以下规则:

  • 静态部分:固定字符串,如 /users、/orders。
  • 路径参数:用 {paramName} 表示,参数名必须与 parameters 中定义的 name 一致。
  • 不允许重复:同一路径模板中不能出现同名路径参数。
  • 不允许连续花括号:{a}{b} 非法,必须用分隔符如 {a}/{b}。
契约校验要点:路径模板中的参数名必须与 parameters 段中 in: path 的参数 name 完全匹配,且该参数必须标记为 required: true。
paths:
  /users/{userId}/orders/{orderId}:
    get:
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
        - name: orderId
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: 成功返回订单详情

4.2 HTTP方法映射:操作与语义的绑定

每个路径下可定义多个HTTP方法,每个方法对应一个操作对象。OpenAPI 3.0支持的方法包括:get、post、put、patch、delete、head、options、trace。方法名必须小写。

HTTP方法 典型语义 是否允许请求体 幂等性
GET 查询资源 不允许 是
POST 创建资源 允许 否
PUT 全量替换资源 允许 是
PATCH 部分更新资源 允许 否
DELETE 删除资源 不允许 是
常见错误:在 GET 或 DELETE 操作中定义 requestBody,契约校验会直接报错。同样,在 POST 或 PUT 中遗漏 requestBody 也可能导致校验失败(除非该操作确实不需要请求体)。

4.3 operationId:操作的唯一标识符

operationId 是操作对象的可选但强烈推荐的字段,用于在工具链中唯一标识一个操作。它必须满足以下约束:

  • 全局唯一:在整个API规范中,所有 operationId 不能重复。
  • 命名规范:通常采用驼峰命名法,如 getUserById、createOrder。
  • 用途:代码生成器使用 operationId 生成方法名;契约测试工具用它定位具体操作。
paths:
  /users/{userId}:
    get:
      operationId: getUserById
      summary: 根据用户ID获取用户信息
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: 用户对象
最佳实践:operationId 应使用动词+名词的格式,清晰表达操作意图。避免使用模糊名称如 doSomething 或 process。

4.4 参数定义:query、path、header、cookie

参数定义是契约校验的高频校验点。每个参数必须包含 name、in、schema 三个核心字段。in 决定了参数的位置,不同位置的参数有不同的校验规则。

参数位置 (in) 示例 序列化方式 是否必须声明 required
path /users/{id} 简单值 必须为 true
query ?page=1&size=20 form / deepObject 可选,默认 false
header X-Request-Id: abc simple 可选,默认 false
cookie Cookie: sessionId=xyz form 可选,默认 false
parameters:
  - name: page
    in: query
    required: false
    schema:
      type: integer
      minimum: 1
      default: 1
  - name: Authorization
    in: header
    required: true
    schema:
      type: string
      pattern: '^Bearer .+$'
契约校验规则:
1. path 参数必须 required: true,否则校验失败。
2. query 参数如果 required: true,则请求必须携带该参数。
3. header 参数名不区分大小写,但规范中建议使用首字母大写的驼峰格式。
4. cookie 参数较少使用,但支持结构化数据。
参数位置与HTTP请求映射 客户端 HTTP请求 服务器 请求行 GET /users/{id} HTTP/1.1 (路径参数) 请求头 Authorization: Bearer xxx X-Request-Id: abc (header参数) 查询字符串 ?page=1&size=20 &sort=name (query参数) 参数位置校验规则 • path: 必须 required: true • query: 可选 required • header: 不区分大小写 • cookie: 较少使用

4.5 请求体定义:requestBody 的结构与约束

请求体定义仅在支持请求体的HTTP方法(POST、PUT、PATCH)中使用。OpenAPI 3.0使用 requestBody 对象替代了2.0中的 body 参数,提供了更灵活的内容协商能力。

请求体定义包含三个核心部分:

  • description:对请求体的文字描述,可选但推荐。
  • required:布尔值,标识请求体是否为必须。默认 false。
  • content:一个映射,键为媒体类型(如 application/json),值为媒体类型对象,其中包含 schema 定义。
requestBody:
  description: 创建用户所需的用户信息
  required: true
  content:
    application/json:
      schema:
        type: object
        required:
          - username
          - email
        properties:
          username:
            type: string
            minLength: 3
            maxLength: 50
          email:
            type: string
            format: email
          age:
            type: integer
            minimum: 0
            maximum: 150
契约校验陷阱:
1. 如果 requestBody 标记为 required: true,但请求未携带请求体,校验失败。
2. content 中至少需要定义一个媒体类型,空 content 对象会导致校验错误。
3. 如果定义了多个媒体类型,客户端必须发送与其中之一匹配的 Content-Type 头。

4.6 路径与操作的综合校验流程

契约测试工具在验证路径与操作时,通常按以下步骤执行:

  1. 路径匹配:将实际请求路径与路径模板进行模式匹配,提取路径参数值。
  2. 方法校验:检查HTTP方法是否在路径下定义,未定义则返回405 Method Not Allowed。
  3. 参数校验:逐一校验 query、header、path、cookie 参数的类型、格式、是否必需。
  4. 请求体验证:如果操作定义了 requestBody,校验请求体的媒体类型和 schema 约束。
  5. operationId 映射:将校验通过的操作映射到对应的 operationId,用于后续的响应校验和文档生成。
路径与操作校验流程 1. 接收HTTP请求 2. 路径模板匹配 3. HTTP方法校验 返回405 Method Not Allowed 4. 参数校验 5. 请求体验证 校验失败常见原因 • 路径参数名不匹配 • 方法未在路径下定义 • 缺少必需参数或请求体
实战建议:在编写契约测试用例时,建议为每个操作至少准备三组测试数据:
1. 正常用例:所有必需参数和请求体字段均合法。
2. 边界用例:参数值在边界附近(如最小值、最大值、空字符串)。
3. 异常用例:缺少必需参数、类型错误、格式不合法。

4.7 本章小结