gigi2
gigi2

Reputation: 2194

add location header to Spring MVC's POST response?

My Spring Boot 1.4 application has this POST HTTP Method to create a resource. As a requirement, it should spit a location header specifying the URL of the newly created resource: RFC 9110 HTTP Semantics - Method Definitions. I am just wondering if there is any good way to do it than manually constructing the URL and adding it to the response.

Any helps/clues are deeply appreciated

Upvotes: 22

Views: 26833

Answers (4)

anand krish
anand krish

Reputation: 4415

 @Autowired 
 private UserService service;

 @PostMapping("/users")
 public ResponseEntity<Object> createUser(@RequestBody User user)
  {
    User myUser = service.save(user);
    URI location = ServletUriComponentsBuilder
                .fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(myUser.getId())
                .toUri();

    ResponseEntity.created(location).build()
  }

Upvotes: 3

cela
cela

Reputation: 2510

This answer pointed me in the right direction, but my create entity endpoint path was slightly different from the path where the saved entity was stored.

I was able to use fromCurrentRequest() and replacePath("new path here") like so:

URI uri = ServletUriComponentsBuilder.fromCurrentRequest()
        .replacePath("/customer/{id}/fat")
        .buildAndExpand(savedCustomer.getCustomerId())
        .toUri();

return ResponseEntity.created(uri).build();

Upvotes: 1

Trevor Gowing
Trevor Gowing

Reputation: 2296

This exact scenario is demonstrated in the Building REST Services with Spring Guide.

Once you have persisted your new entity, in your controller you can use the below:

URI location = ServletUriComponentsBuilder
                    .fromCurrentRequest()
                    .path("/{id}")
                    .buildAndExpand(newEntity.getId())
                    .toUri();

You can then add this to your response using ResponseEntity as below:

ResponseEntity.created(location).build()

or

ResponseEntity.status(CREATED).header(HttpHeaders.LOCATION, location).build()

The latter expects a string so you can use toUriString() on the uri builder instead of toUri().

Upvotes: 54

Valdemar
Valdemar

Reputation: 2600

Another way is to use UriComponentsBuilder. You can inject it right into a controller method:

@PostMapping(consumes = { MediaType.APPLICATION_JSON_UTF8_VALUE })
public ResponseEntity<Void> addCustomer(
          UriComponentsBuilder uriComponentsBuilder, 
          @RequestBody CustomerRequest customerRequest ){

        final long customerId = customerService.addCustomer(customerRequest)

        UriComponents uriComponents =
                uriComponentsBuilder.path("/{id}").buildAndExpand(customerId);

        return ResponseEntity.created(uriComponents.toUri()).build();
}

Take note that the following will not compute the current request path. You will need to add it manually (or I might be missing something).

ex:

UriComponents uriComponents =
       uriComponentsBuilder.path("CURRENT_REQUEST_PATH/{id}")
       .buildAndExpand(customerId);

Upvotes: 5

Related Questions