How to get raw JSON message from request and HTTP status code from response - spring-boot

I am developing a Spring Boot application. We have a requirement to store raw JSON request and HTTP response code to store in database as part of processing the request.
We are able to intercept request in a class that extends RequestBodyAdviceAdapter. This class has implemented afterBodyRead method to get body of the request. Unfortunately there is no way to get the raw JSON request in this method.
Similarly we have another class that has implemented ResponseBodyAdvice to intercept response. In beforeBodyWrite method, response status code is not available.

You can write a simple servlet filter:
#Component
public class JsonFilter implements Filter {
#Override
public void doFilter
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
// Log JSON request
chain.doFilter(request, response);
// Log JSON response and HTTP Status code
}
// other methods
}
Read more about filters and Spring Boot here: https://www.baeldung.com/spring-boot-add-filter

Related

Add response header in HandlerInterceptorAdapter

I am adding a header to the response inside HandlerInterceptorAdapter.
However it seems that the response header cannot be modified in the postHandle method.
public class CredentialInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
return true;
}
#Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) {
String value = "...";
response.addHeader("header_name",value ); // doesn't work
}
}
How to add a header to the response ?
Popular solution is to use OncePerRequestFilter ( Set response header in Spring Boot ). Isn't there any other way ?
The problem with adding headers in the postHandle method is that the response may already be (partially) send. When that is the case you cannot add/change headers anymore. You need to set the headers before anything is sent to the client.
This you can do in the preHandle method or more generic a servlet filter before you call filterchain.doFilter. Doing it after the aforementioned call you might get the same issue that a response has already (partially) been sent.

Springbook 2.0 interceptor forward to controller

I am building a small application in which I am trying to manage user login session.
My question is, is it possible to forward the http request from HandlerInterceptor.preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) method to controller
Something like this..
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.getRequestDispatcher("someController").forward(request, response);
return true;
}

Passin Parameters from Filter to Business Service in SpringBoot

I have 3 REST services which are reading some common header parameters on the request. I need to use that parameters on my business services. instead of reading that common header parameters on each web service controller (#RestController), Is it possible to read that headers on request filter and make it available on the business services ? If yes, are there any examples to do this ?
You can get request object
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
and access the headers in business services using request object.
Like #Nitin suggest you can pass the request object from your controllers to your services and read the header there. There is no problem with that.
If you still want to read it in a filter and have it available in any #Service you can do as follows:
#Component
#Order(1)
public class HeaderReaderFilter implements Filter {
#Autowired
private HeaderDataHolder headerDataHolder;
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
headerDataHolder.setHeaderContent(httpRequest.getHeader("header_field"));
chain.doFilter(request, response);
}
}
#RequestScope
#Component
public class HeaderDataHolder {
private String headerContent;
public String getHeaderContent() {
return headerContent;
}
public void setHeaderContent(String headerContent) {
this.headerContent = headerContent;
}
}
And then have the HeaderDataHolder #Autowired in your service classes. Notice the necessary #RequestScope so you have a different bean for each request.

Spring-boot Zuul: Passing user ID between microservices

I have a Zuul Gateway proxy, where I check the authorization of token received from the user. Now, when this is request is passed on to other microservices to get the user-specific data, the user information needs to be passed from the gateway to the microservice.
Right now, I've added the user ID in the request header and I'm getting it at respective microservice's controller using API header annotation.
Is this the right way to pass the user information. Is there any other better way?
In case if anyone still facing this issue,
In Zuul Proxy add the header to RequestContext as below:
userId = jwtTokenUtil.getUsernameFromToken(jwtToken);
RequestContext ctx = RequestContext.getCurrentContext();
ctx.addZuulRequestHeader("userId", userId);
And then in the respective microservices write a custom filter and extract the value as below
#Component
public class MyFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String userId = request.getHeaders("userId").nextElement();
logger.info("userId: "+userId);
filterChain.doFilter(request, response);
}
}

JSF 2 AJAX Response Cache

When I use JSF 2 Ajax, how do I control whether the response is cacheable. If that's possible, how do I control the expry date of the AJAX response? Thanks! -- Charlie
As is typical for JSF applications, the caching headers are set via a Filter, which is part of the Servlet layer. For this layer there is no automatic difference between a normal request and an AJAX request.
JSF however marks requests as AJAX requests by means of the javax.faces.partial.ajax request parameter. (see JSF spec section 14.2.4)
If you thus want to specifically control the response headers for all JSF AJAX requests, you would do something like:
#WebFilter(filterName="httpHeaders", urlPatterns="/*")
public class HTTPHeaders extends Filter {
#Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request.getParameter("javax.faces.partial.ajax") != null) {
response.setHeader("Cache-Control", "...");
response.setDateHeader ("Expires", "...");
response.setHeader("Pragma", "...");
}
chain.doFilter(request, response);
}
}

Resources