摇摇欲坠验证错误request.path不应具有其他属性

时间:2020-04-24 13:55:38

标签: node.js validation routes swagger endpoint

这与其中包含“ user_id”参数的所有路径(即,除postUser之外的所有路径)有关。当我用邮递员测试这些端点时,我得到400,并带有一条消息“ request.path不应该具有 其他属性”。 我以下列方式在我的路线中使用软件包作为通用的验证器中间件。例如: router.get('/:userId',swaggerValidator.validate,contextExtractor,getUserById);

首先进行大刀阔斧的验证,然后再进行另外2个中间件的验证。 可以在以下位置找到该软件包:https://www.npmjs.com/package/openapi-validator-middleware

如果我放弃验证器中间件,一切都会很好,并且代码将按预期工作。

请参见下面的招摇文件:

swagger: "2.0"
info:
  description: "This is an external Users service API. It manages any user info in the systems, including its personal data, address and additional needed values, all in favour of maintaining the updated and relevant data which is either business-related or provided when a user requests any action in the system."
  version: "1.0.0"
  title: "Users Micro Service"
basePath: "/v1"
tags:
  - name: "User Details"
    description: "A user's data and info, supporting CRUD operations"
  - name: "User Addresses"
    description: "All the addresses data of a user"
  - name: "User Address"
    description: "A user's single address data"
schemes:
  - "https"
  - "http"
consumes:
  - "application/json; charset=utf-8"
produces:
  - "application/json; charset=utf-8"
paths:
  '/users':
    post:
      tags:
        - "User Details"
      summary: "Create a new user in the system"
      operationId: "postUser"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - in: "body"
          name: "User Request"
          description: "The user's data to be stored"
          required: true
          schema:
            $ref: "#/definitions/user_request"
      responses:
        201:
          description: "Successful Operation"
          schema:
            $ref: "#/definitions/user_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        409:
          description: "Conflict - email already exists"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
  '/users/:user_id':
    get:
      tags:
        - "User Details"
      summary: "Get the user's data by its Id"
      operationId: "getUserById"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
      responses:
        200:
          description: "Successful operation"
          schema:
            $ref: "#/definitions/user_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        404:
          description: "User was not found"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
    patch:
      tags:
        - "User Details"
      summary: "Modify an existing user's data"
      operationId: "patchUserById"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
        - in: "body"
          name: "User data"
          description: "The user's data to be modified"
          required: true
          schema:
            $ref: "#/definitions/user_patch_request"
      responses:
        200:
          description: "Successful Operation"
          schema:
            $ref: "#/definitions/user_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        404:
          description: "Not Found"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
    put:
      tags:
        - "User Details"
      summary: "Modify an existing user's data by overriding it"
      operationId: "putUserById"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
        - in: "body"
          name: "User data"
          description: "The user's data to be modified"
          schema:
            $ref: "#/definitions/user_put_request"
      responses:
        200:
          description: "Successful Operation"
          schema:
            $ref: "#/definitions/user_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        404:
          description: "Not Found"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
  '/users/:user_id/addresses':
    post:
      tags:
        - "User Address"
      summary: "Create a new address for a user and store it in the database"
      operationId: "postAddress"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
        - in: "body"
          name: "Address Request"
          description: "The address data to be stored"
          required: true
          schema:
            $ref: "#/definitions/put_user_address_request"
      responses:
        201:
          description: "Successful Operation"
          schema:
            $ref: "#/definitions/user_address_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
    get:
      tags:
        - "User Addresses"
      summary: "Get all addresses of a user by its id"
      operationId: "getAddresses"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
      responses:
        200:
          description: "Successful Operation"
          schema:
            type: "array"
            items:
              $ref: "#/definitions/user_address_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        404:
          description: "User not found"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
  '/users/:user_id/addresses/:address_id':
    get:
      tags:
        - "User Address"
      summary: "Get a user's address by its Id"
      operationId: "getAddressById"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
        - $ref: "#/parameters/address_id"
      responses:
        200:
          description: "Successful Operation"
          schema:
            $ref: "#/definitions/user_address_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        404:
          description: "Not Found"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
    put:
      tags:
        - "User Address"
      summary: "Modify a user's existing address data by overriding it"
      operationId: "putAddressById"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
        - $ref: "#/parameters/address_id"
        - in: "body"
          name: "Address"
          description: "The address's data to be modified"
          schema:
            $ref: "#/definitions/put_user_address_request"
      responses:
        200:
          description: "Successful Operation"
          schema:
            $ref: "#/definitions/user_address_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        404:
          description: "Not Found"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
    patch:
      tags:
        - "User Address"
      summary: "Add or modify to an existing user's address data"
      operationId: "patchAddressById"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
        - $ref: "#/parameters/address_id"
        - in: "body"
          name: "Address"
          description: "The address data to be modified"
          schema:
            $ref: "#/definitions/patch_user_address_request"
      responses:
        200:
          description: "Successful Operation"
          schema:
            $ref: "#/definitions/user_address_resource"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        404:
          description: "Not Found"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
    delete:
      tags:
        - "User Address"
      summary: "Deletes a user's address by its Id"
      operationId: "deleteAddressById"
      produces:
        - "text/plain; charset=utf-8"
      parameters:
        - $ref: "#/parameters/company_user_id"
        - $ref: "#/parameters/company_request_id"
        - $ref: "#/parameters/user_id"
        - $ref: "#/parameters/address_id"
      responses:
        204:
          description: "Successful Operation - No content"
        400:
          description: "Bad Request"
          schema:
            $ref: "#/definitions/error"
        404:
          description: "Not Found"
          schema:
            $ref: "#/definitions/error"
        500:
          description: "Internal Error"
          schema:
            $ref: "#/definitions/error"
definitions:
  user_request:
    type: "object"
    description: "User request body"
    required:
      - email_address
      - terms_accepted
      - first_name
      - last_name
    properties:
      email_address:
        type: "string"
        description: "The user's email address (unique)"
      first_name:
        type: "string"
        description: "The user's first name"
      last_name:
        type: "string"
        description: "The user's last name"
      marketing_opt_in_accepted:
        type: "boolean"
        description: "Boolean to determine if the user has opted in for marketing"
        default: false
      terms_accepted:
        type: "boolean"
        description: "Boolean to determine if the user has accepted the site's terms"
      phone_number:
        type: "string"
        description: "The user's phone number"
      additional_values:
        type: "object"
        x-example: {
          "key1" : "value1",
          "key2" : "value2"
        }
  user_put_request:
    required:
      - email_address
      - first_name
      - last_name
    type: "object"
    properties:
      email_address:
        type: "string"
        description: "The user's email address"
      first_name:
        type: "string"
        description: "The user's first name"
      last_name:
        type: "string"
        description: "The user's last name"
      marketing_opt_in_accepted:
        type: "boolean"
        description: "Boolean to determine if the user has opted in for marketing (default: false)"
        default: false
      phone_number:
        type: "string"
        description: "The user's phone number"
      additional_values:
        type: "object"
        x-example: {
          "key1" : "value1",
          "key2" : "value2"
        }
  user_patch_request:
    type: "object"
    properties:
      email_address:
        type: "string"
        description: "The user's email address"
      first_name:
        type: "string"
        description: "The user's first name"
      last_name:
        type: "string"
        description: "The user's last name"
      marketing_opt_in_accepted:
        type: "boolean"
        description: "Boolean to determine if the user has opted in for marketing"
        default: false
      phone_number:
        type: "string"
        description: "The user's phone number"
      additional_values:
        type: "object"
        x-example: {
          "key1": "value1",
          "key2": "value2"
        }
  user_resource:
    type: "object"
    allOf: [$ref: '#/definitions/user_request', $ref: '#/definitions/updatable_object_metadata']
    required:
      - date_terms_accepted
    properties:
      date_terms_accepted:
        type: "string"
        format: "date-time"
        description: "Time stamp of when the user has accepted the site's terms"
  put_user_address_request:
    required:
      - address_line_1
      - city
      - postal_code
      - country_code
    properties:
      nickname:
        type: "string"
        description: "A human-readable nickname for the address"
        x-example: "HOME"
      address_line_1:
        type: "string"
        description: "A text line containing street name and number"
        x-example: "3 Florentin Street"
      address_line_2:
        type: "string"
        description: "A text line containing apartment number, floor, entrance, etc."
        x-example: "372A, 7th floor"
      address_line_3:
        type: "string"
        description: "A text line containing additional delivery instructions"
        x-example: "Please knock on the door instead of ringing the bell"
      country_code:
        type: "string"
        description: "3-letter alpha-code for a country (capital letters only)"
        x-example: "GBR"
      state_province:
        type: "string"
        description: "The state or province in which the address is in"
        x-example: "Yorkshire"
      city:
        type: "string"
        description: "The city in which the address is in"
        x-example: "London"
      postal_code:
        type: "string"
        description: "The address' zipcode"
        x-example: "EC1A 1BB"
      address_type:
        type: "string"
        description: "The type of which the address belongs to"
        enum: ["RESIDENTIAL", "OFFICE", "HOTEL", "BUSINESS"]
        x-example: "OFFICE"
  patch_user_address_request:
    type: "object"
    properties:
      nickname:
        type: "string"
        description: "A human-readable nickname for the address"
        x-example: "HOME"
      address_line_1:
        type: "string"
        description: "A text line containing street name and number"
        x-example: "3 Florentin Street"
      address_line_2:
        type: "string"
        description: "A text line containing apartment number, floor, entrance, etc."
        x-example: "372A, 7th floor"
      address_line_3:
        type: "string"
        description: "A text line containing additional delivery instructions"
        x-example: "Please knock on door instread of ringing bell"
      country_code:
        type: "string"
        description: "3-letter alpha-code for a country (capital letters only)"
        x-example: "GBR"
      state_province:
        type: "string"
        description: "The state or province in which the address is in"
        x-example: "Yorkshire"
      city:
        type: "string"
        description: "The city in which the address is in"
        x-example: "London"
      postal_code:
        type: "string"
        description: "The address' zipcode"
        x-example: "EC1A 1BB"
      address_type:
        type: "string"
        description: "The type of which the address belongs to"
        enum: ["RESIDENTIAL", "OFFICE", "HOTEL", "BUSINESS"]
        x-example: "OFFICE"
  user_address_resource:
    type: "object"
    required:
      - id
      - address_line_1
      - address_created
      - address_updated
      - city
      - country_code
      - postal_code
    properties:
      id:
        type: "string"
        format: "uuid"
        description: "The address Id"
        x-example: "23cfeebf-45ef-4446-9f2f-017894fc806e"
      nickname:
        type: "string"
        description: "A human-readable nickname for the address"
        x-example: "HOME"
      address_line_1:
        type: "string"
        description: "A text line containing street name and number"
        x-example: "3 Florentin Street"
      address_line_2:
        type: "string"
        description: "A text line containing apartment number, floor, entrance, etc."
        x-example: "372A, 7th floor"
      address_line_3:
        type: "string"
        description: "A text line containing additional delivery instructions"
        x-example: "Please knock on door instread of ringing bell"
      country_code:
        type: "string"
        description: "3-letter alpha-code for a country (capital letters only)"
        x-example: "GBR"
      state_province:
        type: "string"
        description: "The state or province in which the address is in"
        x-example: "Yorkshire"
      city:
        type: "string"
        description: "The city in which the address is in"
        x-example: "London"
      postal_code:
        type: "string"
        description: "The address' zipcode"
        x-example: "EC1A 1BB"
      address_type:
        type: "string"
        description: "The type of which the address belongs to"
        enum: ["RESIDENTIAL", "OFFICE", "HOTEL", "BUSINESS"]
        x-example: "OFFICE"
      address_created:
        type: "string"
        format: "date-time"
        description: "Timestamp of when the address was created"
        x-example: "2017-08-19 12:17:55 -0400"
      address_updated:
        type: "string"
        format: "date-time"
        description: "Timestamp of when the address was updated"
        x-example: "2017-08-19 12:17:55 -0400"
      user_id_created:
        type: "string"
        format: "uuid"
        description: "The user id which created the address"
        x-example: "1df65272-a44e-4b8c-887d-b645ec9136a0"
      user_id_updated:
        type: "string"
        format: "uuid"
        description: "The user id which last updated the address"
        x-example: "1df65272-a44e-4b8c-887d-b645ec9136a0"
  object_metadata: 
    type: "object"
    required: 
      - id
      - created_time
      - user_id_created
      - updated_time
    properties: 
      id: 
        type: "string"
        format: "uuid"
      created_time: 
        type: "string"
        format: "date-time"
      user_id_created: 
        type: "string"
        format: "uuid"
      updated_time: 
        type: "string"
        format: "date-time"
  updatable_object_metadata: 
    type: "object"
    allOf: 
      - $ref: '#/definitions/object_metadata'
    required: 
      - user_id_updated
    properties: 
      user_id_updated: 
        type: "string"
        format: "uuid"
  error:
    type: "object"
    required:
      - "message"
    properties:
      message:
        type: "string"
        description: "The error's message"
      more_info:
        type: "string"
        description: "More info if it exists"
parameters:
  company_user_id:
    name: "x-company-user-id"
    in: "header"
    description: "The User Id"
    required: true
    type: "string"
    format: "uuid"
    x-example: "15325c58-a41a-4105-bae1-99fa3a8bedc7"
  company_request_id:
    name: "x-company-request-id"
    in: "header"
    description: "The Request Id"
    required: true
    type: "string"
    format: "uuid"
    x-example: "5134366e-ce9e-42ea-921b-ebe11257a773"
  user_id:
    name: "user_id"
    in: "path"
    description: "The user's Id"
    required: true
    type: "string"
    format: "uuid"
    x-example: "fc1e2015-f408-465a-af97-6621a3754764"
  address_id:
    name: "address_id"
    in: "path"
    required: true
    type: "string"
    format: "uuid"
    x-example: "08ed91c3-ce96-4c93-b75a-5a0c6eb8d13c"


1 个答案:

答案 0 :(得分:0)

您的示例使用:param表示路径参数,OpenAPI不支持。 OpenAPI使用{param}表示法。您需要更改API定义以使用{param}而不是:param

不正确:

paths:
  '/users':
    ...
  '/users/:user_id':
    ...
  '/users/:user_id/addresses':
    ...
  '/users/:user_id/addresses/:address_id':
    ...

正确:

paths:
  '/users':
    ...
  '/users/{user_id}':
    ...
  '/users/{user_id}/addresses':
    ...
  '/users/{user_id}/addresses/{address_id}':
    ...