【问题标题】:Sending an Empty String as RequestBody not hitting the Rest endpoint发送空字符串作为 RequestBody 未命中 Rest 端点
【发布时间】:2018-10-12 03:47:27
【问题描述】:

我正在尝试为端点编写 unitTest。

此端点应采用如下 json 对象

@PostMapping(value = "/test")
public String endPoint(@RequestBody String obj) {

        try {
          JSONObject inputJsonObject = new JSONObject(individualJson);
        } catch (JSONException | IOException e) {
                    throw new MyException("JSONObject not valid");
        }
 ......
 }

在我的单元测试中,我试图发送一个空字符串,并且我希望有一个 JSONException

mvc.perform(post(url)
                .contentType(MediaType.APPLICATION_JSON)
                .content(""))
                .andReturn().getResponse();

但是,我的帖子没有到达我的终点……就像它无法将空字符串评估为字符串一样:“”但是没有到达终点 “”(带空格)正在到达终点……

这是调用返回的异常:

org.springframework.http.converter.HttpMessageNotReadableException: 缺少所需的请求正文:公共 com.ba.mypackage.MyController.endPoint(java.lang.String)

如何通过传递空字符串 "" 来访问端点?

【问题讨论】:

  • 您在服务器日志上没有看到任何异常?
  • 是的,我更新了我的帖子以放置异常
  • @tima 为什么空字符串不是有意义的对象?
  • @tima 端点不需要有效的 JSON,而是一个字符串 - “@RequestBody String obj”。对于无效的 JSON,将抛出 MyException
  • @eis 我错过了...

标签: java spring-boot request jackson


【解决方案1】:

你不能,因为在这种情况下发送一个空字符串作为正文与不发送正文是一样的,@RequestBody 注释不允许不发送正文,因为它的 required 属性的默认值是true

将空字符串作为正文发送与不发送正文相同,因为在 HTTP 中,POST 请求具有由 CRLF 分隔的标头部分和正文部分,并且在有正文和没有正文时都需要分隔 CRLF . HTTP 规范中是这样定义的,详见https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html

5 请求

从客户端到服务器的请求消息在该消息的第一行中包括要应用于资源的方法、资源的标识符以及正在使用的协议版本。

    Request       = Request-Line              ; Section 5.1
                    *(( general-header        ; Section 4.5
                     | request-header         ; Section 5.3
                     | entity-header ) CRLF)  ; Section 7.1
                    CRLF
                    [ message-body ]          ; Section 4.3

您提供的标题部分和正文是您希望拥有的空字符串。但是,无论如何,您都需要使用 CRLF,因此请求看起来像这样:

POST /url HTTP/1.1
Content-Type: application/json; charset=UTF-8
Accept: application/json, application/javascript, text/javascript
Content-Length: 0
Host: localhost:8888
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_112)
Accept-Encoding: gzip,deflate
 

或者,将 [CRLF] 放在该字符所在的位置,

POST /url HTTP/1.1[CRLF]
Content-Type: application/json; charset=UTF-8[CRLF]
Accept: application/json, application/javascript, text/javascript[CRLF]
Content-Length: 0[CRLF]
Host: localhost:8888[CRLF]
Connection: Keep-Alive[CRLF]
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_112)[CRLF]
Accept-Encoding: gzip,deflate[CRLF]
[CRLF]

由于内容长度为零并且 CRLF 分隔符必须始终存在,您如何区分作为正文发送的空字符串和根本不发送正文?问题是你做不到,在这种情况下它是同一件事,所以你问的事情是做不到的。

【讨论】:

    【解决方案2】:

    因为空字符串不是有效的字符串,并且被视为类似于 Null。

    但是,如果您只是想点击控制器并且对控制器内部的空字符串值不感兴趣,只需将参数标记为可选。

    public String endPoint(@RequestBody(required = false) String obj) {
    

    【讨论】:

    • 谢谢!但是,这使我的端点接收 null .. 我希望它接收空字符串“”
    • 空字符串肯定是有效字符串。
    猜你喜欢
    • 2022-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 2016-03-09
    相关资源
    最近更新 更多