Carry forward honolulu fixes
[ccsdk/apps.git] / services / src / main / java / org / onap / ccsdk / apps / filters / PayloadLoggingFilter.java
1 package org.onap.ccsdk.apps.filters;
2
3 import java.io.BufferedReader;
4 import java.io.ByteArrayInputStream;
5 import java.io.CharArrayWriter;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.io.PrintWriter;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.Enumeration;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18
19 import javax.servlet.Filter;
20 import javax.servlet.FilterChain;
21 import javax.servlet.FilterConfig;
22 import javax.servlet.ReadListener;
23 import javax.servlet.ServletException;
24 import javax.servlet.ServletInputStream;
25 import javax.servlet.ServletOutputStream;
26 import javax.servlet.ServletRequest;
27 import javax.servlet.ServletResponse;
28 import javax.servlet.WriteListener;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletRequestWrapper;
31 import javax.servlet.http.HttpServletResponse;
32 import javax.servlet.http.HttpServletResponseWrapper;
33
34 import org.onap.logging.filter.base.AbstractServletFilter;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.springframework.stereotype.Component;
38
39 @Component
40 public class PayloadLoggingFilter extends AbstractServletFilter implements Filter {
41
42         private static final Logger log = LoggerFactory.getLogger(PayloadLoggingFilter.class);
43
44         @Override
45         public void init(FilterConfig filterConfig) throws ServletException {
46         }
47
48         @Override
49         public void destroy() {
50         }
51
52         @Override
53         public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
54                 RequestWrapper req = new RequestWrapper((HttpServletRequest) request);
55                 Request requestData = req.getMessageRequest();
56                 
57                 StringBuilder requestHeaders = new StringBuilder("REQUEST|");
58             requestHeaders.append(requestData.method);
59             requestHeaders.append(":");
60             requestHeaders.append(requestData.uri);
61             requestHeaders.append("|");
62             mapstr(requestHeaders, requestData.headers);
63
64             log.info(requestHeaders.toString());
65             log.info("REQUEST BODY|{}", requestData.body);
66
67                 ResponseWrapper res = new ResponseWrapper((HttpServletResponse) response);
68
69                 chain.doFilter(req, res);
70
71                 Response responseData = res.getMessageResponse();
72                 
73                 StringBuilder responseHeaders = new StringBuilder();
74         responseHeaders.append("RESPONSE HEADERS|");
75         mapstr(responseHeaders, responseData.headers);
76         responseHeaders.append("Status:").append(responseData.code);
77         responseHeaders.append(";IsCommitted:").append(res.isCommitted());
78
79         log.info(responseHeaders.toString());
80                 log.info("RESPONSE BODY|{}", responseData.body);
81
82                 res.writeBody();
83         }
84
85         private static class Request {
86
87                 public String method;
88                 public String uri;
89                 public Map<String, Object> headers;
90                 public Map<String, Object> param;
91                 public String body;
92
93                 @Override
94                 public String toString() {
95                         StringBuilder ss = new StringBuilder();
96                         ss.append("REQUEST|").append(method).append(":").append(uri).append("|");
97                         ss.append("Headers: ");
98                         mapstr(ss, headers);
99                         if (param != null && !param.isEmpty()) {
100                                 ss.append("Parameters: ");
101                                 mapstr(ss, param);
102                         }
103                         ss.append("REQUEST BODY|\n");
104                         ss.append(body);
105                         return ss.toString();
106                 }
107         }
108
109         private static class Response {
110
111                 public int code;
112                 public String message;
113                 public Map<String, Object> headers;
114                 public String body;
115
116                 @Override
117                 public String toString() {
118                         StringBuilder ss = new StringBuilder();
119                         ss.append("HTTP Response: ").append(code).append(" ").append(message).append("\n");
120                         ss.append("Headers:\n");
121                         mapstr(ss, headers);
122                         ss.append("Body:\n");
123                         ss.append(body);
124                         return ss.toString();
125                 }
126         }
127
128         private static class RequestWrapper extends HttpServletRequestWrapper {
129
130                 private final String body;
131
132                 public RequestWrapper(HttpServletRequest request) throws IOException {
133                         super(request);
134
135                         StringBuilder stringBuilder = new StringBuilder();
136                         InputStream inputStream = request.getInputStream();
137                         if (inputStream != null) {
138                                 try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
139                                         char[] charBuffer = new char[128];
140                                         int bytesRead = -1;
141                                         while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
142                                                 stringBuilder.append(charBuffer, 0, bytesRead);
143                                         }
144                                 }
145                         }
146                         body = stringBuilder.toString();
147                 }
148
149                 @Override
150                 public ServletInputStream getInputStream() throws IOException {
151                         final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
152                         ServletInputStream servletInputStream = new ServletInputStream() {
153
154                                 @Override
155                                 public int read() throws IOException {
156                                         return byteArrayInputStream.read();
157                                 }
158
159                                 @Override
160                                 public boolean isFinished() {
161                                         return byteArrayInputStream.available() == 0;
162                                 }
163
164                                 @Override
165                                 public boolean isReady() {
166                                         return true;
167                                 }
168
169                                 @Override
170                                 public void setReadListener(ReadListener listener) {
171                                 }
172                         };
173                         return servletInputStream;
174                 }
175
176                 @Override
177                 public BufferedReader getReader() throws IOException {
178                         return new BufferedReader(new InputStreamReader(getInputStream()));
179                 }
180
181                 public String getBody() {
182                         return body;
183                 }
184
185                 public Request getMessageRequest() {
186                         Request r = new Request();
187                         r.method = getMethod();
188                         r.uri = getRequestURI();
189                         r.param = getParamMap();
190
191                         r.headers = new HashMap<>();
192                         Enumeration<String> headerNames = getHeaderNames();
193                         while (headerNames.hasMoreElements()) {
194                                 String name = headerNames.nextElement();
195
196                                 if (name.equalsIgnoreCase("authorization")) {
197                                         r.headers.put(name, "***REDACTED***");
198                                         continue;
199                                 }
200
201                                 Enumeration<String> values = getHeaders(name);
202                                 List<String> valueList = new ArrayList<>();
203                                 while (values.hasMoreElements()) {
204                                         valueList.add(values.nextElement());
205                                 }
206                                 if (valueList.size() > 1) {
207                                         r.headers.put(name, valueList);
208                                 } else if (valueList.size() > 0) {
209                                         r.headers.put(name, valueList.get(0));
210                                 }
211                         }
212
213                         r.body = getBody();
214
215                         return r;
216                 }
217
218                 private Map<String, Object> getParamMap() {
219                         Map<String, String[]> parameterMap = getParameterMap();
220                         Map<String, Object> paramMap = new HashMap<>();
221                         if (parameterMap != null) {
222                                 for (Entry<String, String[]> entry : parameterMap.entrySet()) {
223                                         String name = entry.getKey();
224                                         String[] values = entry.getValue();
225                                         if (values != null && values.length > 0) {
226                                                 if (values.length == 1) {
227                                                         paramMap.put(name, values[0]);
228                                                 } else {
229                                                         paramMap.put(name, Arrays.<String> asList(values));
230                                                 }
231                                         }
232                                 }
233                         }
234                         return paramMap;
235                 }
236         }
237
238         public class ResponseWrapper extends HttpServletResponseWrapper {
239
240                 private CharArrayWriter writer = new CharArrayWriter();
241
242                 private String statusMessage;
243
244                 public ResponseWrapper(HttpServletResponse response) {
245                         super(response);
246                 }
247
248                 @Override
249                 public PrintWriter getWriter() {
250                         return new PrintWriter(writer);
251                 }
252
253                 @Override
254                 public ServletOutputStream getOutputStream() {
255                         return new ServletOutputStream() {
256
257                                 @Override
258                                 public void write(int b) throws IOException {
259                                         writer.write(b);
260                                 }
261
262                                 @Override
263                                 public void setWriteListener(WriteListener listener) {
264                                 }
265
266                                 @Override
267                                 public boolean isReady() {
268                                         return true;
269                                 }
270                         };
271                 }
272
273                 @SuppressWarnings("deprecation")
274                 @Override
275                 public void setStatus(int sc, String sm) {
276                         super.setStatus(sc, sm);
277                         statusMessage = sm;
278                 }
279
280                 public Response getMessageResponse() {
281                         Response r = new Response();
282                         r.code = getStatus();
283                         r.message = statusMessage == null ? "" : statusMessage;
284
285                         r.headers = new HashMap<>();
286                         Collection<String> headerNames = getHeaderNames();
287                         for (String name : headerNames) {
288
289                                 if (name.equalsIgnoreCase("authorization")) {
290                                         r.headers.put(name, "***REDACTED***");
291                                         continue;
292                                 }
293
294                                 Collection<String> values = getHeaders(name);
295                                 List<String> valueList = new ArrayList<>(values);
296                                 if (valueList.size() > 1) {
297                                         r.headers.put(name, valueList);
298                                 } else {
299                                         r.headers.put(name, valueList.get(0));
300                                 }
301                         }
302
303                         r.body = writer.toString();
304
305                         return r;
306                 }
307
308                 public void writeBody() throws IOException {
309                         String body = writer.toString();
310                         setContentLength(body.length());
311                         super.getWriter().write(body);
312                 }
313         }
314
315         private static void mapstr(StringBuilder ss, Map<String, Object> m) {
316                 if (m != null) {
317                         for (Entry<String, Object> entry : m.entrySet()) {
318                                 ss.append(entry.getKey()).append(": ").append(entry.getValue()).append(";");
319                         }
320                 }
321         }
322 }