Reputation: 8509
How should I set the status code to 401?
public class Response<T> {
private Status status;
private T payload;
private Object errors;
private Object metadata;
public static <T> Response<T> unauthorized() {
Response<T> response = new Response<>();
response.setStatus(Status.UNAUTHORIZED);
return response;
}
controller:
public Response fail(@RequestBody AuthRefreshRequest authRefreshRequest) throws Exception {
return Response.unauthorized();
}
but return status is always 200
Upvotes: 0
Views: 2330
Reputation: 42541
By default if you return the object from the @RestController
spring converts it to JSON/XML and adds http status code 200 to the response. This makes sense because the flow didn't end "abnormally" in a sense that the exception has not been thrown.
Conceptually there are two ways to alter this behavior:
More fine-grained control over the response: despite the fact the returned object indeed has some data, return some non-200 status code.
Throw the exception and take advantage of spring exception handling mvc integration.
The first way can be easily done by a simple refactor:
Remove the status from the Response
object and in general tend to remove this level of abstraction: return objects from the business domain from the controller. Spring already has such an abstraction: it's called org.springframework.http.ResponseEntity
:
Assuming your have a "Payload" object:
public ResponseEntity<Payload> fail(...) {
Payload payload = ...
return new ResponseEntity(payload, HttpStatus.UNAUTHORIZED);
}
The second method (exceptions based) should be used when you execute the code and something goes wrong, so that the server can't really execute the request and from the "business logic point of view" it throws the exception.
In this case you could throw the exception that would include some message, applicative error code, status code or whatever and put a Controller Advice that will intercept that exception after it "leaves" the controller (in term of stack trace) - its a hook that allows to "customize" the response: put status code, headers, build response body, whatever. This "controller advice" is one of the ways to process flows that end with exceptions in spring mvc, but there many others, all in all, exception handling is a broad topic in spring mvc, so if you need this, consider reading this tutorial for example (there are many others as well).
Upvotes: 1
Reputation: 1275
You can achieve this by adding a response interceptor ResponseBodyAdvice, in which set the return status to the status
code in response object:
@ControllerAdvice
public class ResponseIntercepter implements ResponseBodyAdvice<Response> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public Response beforeBodyWrite(Response body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
// here set the return status (need to convert your own Status to org.springframework.http.HttpStatus)
serverHttpResponse.setStatusCode(body.getStatus());
return body;
}
}
Upvotes: 0