@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request); ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response); try { filterChain.doFilter(requestWrapper, responseWrapper); } finally { String requestBody = new String(requestWrapper.getContentAsByteArray()); log.info("Request body: {}", requestBody); String responseBody = new String(responseWrapper.getContentAsByteArray()); log.info("Response body: {}", responseBody); // Do not forget this line after reading response content or actual response will be empty! responseWrapper.copyBodyToResponse(); } }
private String extractRequestPayload(HttpServletRequest request) { ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class); if (wrapper == null) { return UNKNOWN_PAYLOAD; } if (wrapper.getContentLength() > 0) { try { return request.getReader().lines().collect(Collectors.joining(StringUtils.LF)); } catch (IOException e) { return UNKNOWN_PAYLOAD; } } return EMPTY_PAYLOAD; }
private static String getRequestContent(HttpServletRequest request) { if (request instanceof ContentCachingRequestWrapper) { return new String(((ContentCachingRequestWrapper) request).getContentAsByteArray()); } if (request instanceof HttpServletRequestWrapper && ((HttpServletRequestWrapper) request).getRequest() instanceof ContentCachingRequestWrapper) { return new String(((ContentCachingRequestWrapper) ((HttpServletRequestWrapper) request) .getRequest()).getContentAsByteArray()); } log.warn("Empty request content because of unsupported request class {}", request.getClass()); return ""; }
/** * 从HttpServletRequest中提取请求参数(包括请求体中的参数) * @param request * @param loggingContext * @return * @throws Exception */ protected HttpRequestParameter extractRequestParameter(HttpServletRequest request, LoggingContext loggingContext) throws Exception { HttpRequestParameter parameter = new HttpRequestParameter(); Map<String,String[]> originalParamMap = request.getParameterMap(); Map<String,String> paramMap = new HashMap<String,String>(); if(originalParamMap != null && !originalParamMap.isEmpty()){ for(Map.Entry<String, String[]> entry : originalParamMap.entrySet()){ paramMap.put(entry.getKey(), getStringParameterValue(entry.getValue())); } } parameter.setParameter(paramMap); MediaType contentType = loggingContext.getHttpAccessLog().getRequestContentType(); if(contentType != null){ if(isContentCachingRequest(request)){ String charset = request.getCharacterEncoding(); if(StringUtils.isEmpty(charset)){ charset = StringUtils.defaultIfEmpty(contentType.getCharset().name(), GlobalConstants.SYSTEM_DEFAULT_CHARSET); } ContentCachingRequestWrapper requestToUse = (ContentCachingRequestWrapper) request; byte[] bytes = requestToUse.getContentAsByteArray(); if(bytes != null){ String body = IOUtils.toString(bytes, charset); Object bodyObj = body; if(MediaType.APPLICATION_JSON.getType().equals(contentType.getType())){ //目前只处理JSON类型的数据 if(body.startsWith("[") && body.endsWith("]")){ //JSON Array String -> List<Map<String,Object>> bodyObj = JsonUtils.json2Object(body, new TypeReference<List<Map<String,Object>>>(){}); }else if(body.startsWith("{") && body.endsWith("}")){ //JSON Object String -> Map<String,Object> bodyObj = JsonUtils.json2Object(body, new TypeReference<Map<String,Object>>(){}); } } parameter.setBody(bodyObj); } } } return excludeRequestParameter(parameter, loggingContext); }
protected boolean isContentCachingRequest(ServletRequest request) { if(request instanceof ContentCachingRequestWrapper){ return true; }else if(request instanceof HttpServletRequestWrapper) { HttpServletRequestWrapper requestToUse = (HttpServletRequestWrapper) request; return isContentCachingRequest(requestToUse.getRequest()); } return false; }
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request); ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response); try { filterChain.doFilter(requestWrapper, responseWrapper); } finally { responseWrapper.copyBodyToResponse(); } }
@Test public void doFilterInternal_NoCacheRequestAndResponse_CallWithCacheRequestAndResponse() throws Exception { HttpServletRequest request = new MockHttpServletRequest(); HttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = spy(new MockFilterChain()); FILTER.doFilterInternal(request, response, filterChain); Mockito.verify(filterChain).doFilter(isA(ContentCachingRequestWrapper.class), isA (ContentCachingResponseWrapper.class)); }
@Test public void doFilterInternal_CacheRequestAndNoCacheResponse_CallWithCacheRequestAndResponse() throws Exception { HttpServletRequest cacheRequest = new ContentCachingRequestWrapper(new MockHttpServletRequest()); HttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = spy(new MockFilterChain()); ArgumentCaptor<HttpServletRequest> requestCaptor = ArgumentCaptor.forClass(HttpServletRequest.class); FILTER.doFilterInternal(cacheRequest, response, filterChain); Mockito.verify(filterChain).doFilter(requestCaptor.capture(), isA(ContentCachingResponseWrapper.class)); assertThat(requestCaptor.getValue(), is(cacheRequest)); }
@Test public void doFilterInternal_NoCacheRequestAndCacheResponse_CallWithCacheRequestAndResponse() throws Exception { HttpServletRequest request = new MockHttpServletRequest(); HttpServletResponse cacheResponse = new ContentCachingResponseWrapper(new MockHttpServletResponse()); FilterChain filterChain = spy(new MockFilterChain()); ArgumentCaptor<HttpServletResponse> responseCaptor = ArgumentCaptor.forClass(HttpServletResponse.class); FILTER.doFilterInternal(request, cacheResponse, filterChain); Mockito.verify(filterChain).doFilter(isA(ContentCachingRequestWrapper.class), responseCaptor.capture()); assertThat(responseCaptor.getValue(), is(cacheResponse)); }
@Test public void buildRequestLog_WithNoBody_ReturnStringRequestWithUriAndEmptyBody() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod(HttpMethod.GET.name()); request.setRequestURI("/dummy"); String log = FILTER.buildRequestLog(new ContentCachingRequestWrapper(request)); assertThat(log, is("Server has received a request\n > GET http://localhost/dummy\n[empty]")); }
@Test public void buildRequestLog_WithCorrectBody_ReturnStringRequestWithUriAndBody() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod(HttpMethod.GET.name()); request.setRequestURI("/dummy"); request.setContent("test".getBytes()); String log = FILTER.buildRequestLog(new ContentCachingRequestWrapper(request)); assertThat(log, is("Server has received a request\n > GET http://localhost/dummy\n > Content-Length: 4\ntest")); }
@Test public void buildRequestLog_WithUnreadableBody_ReturnStringRequestWithUriAndUnknownBody() throws IOException { MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod(HttpMethod.GET.name()); request.setRequestURI("/dummy"); request.setContent(nextBytes(4)); ContentCachingRequestWrapper requestWrapper = spy(new ContentCachingRequestWrapper(request)); when(requestWrapper.getReader()).thenThrow(new UnsupportedEncodingException()); String log = FILTER.buildRequestLog(requestWrapper); assertThat(log, is("Server has received a request\n > GET http://localhost/dummy\n > Content-Length: 4\n[unknown]")); }
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { return; } ContentCachingRequestWrapper wrapperRequest = new ContentCachingRequestWrapper((HttpServletRequest) request); ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper((HttpServletResponse) response); String ua = wrapperRequest.getHeader("User-Agent"); ua = null == ua ? "" : ua; if (ua.equals("KeepAliveClient") || HttpMethod.HEAD.matches(wrapperRequest.getMethod())) { chain.doFilter(wrapperRequest, wrapperResponse); wrapperResponse.copyBodyToResponse(); } else { ApplicationContext context = ACU.ctx(); logFilterInterceptorList.forEach(LogFilterInterceptor::prepare); StringBuilder accessLogBuilder = new StringBuilder(); long startTime = Instant.now().toEpochMilli(); addLogKV(accessLogBuilder, "start", String.valueOf(startTime)); chain.doFilter(wrapperRequest, wrapperResponse); addLogKV(accessLogBuilder, "status", String.valueOf(wrapperResponse.getStatusCode())); RequestAttributes requestAttributes = (RequestAttributes) context.getBean("requestAttributes"); if (null != requestAttributes.getDeviceToken()) { addLogKV(accessLogBuilder, "vd", (String) requestAttributes.getDeviceToken()); } if (null != requestAttributes.getLoginUser()) { addLogKV(accessLogBuilder, "user", String.valueOf(requestAttributes.getLoginUser().getId())); addLogKV(accessLogBuilder, "token", requestAttributes.getLoginUser().getToken()); addLogKV(accessLogBuilder, "tokenExpireTime", requestAttributes.getLoginUser().getTokenExpireTime().toString ()); } addLogKV(accessLogBuilder, "locale", RequestContextUtils.getLocale(wrapperRequest).toLanguageTag()); String remoteIp = requestAttributes.getRemoteIp(); addLogKV(accessLogBuilder, "prevIp", wrapperRequest.getRemoteAddr()); addLogKV(accessLogBuilder, "remoteIp", remoteIp); addLogKV(accessLogBuilder, "request", wrapperRequest.getRequestURI()); addLogKV(accessLogBuilder, "method", wrapperRequest.getMethod()); addLogKV(accessLogBuilder, "params", parseParams(wrapperRequest.getParameterMap())); addLogKV(accessLogBuilder, "ua", wrapperRequest.getHeader("User-Agent")); if ("POST".equalsIgnoreCase(wrapperRequest.getMethod())) { byte[] content = wrapperRequest.getContentAsByteArray(); if (content.length < 1) { content = StreamUtils.copyToByteArray(wrapperRequest.getInputStream()); } addLogKV(accessLogBuilder, "body", IOUtils.toString(content, "UTF-8").replaceAll("\\r\\n", "") .replaceAll ("\\n", "")); } if (null != wrapperResponse.getContentType() && (wrapperResponse.getContentType().equals(MediaType .APPLICATION_JSON_UTF8_VALUE) || wrapperResponse.getContentType().equals(MediaType .APPLICATION_JSON_VALUE))) { addLogKV(accessLogBuilder, "response", IOUtils.toString(wrapperResponse.getContentAsByteArray(), "UTF-8")); } logFilterInterceptorList.forEach(logFilterInterceptor -> addLogKV(accessLogBuilder, logFilterInterceptor .getKey(), logFilterInterceptor.getOutput())); long endTime = Instant.now().toEpochMilli(); addLogKV(accessLogBuilder, "duration", String.valueOf(endTime - startTime) + "ms"); accessLogger.info(accessLogBuilder.toString()); wrapperResponse.copyBodyToResponse(); } }
@Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { Object handler = webRequest.getAttribute(WebRequestConstants.HANDLER, NativeWebRequest.SCOPE_REQUEST); Class<?> type = inspector.getInputType(handler); if (type == null) { type = Object.class; } boolean message = inspector.isMessage(handler); List<Object> body; ContentCachingRequestWrapper nativeRequest = new ContentCachingRequestWrapper( webRequest.getNativeRequest(HttpServletRequest.class)); if (logger.isDebugEnabled()) { logger.debug("Resolving request body into type: " + type); } if (isPlainText(webRequest) && CharSequence.class.isAssignableFrom(type)) { body = Arrays.asList(StreamUtils.copyToString(nativeRequest.getInputStream(), Charset.forName("UTF-8"))); } else { try { body = mapper.readValue(nativeRequest.getInputStream(), mapper.getTypeFactory() .constructCollectionLikeType(ArrayList.class, type)); } catch (JsonMappingException e) { nativeRequest.setAttribute(WebRequestConstants.INPUT_SINGLE, true); body = Arrays.asList( mapper.readValue(nativeRequest.getContentAsByteArray(), type)); } } if (message) { List<Object> messages = new ArrayList<>(); for (Object payload : body) { messages.add(MessageBuilder.withPayload(payload) .copyHeaders(HeaderUtils.fromHttp(new ServletServerHttpRequest( webRequest.getNativeRequest(HttpServletRequest.class)) .getHeaders())) .build()); } body = messages; } return new FluxRequest<Object>(body); }