【问题标题】:Camel Json Validation throws NoJsonBodyValidationExceptionCamel Json 验证抛出 NoJsonBodyValidationException
【发布时间】:2020-02-03 20:30:07
【问题描述】:

我正在尝试对传入的 GET 请求执行标头验证。我参考了Camel JSON schema validator component 并按照以下步骤在我的项目中实施,即

  • 在 build.gradle 中添加 camel-json-validator-starter 依赖
  • 在我的 Spring boot 项目的 Resource 文件夹中添加 Employee.json(YAML 转换为 JSON)。最初我在这里有 Open API 3.0 yaml 规范文件,并将其转换为 json
  • 使用以下代码调用验证

    rest(/employee).id("get-employee")
        .produces(JSON_MEDIA_TYPE)
        .get()
        .description("The employee API")
        .outType(EmployeeResponse.class)
        .responseMessage()
          .code(HttpStatus.OK.toString())
          .message("Get Employee")
        .endResponseMessage()
        .route()
        .to("json-validator:openapi.json")
        .to("bean:employeeService?method=getEmployee()");
    

运行项目会引发org.apache.camel.component.jsonvalidator.NoJsonBodyValidationException,我正在使用 GET 请求,但为什么它需要请求正文,我只是想验证传入请求的标头和请求参数。我不确定我的方法是否正确以及我缺少什么。

【问题讨论】:

  • 问个简单的问题,您是否使用 JSON 版本的 OpenAPI 规范来验证消息?如果是这样就行不通了。 JSON 验证器与 OpenAPI 规范不兼容。您需要将 OpenAPI 模式转换为有效的 JSON 模式。是的,它们不同,请参见此处json-schema.org。您不能在此处使用 OpenAPI。标头等在 OpenAPI 中可用,但 JSON 模式仅验证 JSON 对象。 HTTP 标头不属于 JSON 对象。
  • 为了从开放 API 3.0 转换为 json 模式,我所做的只是将原始 yaml 文件加载到 swagger 编辑器中,然后通过“文件 -> 转换并另存为 JSON”转换为 json 模式。生成的 json 模式也具有标头验证。请参阅下面从 JSON Schema 中提取的标头定义。 "RequestId": { "in": "header", "name": "x-et-request-id", "description": "Unique ID ", "schema": { "type": "string", "maxLength": 36 }, "required": true },
  • @Namphibian 我想要实现的只是针对 GET 方法的传入请求针对 yaml/json 模式验证标头,并针对 POST 方法调用的 yaml/json 模式验证标头 + 请求有效负载。这是我试图使用骆驼 REST DSL 来实现的,但它并不简单。
  • 当您将文件保存为 JSON 时,您只是在创建 JSON 格式的 OpenAPI 规范。这仍然不是 JSON 模式。它非常接近,但存在差异。使用这组技术是不可能做到的。 json 格式的 OpenAPI 不是 json 模式,它们完全不同。它可能有点作用,因为它们很相似,但是 json 模式没有诸如 get 和 post 之类的操作,这都是关于模式的。

标签: rest validation apache-camel openapi spring-camel


【解决方案1】:

去年我在采用 OpenAPI 时遇到了这个问题,得出的结论是工作量太大。我无法使用 OpenAPI 从 JSON 验证器获得完整验证,因为 OpenAPI 声明架构定义的方式与完整的 JSON 架构定义之间存在一些差异。

查看 JSON 验证组件的文档,您会发现:

JSON Schema Validator 组件使用 NetworkNT JSON Schema 库 (https://github.com/networknt/json-schema-validator) 对 JSON Schemas v4 草稿执行消息正文的 bean 验证。这是一个完全独立的 JSON Schema,如果您阅读 github 页面,您会发现它。

OpenAPI 支持

OpenAPI 3.0 规范使用 JSON 模式来验证请求/响应,但存在一些差异。使用配置文件,您可以启用该库以使用 OpenAPI 3.0 验证。

OpenAPI 架构似乎是真正 JSON 架构的子集。

在我给你看一个更详细的例子之前。查看此处骆驼文档中给出的示例:https://camel.apache.org/components/latest/json-validator-component.html。将该 json 模式文件与 openAPI 模式定义进行比较,您会发现它们并不相同。

这里的一个有用工具是https://jsonschema.net,您可以在此处粘贴您的 json 示例并推断架构。我在下面的示例中使用了这个工具和 OpenAPI Pet Store 示例,

OpenAPI Petstore 宠物对象示例:

{
  "id": 0,
  "category": {
    "id": 0,
    "name": "string"
  },
  "name": "doggie",
  "photoUrls": [
    "string"
  ],
  "tags": [
    {
      "id": 0,
      "name": "string"
    }
  ],
  "status": "available"
}

保存在 JSON 中的 openAPI 规范产生了这个定义:

  "Pet": {
      "type": "object",
      "required": [
        "name",
        "photoUrls"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "category": {
          "$ref": "#/definitions/Category"
        },
        "name": {
          "type": "string",
          "example": "doggie"
        },
        "photoUrls": {
          "type": "array",
          "xml": {
            "name": "photoUrl",
            "wrapped": true
          },
          "items": {
            "type": "string"
          }
        },
        "tags": {
          "type": "array",
          "xml": {
            "name": "tag",
            "wrapped": true
          },
          "items": {
            "$ref": "#/definitions/Tag"
          }
        },
        "status": {
          "type": "string",
          "description": "pet status in the store",
          "enum": [
            "available",
            "pending",
            "sold"
          ]
        }
      },
      "xml": {
        "name": "Pet"
      }
    }

当我将其转换为正确的 JSON 架构语法时,JSON 架构如下所示:

{
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [
    "id",
    "category",
    "name",
    "photoUrls",
    "tags",
    "status"
  ],
  "properties": {
    "id": {
      "$id": "#/properties/id",
      "type": "integer",
      "title": "The Id Schema",
      "default": 0,
      "examples": [
        0
      ]
    },
    "category": {
      "$id": "#/properties/category",
      "type": "object",
      "title": "The Category Schema",
      "required": [
        "id",
        "name"
      ],
      "properties": {
        "id": {
          "$id": "#/properties/category/properties/id",
          "type": "integer",
          "title": "The Id Schema",
          "default": 0,
          "examples": [
            0
          ]
        },
        "name": {
          "$id": "#/properties/category/properties/name",
          "type": "string",
          "title": "The Name Schema",
          "default": "",
          "examples": [
            "string"
          ],
          "pattern": "^(.*)$"
        }
      }
    },
    "name": {
      "$id": "#/properties/name",
      "type": "string",
      "title": "The Name Schema",
      "default": "",
      "examples": [
        "doggie"
      ],
      "pattern": "^(.*)$"
    },
    "photoUrls": {
      "$id": "#/properties/photoUrls",
      "type": "array",
      "title": "The Photourls Schema",
      "items": {
        "$id": "#/properties/photoUrls/items",
        "type": "string",
        "title": "The Items Schema",
        "default": "",
        "examples": [
          "string"
        ],
        "pattern": "^(.*)$"
      }
    },
    "tags": {
      "$id": "#/properties/tags",
      "type": "array",
      "title": "The Tags Schema",
      "items": {
        "$id": "#/properties/tags/items",
        "type": "object",
        "title": "The Items Schema",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "$id": "#/properties/tags/items/properties/id",
            "type": "integer",
            "title": "The Id Schema",
            "default": 0,
            "examples": [
              0
            ]
          },
          "name": {
            "$id": "#/properties/tags/items/properties/name",
            "type": "string",
            "title": "The Name Schema",
            "default": "",
            "examples": [
              "string"
            ],
            "pattern": "^(.*)$"
          }
        }
      }
    },
    "status": {
      "$id": "#/properties/status",
      "type": "string",
      "title": "The Status Schema",
      "default": "",
      "examples": [
        "available"
      ],
      "pattern": "^(.*)$"
    }
  }
}

OpenAPI 的 Schema 定义和 JSON Schema 定义有一些不同。

【讨论】:

    【解决方案2】:

    failOnNullBody (producer) - 如果没有 body 是否失败。

    默认为真

    尝试在通话中设置选项:

    .to("json-validator:openapi.json?failOnNullBody=false")
    

    【讨论】:

    • 感谢 Mark 的回复,我尝试添加 .to("json-validator:openapi.json?failOnNullBody=false") 但问题仍然存在,即仍然抛出消息 org.apache.camel.component.jsonvalidator.NoJsonBodyValidationException: No JSON body could be在输入消息中找到。交换[ID-RVCRB439-1570421215006-0-1]
    • 还有另一个可能与您相关的查询参数:headerName (producer) - 验证标头而不是消息正文。
    • @MarkMcKeever JSON 模式仅验证 JSON 对象。请参阅我对他的问题的评论,但我怀疑他正在使用 OpenAPI 来尝试验证请求。 JSON Schema 与 OpenAPI 非常不同。
    • @MarkMcKeever 谢谢,它现在对我有用,即我可以使用 .to("json-validator:openapi.json?headerName=header1") 跳过请求有效负载验证
    • @Nicolas - 我相信您使用如下语法: ?name=value&name=value 所以对于您的示例 .to("json-validator:openapi.json?headerName=header1&headerName=header2&headerName=header3"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多