Home > Back-end >  Send Restful API JSON response from Spring Boot Filter
Send Restful API JSON response from Spring Boot Filter

Time:07-02

I am using following filter for checking if a specific HTTP Header is present on api request.

@Component
@RequiredArgsConstructor
public class HeaderValidationFilter extends OncePerRequestFilter {
private final ObjectMapper objectMapper;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        
String headerValue = request.getHeader("RANDOM_HEADER");

if(Objects.isNull(headerValue)) {
    ResponseEntity<Object> responseToSend = ResponseGen.create("FAILED", "Missing Authentication Header", new Object())));

    response.setHeader("Content-Type", "application/json");
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    response.getOutputStream().write(responseToSend);
    return;
}

    filterChain.doFilter(request, response);
}

It returns response as JSON but with added object keys like headers,statusCodeetc and the payload I provided is placed inside body. As I have a standard error response defined on the Project, I cannot return the response at it is. (See the following response)

{
"headers": {},
"body": {
    "status": "FAILURE",
    "message": "Missing Authentication Header",
    "data": {}
},
"statusCode": "UNAUTHORIZED",
"statusCodeValue": 401
}

I want the response to be only in this format:

{
    "status": "FAILED",
    "message": "Missing Authentication Header",
    "data": {}
}

I have tried returning using generic exception handler with @ControllerAdvice but it doesn't capture exception from Filters as it is executed before DispatcherServlet

Can someone help me out?

CodePudding user response:

The JSON you see

{
"headers": {...},
"body": {...},
"statusCode": ...,
"statusCodeValue": ...
}

is the serialized ResponseEntity that you write as a response in your filter:

ResponseEntity<Object> responseToSend = ResponseGen.create("FAILED", "Missing Authentication Header", new Object())));

Obviously, if you need a response in another format you'll have to use an object that is serialized to the desired format as a response. E.g.

@Data
@AllArgsConstructor
class StandardError {
    private String status;
    private String message;
    private Object data;
}

....

@Override
protected void doFilterInternal(HttpServletRequest request, 
                                HttpServletResponse response, 
                                FilterChain filterChain) throws ServletException, IOException {
    ...
    if (Objects.isNull(headerValue)) {
        StandardError responseToSend = new StandardError("FAILED", "Missing Authentication Header", new Object());

        response.setHeader("Content-Type", "application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getOutputStream().write(responseToSend);
        return;
}
  • Related