Monday, 3 May 2021

Request Body only once

package com.example.demo.config; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.filters.RequestFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.apache.log4j.Logger; @Component public class CustomFilter implements Filter{ private static final Logger LOGGER = Logger.getLogger(RequestFilter.class); @Autowired LogApiInterceptor logApiInterceptor; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { LOGGER.info("doFilter, parsing request"); // LOG REQUEST ResettableStreamHttpServletRequest wrappedRequest = null; try { wrappedRequest = new ResettableStreamHttpServletRequest((HttpServletRequest) request); logApiInterceptor.writeRequestPayloadAudit(wrappedRequest); } catch (Exception e) { LOGGER.error("Fail to wrap request and response",e); } chain.doFilter(wrappedRequest, response); } } ----------------------------------------------------------------------------------------------------------------- package com.example.demo.config; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Enumeration; import java.lang.StringBuffer; import java.io.Writer; import java.io.BufferedWriter; import java.io.OutputStreamWriter; import java.io.FileOutputStream; import java.util.Collections; import java.nio.charset.StandardCharsets; import java.io.IOException; import org.springframework.stereotype.Component; import org.apache.log4j.Logger; import java.util.UUID; @Component public class LogApiInterceptor extends HandlerInterceptorAdapter { private static final Logger LOGGER = Logger.getLogger(LogApiInterceptor.class); @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } public String getRawHeaders(HttpServletRequest request) { StringBuffer rawHeaders = new StringBuffer(); Enumeration headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String key = (String) headerNames.nextElement(); String value = request.getHeader(key); rawHeaders.append(key).append(":").append(value).append("\n"); } System.out.println("Testing :::::: "+rawHeaders.toString()); return rawHeaders.toString(); } public String getRawHeaders(HttpServletResponse response){ StringBuffer rawHeaders = new StringBuffer(); Enumeration headerNames = Collections.enumeration(response.getHeaderNames()); while (headerNames.hasMoreElements()) { String key = (String) headerNames.nextElement(); String value = response.getHeader(key); rawHeaders.append(key).append(":").append(value).append("\n"); } return rawHeaders.toString(); } private void writePayloadAudit(String payloadFile, String rawHeaders, String requestBody) throws IOException { try (Writer writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(payloadFile), StandardCharsets.UTF_8))) { writer.write(rawHeaders); writer.write("\n"); writer.write(requestBody); } } public void writeRequestPayloadAudit(ResettableStreamHttpServletRequest wrappedRequest) { try { String requestHeaders = getRawHeaders(wrappedRequest); String requestBody = org.apache.commons.io.IOUtils.toString(wrappedRequest.getReader()); LOGGER.info("Request Method: "+wrappedRequest.getMethod()); LOGGER.info("Request Headers:"); LOGGER.info(requestHeaders); LOGGER.info("Request body:"); LOGGER.info(requestBody); } catch (Exception e) { LOGGER.error(e); } } } ----------------------------------------------------------------------------------------------------------------------------- package com.example.demo.config; import javax.servlet.ServletInputStream; import java.io.InputStream; import javax.servlet.ReadListener; import java.io.IOException; public class ResettableServletInputStream extends ServletInputStream { public InputStream inputStream; private ServletInputStream servletInputStream = new ServletInputStream(){ boolean isFinished = false; boolean isReady = true; ReadListener readListener = null; public int read() throws IOException { int i = inputStream.read(); isFinished = i == -1; isReady = !isFinished; return i; } @Override public boolean isFinished() { return isFinished; } @Override public boolean isReady() { return isReady; } @Override public void setReadListener(ReadListener readListener) { this.readListener = readListener; } }; public int available() throws IOException { return inputStream.available(); } public void close() throws IOException { inputStream.close(); } public void mark(int readLimit){ inputStream.mark(readLimit); } public boolean markSupported(){ return inputStream.markSupported(); } public int read(byte[] b, int off, int len) throws IOException { return inputStream.read(b,off,len); } public int readline(byte[] b, int off, int len) throws IOException { if ( len <= 0 ){ return 0; } int count=0,c; while ( (c = read()) != -1 ) { b[off++] = (byte) c; count++; if ( c == '\n' || count == len ) { break; } } return count > 0 ? count : -1; } public void reset() throws IOException { inputStream.reset(); } public long skip(long n) throws IOException { return inputStream.skip(n); } @Override public int read() throws IOException { return inputStream.read(); } @Override public void setReadListener(ReadListener readListener){ servletInputStream.setReadListener(readListener); } public boolean isReady() { return servletInputStream.isReady(); } public boolean isFinished() { return servletInputStream.isFinished(); } } -------------------------------------------------------------------------------------------------------------------- package com.example.demo.config; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.IOException; import java.io.ByteArrayInputStream; import org.apache.commons.io.IOUtils; import java.io.InputStreamReader; import java.io.BufferedReader; import javax.servlet.ServletInputStream; public class ResettableStreamHttpServletRequest extends HttpServletRequestWrapper { private byte[] rawData = {}; private HttpServletRequest request; private ResettableServletInputStream servletStream; public String requestId; public String payloadFilePrefix; public String payloadTarget; ResettableStreamHttpServletRequest(HttpServletRequest request) throws IOException { super(request); this.request = request; this.servletStream = new ResettableServletInputStream(); } void resetInputStream() throws IOException { initRawData(); servletStream.inputStream = new ByteArrayInputStream(rawData); } private void initRawData() throws IOException { if ( rawData.length == 0 ) { byte[] b = IOUtils.toByteArray(this.request.getInputStream()); if ( b != null ) rawData = b; } servletStream.inputStream = new ByteArrayInputStream(rawData); } @Override public ServletInputStream getInputStream() throws IOException { initRawData(); return servletStream; } public BufferedReader getReader() throws IOException { initRawData(); String encoding = getCharacterEncoding(); if ( encoding != null ) { return new BufferedReader(new InputStreamReader(servletStream, encoding)); } else { return new BufferedReader(new InputStreamReader(servletStream)); } } } ------------------------------------------------------------------------------------------------------------- package com.example.demo.config; import javax.servlet.http.HttpServletResponse; public class ResettableStreamHttpServletResponse { public ResettableStreamHttpServletResponse(HttpServletResponse response) { // TODO Auto-generated constructor stub } } ------------------------------------------------------------------------------------------------------------------ package com.example.demo; import java.util.concurrent.atomic.AtomicLong; import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @RestController public class GreetingController { private static final String template = "Hello, %s!"; private final AtomicLong counter = new AtomicLong(); @RequestMapping(value = "/greeting", method = { RequestMethod.GET, RequestMethod.POST }) public Greeting greeting(@RequestBody String latestName, @RequestParam(value = "name", defaultValue = "World") String name) { System.out.println("calling"+latestName); return new Greeting(counter.incrementAndGet(), String.format(template, latestName)); } } -------------------------------------------------------------------------------------------------------------------- package com.example.demo; public class Greeting { private final long id; private final String content; public Greeting(long id, String content) { this.id = id; this.content = content; } public long getId() { return id; } public String getContent() { return content; } } ---------------------------------------------------------------------------------------------------------------------- # Root logger option log4j.rootLogger=INFO, stdout # Direct log messages to stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -----------------------------------------------------------------------------------------------------------------------

No comments:

Post a Comment