2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (C) 2018 IBM.
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.logging.filter.base;
25 import java.io.BufferedReader;
26 import java.io.ByteArrayInputStream;
27 import java.io.ByteArrayOutputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.io.PrintWriter;
32 import java.util.zip.GZIPInputStream;
33 import javax.servlet.Filter;
34 import javax.servlet.FilterChain;
35 import javax.servlet.FilterConfig;
36 import javax.servlet.ReadListener;
37 import javax.servlet.ServletException;
38 import javax.servlet.ServletInputStream;
39 import javax.servlet.ServletOutputStream;
40 import javax.servlet.ServletRequest;
41 import javax.servlet.ServletResponse;
42 import javax.servlet.WriteListener;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.servlet.http.HttpServletRequestWrapper;
45 import javax.servlet.http.HttpServletResponse;
46 import javax.servlet.http.HttpServletResponseWrapper;
48 public class PayloadLoggingServletFilter extends AbstractServletFilter implements Filter {
50 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PayloadLoggingServletFilter.class);
51 private static final int defaultMaxSize = 100000;
52 private static Integer maxResponseSize;
53 private static Integer maxRequestSize;
54 protected static Boolean LOG_INVOKE;
56 public PayloadLoggingServletFilter() {
57 String maxRequestSizeOverride = System.getProperty("FILTER_MAX_REQUEST_SIZE");
58 if (maxRequestSizeOverride != null) {
59 maxRequestSize = Integer.valueOf(maxRequestSizeOverride);
61 maxRequestSize = defaultMaxSize;
64 String maxResponseSizeOverride = System.getProperty("FILTER_MAX_RESPONSE_SIZE");
65 if (maxResponseSizeOverride != null) {
66 maxResponseSize = Integer.valueOf(maxResponseSizeOverride);
68 maxResponseSize = defaultMaxSize;
72 private static class ByteArrayServletStream extends ServletOutputStream {
73 ByteArrayOutputStream baos;
75 ByteArrayServletStream(ByteArrayOutputStream baos) {
80 public void write(int param) throws IOException {
85 public boolean isReady() {
90 public void setWriteListener(WriteListener arg0) {
91 // this method does nothing
96 private static class ByteArrayPrintWriter extends PrintWriter {
97 private ByteArrayOutputStream baos;
98 private int errorCode = -1;
99 private String errorMsg = "";
100 private boolean errored = false;
102 public ByteArrayPrintWriter(ByteArrayOutputStream out) {
107 public ServletOutputStream getStream() {
108 return new ByteArrayServletStream(baos);
111 public Boolean hasErrored() {
115 public int getErrorCode() {
119 public String getErrorMsg() {
123 public void setError(int code) {
128 public void setError(int code, String msg) {
137 private class BufferedServletInputStream extends ServletInputStream {
138 ByteArrayInputStream bais;
140 public BufferedServletInputStream(ByteArrayInputStream bais) {
145 public int available() {
146 return bais.available();
155 public int read(byte[] buf, int off, int len) {
156 return bais.read(buf, off, len);
160 public boolean isFinished() {
161 return available() < 1;
165 public boolean isReady() {
170 public void setReadListener(ReadListener arg0) {
171 // this method does nothing
177 private class BufferedRequestWrapper extends HttpServletRequestWrapper {
178 ByteArrayInputStream bais;
179 ByteArrayOutputStream baos;
180 BufferedServletInputStream bsis;
183 public BufferedRequestWrapper(HttpServletRequest req) throws IOException {
186 InputStream is = req.getInputStream();
187 baos = new ByteArrayOutputStream();
188 byte[] buf = new byte[1024];
190 while ((letti = is.read(buf)) > 0) {
191 baos.write(buf, 0, letti);
193 buffer = baos.toByteArray();
197 public ServletInputStream getInputStream() {
199 bais = new ByteArrayInputStream(buffer);
200 bsis = new BufferedServletInputStream(bais);
201 } catch (Exception ex) {
202 log.error("Exception in getInputStream", ex);
207 public byte[] getBuffer() {
213 public void init(FilterConfig filterConfig) throws ServletException {
214 // this method does nothing
218 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
219 throws IOException, ServletException {
220 final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
221 BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpRequest);
223 StringBuilder requestHeaders = new StringBuilder("REQUEST|");
224 requestHeaders.append(httpRequest.getMethod());
225 requestHeaders.append(":");
226 requestHeaders.append(httpRequest.getRequestURL().toString());
227 requestHeaders.append("|");
228 requestHeaders.append(getSecureRequestHeaders(httpRequest));
230 log.info(requestHeaders.toString());
232 byte[] buffer = bufferedRequest.getBuffer();
233 if (buffer.length < maxRequestSize) {
234 log.info("REQUEST BODY|{}", new String(buffer));
236 log.info("REQUEST BODY|{}", new String(buffer, 0, maxRequestSize));
239 final HttpServletResponse response = (HttpServletResponse) servletResponse;
240 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
241 final ByteArrayPrintWriter pw = new ByteArrayPrintWriter(baos);
243 HttpServletResponse wrappedResp = new HttpServletResponseWrapper(response) {
245 public PrintWriter getWriter() {
250 public ServletOutputStream getOutputStream() {
251 return pw.getStream();
255 public void sendError(int sc) throws IOException {
261 public void sendError(int sc, String msg) throws IOException {
262 super.sendError(sc, msg);
263 pw.setError(sc, msg);
268 filterChain.doFilter(bufferedRequest, wrappedResp);
269 } catch (Exception e) {
270 log.error("Chain Exception", e);
274 byte[] bytes = baos.toByteArray();
275 StringBuilder responseHeaders = new StringBuilder();
276 responseHeaders.append("RESPONSE HEADERS|").append(formatResponseHeaders(response));
277 responseHeaders.append("Status:").append(response.getStatus());
278 responseHeaders.append(";IsCommitted:").append(wrappedResp.isCommitted());
280 log.info(responseHeaders.toString());
282 if ("gzip".equals(response.getHeader("Content-Encoding"))) {
283 log.info("UNGZIPED RESPONSE BODY|{}", decompressGZIPByteArray(bytes));
285 if (bytes.length < maxResponseSize) {
286 log.info("RESPONSE BODY|{}", new String(bytes));
288 log.info("RESPONSE BODY|{}", new String(bytes, 0, maxResponseSize));
292 if (pw.hasErrored()) {
293 log.info("ERROR RESPONSE|{}:{}", pw.getErrorCode(), pw.getErrorMsg());
294 } else if (!wrappedResp.isCommitted()) {
295 response.getOutputStream().write(bytes);
296 response.getOutputStream().flush();
298 } catch (Exception e) {
299 log.error("Exception in response filter", e);
305 public void destroy() {
306 // this method does nothing
309 private String decompressGZIPByteArray(byte[] bytes) {
310 StringBuilder str = new StringBuilder();
311 try (BufferedReader in =
312 new BufferedReader(new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(bytes))))) {
314 while ((content = in.readLine()) != null) {
317 } catch (Exception e) {
318 log.error("Failed get read GZIPInputStream", e);
320 return str.toString();