Merge pull request #13230 from hmdrzsharifi/BAEL-2862

Bael-2862: Update Spring Http Logging Article
This commit is contained in:
davidmartinezbarua 2023-01-31 17:11:50 -03:00 committed by GitHub
commit 09d1eb4e8c
12 changed files with 125 additions and 172 deletions

View File

@ -1,19 +1,18 @@
package com.baeldung.web.log.app;
import javax.servlet.ServletRegistration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import com.baeldung.web.log.config.CustomeRequestLoggingFilter;
@EnableAutoConfiguration
@ComponentScan("com.baeldung.web.log")
@PropertySource("application-log.properties")
@SpringBootApplication
@SpringBootApplication(exclude = {
SecurityAutoConfiguration.class,
ManagementWebSecurityAutoConfiguration.class
})
public class Application {
public static void main(final String[] args) {

View File

@ -0,0 +1,30 @@
package com.baeldung.web.log.app;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class CachedHttpServletRequest extends HttpServletRequestWrapper {
private byte[] cachedPayload;
public CachedHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
InputStream requestInputStream = request.getInputStream();
this.cachedPayload = StreamUtils.copyToByteArray(requestInputStream);
}
@Override
public ServletInputStream getInputStream() {
return new CachedServletInputStream(this.cachedPayload);
}
@Override
public BufferedReader getReader() {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedPayload);
return new BufferedReader(new InputStreamReader(byteArrayInputStream));
}
}

View File

@ -0,0 +1,45 @@
package com.baeldung.web.log.app;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class CachedServletInputStream extends ServletInputStream {
private final static Logger LOGGER = LoggerFactory.getLogger(CachedServletInputStream.class);
private InputStream cachedInputStream;
public CachedServletInputStream(byte[] cachedBody) {
this.cachedInputStream = new ByteArrayInputStream(cachedBody);
}
@Override
public boolean isFinished() {
try {
return cachedInputStream.available() == 0;
} catch (IOException exp) {
LOGGER.error(exp.getMessage());
}
return false;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
throw new UnsupportedOperationException();
}
@Override
public int read() throws IOException {
return cachedInputStream.read();
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.web.log.app;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@Component
@WebFilter(filterName = "RequestCachingFilter", urlPatterns = "/*")
public class RequestCachingFilter extends OncePerRequestFilter {
private final static Logger LOGGER = LoggerFactory.getLogger(RequestCachingFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CachedHttpServletRequest cachedHttpServletRequest = new CachedHttpServletRequest(request);
LOGGER.info("REQUEST DATA: " + IOUtils.toString(cachedHttpServletRequest.getInputStream(), StandardCharsets.UTF_8));
filterChain.doFilter(cachedHttpServletRequest, response);
}
}

View File

@ -1,44 +0,0 @@
package com.baeldung.web.log.app;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import com.baeldung.web.log.util.RequestLoggingUtil;
@Component
public class TaxiFareRequestInterceptor extends HandlerInterceptorAdapter {
private final static Logger LOGGER = LoggerFactory.getLogger(TaxiFareRequestInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String postData;
HttpServletRequest requestCacheWrapperObject = null;
try {
// Uncomment to produce the stream closed issue
// postData = RequestLoggingUtil.getStringFromInputStream(request.getInputStream());
// To overcome request stream closed issue
requestCacheWrapperObject = new ContentCachingRequestWrapper(request);
requestCacheWrapperObject.getParameterMap();
} catch (Exception exception) {
exception.printStackTrace();
} finally {
postData = RequestLoggingUtil.readPayload(requestCacheWrapperObject);
LOGGER.info("REQUEST DATA: " + postData);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LOGGER.info("RESPONSE: " + response.getStatus());
}
}

View File

@ -1,27 +0,0 @@
package com.baeldung.web.log.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.WebApplicationInitializer;
public class CustomWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.baeldung.web.log");
container.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
container.addFilter("customRequestLoggingFilter", CustomeRequestLoggingFilter.class).addMappingForServletNames(null, false, "dispatcher");
}
}

View File

@ -1,12 +0,0 @@
package com.baeldung.web.log.config;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
public class CustomeRequestLoggingFilter extends CommonsRequestLoggingFilter {
public CustomeRequestLoggingFilter() {
super.setIncludeQueryString(true);
super.setIncludePayload(true);
super.setMaxPayloadLength(10000);
}
}

View File

@ -14,7 +14,7 @@ public class RequestLoggingFilterConfig {
filter.setIncludePayload(true);
filter.setMaxPayloadLength(10000);
filter.setIncludeHeaders(false);
filter.setAfterMessagePrefix("REQUEST DATA : ");
filter.setAfterMessagePrefix("REQUEST DATA: ");
return filter;
}
}

View File

@ -1,19 +0,0 @@
package com.baeldung.web.log.config;
import com.baeldung.web.log.app.TaxiFareRequestInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class TaxiFareMVCConfig implements WebMvcConfigurer {
@Autowired
private TaxiFareRequestInterceptor taxiFareRequestInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(taxiFareRequestInterceptor).addPathPatterns("/taxifare/*/");
}
}

View File

@ -1,38 +0,0 @@
package com.baeldung.web.log.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.WebUtils;
public class RequestLoggingUtil {
public static String getStringFromInputStream(InputStream is) {
StringWriter writer = new StringWriter();
String encoding = "UTF-8";
try {
IOUtils.copy(is, writer, encoding);
} catch (IOException e) {
e.printStackTrace();
}
return writer.toString();
}
public static String readPayload(final HttpServletRequest request) throws IOException {
String payloadData = null;
ContentCachingRequestWrapper contentCachingRequestWrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
if (null != contentCachingRequestWrapper) {
byte[] buf = contentCachingRequestWrapper.getContentAsByteArray();
if (buf.length > 0) {
payloadData = new String(buf, 0, buf.length, contentCachingRequestWrapper.getCharacterEncoding());
}
}
return payloadData;
}
}

View File

@ -7,6 +7,10 @@
</encoder>
</appender>
<logger name="org.springframework.web.filter.CommonsRequestLoggingFilter">
<level value="DEBUG" />
</logger>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>

View File

@ -1,23 +1,19 @@
package com.baeldung.web.controller;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import com.baeldung.web.log.app.Application;
import com.baeldung.web.log.data.TaxiRide;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import com.baeldung.web.log.app.Application;
import com.baeldung.web.log.data.TaxiRide;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { Application.class, TaxiFareControllerIntegrationTest.SecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@SpringBootTest(classes = { Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TaxiFareControllerIntegrationTest {
@LocalServerPort
@ -25,8 +21,6 @@ public class TaxiFareControllerIntegrationTest {
@Test
public void givenRequest_whenFetchTaxiFareRateCard_thanOK() {
System.out.println(port);
String URL = "http://localhost:" + port + "/spring-rest";
TestRestTemplate testRestTemplate = new TestRestTemplate();
TaxiRide taxiRide = new TaxiRide(true, 10l);
@ -37,16 +31,4 @@ public class TaxiFareControllerIntegrationTest {
assertThat(fare, equalTo("200"));
}
@Configuration
static class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("security being set");
http
.authorizeRequests()
.anyRequest().permitAll()
.and()
.csrf().disable();
}
}
}