| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the License. You may obtain a |
| * copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package org.apache.geode.management.internal.rest; |
| |
| import java.io.IOException; |
| import java.io.UnsupportedEncodingException; |
| |
| import javax.servlet.FilterChain; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.springframework.web.filter.OncePerRequestFilter; |
| import org.springframework.web.util.ContentCachingRequestWrapper; |
| import org.springframework.web.util.ContentCachingResponseWrapper; |
| |
| public class ManagementLoggingFilter extends OncePerRequestFilter { |
| |
| // Because someone is going to want to disable this. |
| private static final Boolean ENABLE_REQUEST_LOGGING = |
| Boolean.parseBoolean(System.getProperty("geode.management.request.logging", "true")); |
| |
| private static int MAX_PAYLOAD_LENGTH = 10000; |
| |
| @Override |
| protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, |
| FilterChain filterChain) throws ServletException, IOException { |
| |
| if (!ENABLE_REQUEST_LOGGING) { |
| filterChain.doFilter(request, response); |
| return; |
| } |
| |
| // We can not log request payload before making the actual request because then the InputStream |
| // would be consumed and cannot be read again by the actual processing/server. |
| ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request); |
| ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response); |
| |
| // performs the actual request before logging |
| filterChain.doFilter(wrappedRequest, wrappedResponse); |
| |
| // Log after the request has been made and ContentCachingRequestWrapper has cached the request |
| // payload. We don't want to log any swagger requests though. |
| if (!(request.getRequestURI().contains("swagger") |
| || request.getRequestURI().contains("api-docs"))) { |
| logRequest(request, wrappedRequest); |
| logResponse(response, wrappedResponse); |
| } |
| |
| // IMPORTANT: copy content of response back into original response |
| wrappedResponse.copyBodyToResponse(); |
| } |
| |
| private void logRequest(HttpServletRequest request, ContentCachingRequestWrapper wrappedRequest) { |
| String requestPattern = "Management Request: %s[url=%s]; user=%s; payload=%s"; |
| String requestUrl = request.getRequestURI(); |
| if (request.getQueryString() != null) { |
| requestUrl = requestUrl + "?" + request.getQueryString(); |
| } |
| String payload = getContentAsString(wrappedRequest.getContentAsByteArray(), |
| wrappedRequest.getCharacterEncoding()); |
| logger.info(String.format(requestPattern, request.getMethod(), requestUrl, |
| request.getRemoteUser(), payload)); |
| } |
| |
| private void logResponse(HttpServletResponse response, |
| ContentCachingResponseWrapper wrappedResponse) { |
| // construct the response message |
| String responsePattern = "Management Response: Status=%s; response=%s"; |
| String payload = getContentAsString(wrappedResponse.getContentAsByteArray(), |
| wrappedResponse.getCharacterEncoding()); |
| logger.info(String.format(responsePattern, response.getStatus(), payload)); |
| } |
| |
| private String getContentAsString(byte[] buf, String encoding) { |
| if (buf == null || buf.length == 0) { |
| return ""; |
| } |
| int length = Math.min(buf.length, MAX_PAYLOAD_LENGTH); |
| try { |
| return new String(buf, 0, length, encoding); |
| } catch (UnsupportedEncodingException ex) { |
| return "[unknown]"; |
| } |
| } |
| } |