dcb
dcb

Reputation: 2302

How to Construct a POST Request Which Expects No Body

I've an HTTP client sending many POST requests to a server. The server responds to all requests with 201 Created and a response body. For my purposes, the response header is enough, as I'm only interested in the Location header. I'd like to avoid that the server produces a response body in order to significantly decrease network traffic.

According to 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 [...]

..., thus, I assume, the server COULD also respond e.g. with 204 No Content, omiting the body.

Therefore my question: Is it possible to construct a POST request which makes the server respond with 204 No Content or to omit the response body in another way?

Update 1: The server side is a Spring Data REST project and I'm free to configure it. I know that I could set RepositoryRestConfiguration#setReturnBodyOnCreate to false, but that would be overdone as it affects all incoming requests. Therefore, I'd prefer to make the decision on the client side.

Upvotes: 6

Views: 1627

Answers (4)

dcb
dcb

Reputation: 2302

Based on Evert's and Bertrand's answers plus a bit of googling, I finally implemented the following interceptor in the Spring Data REST server:

@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;
            }
        });
    }

}

It produces the following communication, which is good enough for my purposes:

> 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

I would like to share the bounty evenly, but this is not possible. It goes to Bertrand, as he came with an answer which guided me to the very implementation. Thanks for your help.

Upvotes: 0

Ruchira Randana
Ruchira Randana

Reputation: 4179

Can you try changing your client such that you

  • a) Query the server with HTTP HEAD requests instead of POST requests
  • b) Analyze the response headers. There is no response body for HEAD requests as the purpose of HEAD requests is very similar to your requirement
  • c) Perform the necessary POST requests only when required

I understand that you may have difficulties at the client end to apply these changes. But, in the longer run, I believe this would be worth it.

Upvotes: 0

Bertrand
Bertrand

Reputation: 1976

There is no way to do it client side only as it is not natively implemented in Spring REST server.

Anyway, any client demand can be transformed as an extra custom header or a query parameter in the request.

A way could be to 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 to figure it out.

Upvotes: 1

Evert
Evert

Reputation: 99851

There's no real lever you can pull from the client side to control if the server will respond with a body or not, unless the service you work with has a specific feature that allows this.

A header that a server might use is Prefer: return=minimal but if the service doesn't explicitly document support for this, chances are low that this will work.

Really the only think you can do one the client is to:

  1. Kill the TCP connection as soon as you got the response headers
  2. Kill the HTTP/2 stream when you recieved the headers.

This is a pretty 'drastic' thing but clients do use this mechanism for some cases and it does work. However, if the POST response body was somewhat small there's a chance that it's not really making a ton of difference because the response might already have been sent.

Upvotes: 4

Related Questions