如何构造一个 POST 请求不期望 Body

How to Construct a POST Request Which Expects No Body

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

根据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,省略 body。

因此我的问题是:是否可以构造一个 POST 请求,使服务器以 [​​=16=] 响应或以另一种方式省略响应 body?

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

您无法从客户端拉出真正的杠杆来控制服务器是否会响应 body,除非您使用的服务具有允许这样做的特定功能。

服务器可能使用的 header 是 Prefer: return=minimal,但如果服务没有明确记录对此的支持,那么这将起作用的可能性很小。

真正认为您可以为客户做的唯一事情是:

  1. 收到响应后立即终止 TCP 连接 headers
  2. 收到 header 后关闭 HTTP/2 流。

这是一件很漂亮的 'drastic' 事情,但客户确实在某些情况下使用了这种机制并且它确实有效。但是,如果 POST 响应 body 有点小,那么它可能不会真正产生很大的不同,因为响应可能已经发送。

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

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

一种方法是 override default response handlers and detect custom header (implements Prefer: return=minimal as suggested before for instance) and/or query param presence to trigger an empty response with a 204 status. This post may help you 弄明白。

你能试着改变你的客户,这样你

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

我知道您可能在客户端应用这些更改时遇到困难。但是,在更长的时间里 运行,我相信这是值得的。

基于 Evert 和 Bertrand 的回答以及一些谷歌搜索,我最终在 Spring 数据 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,因为他带来了一个答案,这个答案指导我进行了实施。感谢您的帮助。