如何构建不包含任何正文的POST请求

时间:2018-11-20 10:50:42

标签: http spring-boot post spring-data-rest

我有一个HTTP客户端,它向服务器发送许多POST请求。服务器使用201 Created和响应主体来响应所有请求。就我而言,响应标头就足够了,因为我只对Location标头感兴趣。我想避免服务器生成响应主体以显着减少网络流量。

根据RFC 7231,...

  [...] if one or more resources has been created on the origin server as a
  result of successfully processing a POST request, the origin server
  SHOULD send a 201 (Created) response containing a Location header [...]

...,因此,我认为服务器也可能会响应例如204 No Content,省略了身体。

因此,我的问题是:是否可以构造一个POST请求,使服务器以204 No Content进行响应,或者以其他方式省略响应主体?

更新1:服务器端是Spring Data REST项目,我可以自由配置它。我知道我可以将RepositoryRestConfiguration#setReturnBodyOnCreate设置为false,但这会过分使用,因为它会影响所有传入的请求。因此,我宁愿在客户端做出决定。

4 个答案:

答案 0 :(得分:4)

除非您使用的服务具有允许此功能的特定功能,否则您无法从客户端拉出任何真正的杠杆来控制服务器是否响应正文。

服务器可能使用的标头为Prefer: return=minimal,但是如果服务未明确记录对此的支持,则该标头工作的可能性很小。

您真的唯一可以做一个客户的想法是:

  1. 获得响应标头后立即终止TCP连接
  2. 在收到标头时杀死HTTP / 2流。

这是一件非常“棘手”的事情,但是客户在某些情况下确实使用了这种机制,并且确实起作用。但是,如果POST响应主体较小,则可能真的没有造成太大的改变,因为响应可能已经发送了。

答案 1 :(得分:1)

无法仅在客户端执行此操作,因为它不是在Spring REST服务器中本地实现的。

无论如何,任何客户需求都可以转换为请求中的额外自定义标头或查询参数。

一种方法可以是override default response handlers和检测自定义标头(例如,如之前建议的实现Prefer: return=minimal)和/或查询参数存在以触发状态为204的空响应。 This post may help you来解决。

答案 2 :(得分:0)

您可以尝试更改客户这样吗

  • a)使用HTTP HEAD请求而不是POST请求查询服务器
  • b)分析响应头。 HEAD请求没有响应主体,因为HEAD请求的目的与您的要求非常相似
  • c)仅在需要时执行必要的POST请求

我了解您可能无法在客户端应用这些更改。但是,从长远来看,我相信这是值得的。

答案 3 :(得分:0)

基于Evert和Bertrand的答案以及一些谷歌搜索,我终于在Spring Data REST服务器中实现了以下拦截器:

@Configuration
class RepositoryConfiguration {

    @Bean
    public MappedInterceptor preferReturnMinimalMappedInterceptor() {
        return new MappedInterceptor(new String[]{"/**"}, new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
                if ("return=minimal".equals(request.getHeader("prefer"))) {
                    response.setContentLength(0);
                    response.addHeader("Preference-Applied", "return=minimal"");
                }
                return true;
            }
        });
    }

}

它会产生以下交流信息,对于我的目的而言足够好了

> POST /versions HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.59.0
> Accept: */*
> Content-Type: application/json
> Prefer: return=minimal
> Content-Length: 123
>
> [123 bytes data]

...

< HTTP/1.1 201
< Preference-Applied: return=minimal
< ETag: "0"
< Last-Modified: Fri, 30 Nov 2018 12:37:57 GMT
< Location: http://localhost:8080/versions/1
< Content-Type: application/hal+json;charset=UTF-8
< Content-Length: 0
< Date: Fri, 30 Nov 2018 12:37:57 GMT

我想平均分享赏金,但这是不可能的。伯特兰(Bertrand)来了,他给了我一个答案,该答案指导了我的真正实现。感谢您的帮助。