package de.rwth.idsg.bikeman.psinterface.log;
import com.google.common.base.Joiner;
import de.rwth.idsg.bikeman.psinterface.Utils;
import de.rwth.idsg.bikeman.psinterface.exception.PsException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Taken from https://github.com/isrsal/spring-mvc-logger and modified
*
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
* @since 09.10.2015
*/
@Slf4j
public class ResourceLogFilter extends OncePerRequestFilter {
private static final String PREFIX_FORMAT = "[stationId=%s, requestId=%s] ";
private static final String REQUEST_PREFIX = "Request: ";
private static final String RESPONSE_PREFIX = "Response: ";
private AtomicInteger id = new AtomicInteger(0);
private static final Joiner.MapJoiner joiner = Joiner.on(", ").withKeyValueSeparator("=");
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException {
if (log.isDebugEnabled()) {
String from = null;
boolean stationHeaderMissing = false;
try {
from = Utils.getFrom(request);
} catch (PsException e) {
stationHeaderMissing = true;
}
String prefix = String.format(PREFIX_FORMAT, from, id.incrementAndGet());
request = new RequestWrapper(prefix, request, stationHeaderMissing);
response = new ResponseWrapper(prefix, response);
}
try {
filterChain.doFilter(request, response);
//response.flushBuffer();
} finally {
if (log.isDebugEnabled()) {
logRequest(request);
logResponse(response);
}
}
}
private void logRequest(final HttpServletRequest request) {
if (request instanceof RequestWrapper) {
RequestWrapper wrap = (RequestWrapper) request;
StringBuilder msg = new StringBuilder();
msg.append(wrap.getPrefix())
.append(REQUEST_PREFIX)
.append("uri=")
.append(request.getRequestURI());
try {
msg.append("; payload=")
.append(new String(wrap.toByteArray(), wrap.getCharacterEncoding()));
} catch (UnsupportedEncodingException e) {
log.warn("Failed to parse request payload", e);
}
if (wrap.isStationHeaderMissing()) {
log.error("stationId header was missing. Headers=[{}]", joiner.join(getHeadersMap(request)));
}
log.debug(msg.toString());
}
}
private void logResponse(final HttpServletResponse response) {
if (response instanceof ResponseWrapper) {
ResponseWrapper wrap = (ResponseWrapper) response;
StringBuilder msg = new StringBuilder();
msg.append(wrap.getPrefix())
.append(RESPONSE_PREFIX)
.append("statusCode=")
.append(response.getStatus());
try {
msg.append("; payload=")
.append(new String(wrap.toByteArray(), wrap.getCharacterEncoding()));
} catch (UnsupportedEncodingException e) {
log.warn("Failed to parse response payload", e);
}
log.debug(msg.toString());
}
}
private Map<String, String> getHeadersMap(HttpServletRequest request) {
Map<String, String> map = new HashMap<>();
Enumeration names = request.getHeaderNames();
while (names.hasMoreElements()) {
String key = (String) names.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
return map;
}
}