如何构造一个 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
,但如果服务没有明确记录对此的支持,那么这将起作用的可能性很小。
真正认为您可以为客户做的唯一事情是:
- 收到响应后立即终止 TCP 连接 headers
- 收到 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,因为他带来了一个答案,这个答案指导我进行了实施。感谢您的帮助。
我有一个 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
,但如果服务没有明确记录对此的支持,那么这将起作用的可能性很小。
真正认为您可以为客户做的唯一事情是:
- 收到响应后立即终止 TCP 连接 headers
- 收到 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,因为他带来了一个答案,这个答案指导我进行了实施。感谢您的帮助。