com.turbospaces.resteasy.DefaultHttpClientResponsePrinter Maven / Gradle / Ivy
The newest version!
package com.turbospaces.resteasy;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker;
import com.github.robtimus.obfuscation.Obfuscator;
import com.github.robtimus.obfuscation.http.HeaderObfuscator;
import com.google.common.net.HttpHeaders;
import com.turbospaces.annotations.ApiEndpoint;
import com.turbospaces.cfg.ApplicationProperties;
import com.turbospaces.http.HttpProto;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientResponseContext;
import jakarta.ws.rs.core.Cookie;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NewCookie;
import jakarta.ws.rs.ext.RuntimeDelegate;
import jakarta.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DefaultHttpClientResponsePrinter implements HttpClientResponsePrinter {
private static HeaderDelegate COOKIE_PRINTER = RuntimeDelegate.getInstance().createHeaderDelegate(Cookie.class);
protected final ApplicationProperties props;
protected final StringWriter writer = new StringWriter();
protected final BufferedWriter buffer = new BufferedWriter(writer);
public DefaultHttpClientResponsePrinter(ApplicationProperties props) {
this.props = Objects.requireNonNull(props);
}
@Override
public void writeStart(ClientRequestContext req, ClientResponseContext resp) throws IOException {
buffer.write("Response:");
buffer.newLine();
}
@Override
public void writeUri(ClientRequestContext context, ClientResponseContext resp) throws IOException {
URIBuilder builder = (URIBuilder) context.getProperty(HttpProto.toCtxName(HttpProto.CONTEXT_URI));
buffer.write(context.getMethod() + ": " + builder);
buffer.newLine();
}
@Override
public void writeStatus(ClientRequestContext req, ClientResponseContext resp) throws IOException {
buffer.write("Status: " + resp.getStatus());
buffer.newLine();
if (resp.getLength() > 0) {
buffer.write("Length: " + resp.getLength());
buffer.newLine();
}
}
@Override
public void writeHeaders(ClientRequestContext req, ClientResponseContext resp) throws IOException {
MultivaluedMap headers = resp.getHeaders();
HeaderObfuscator.Builder b = HeaderObfuscator.builder();
List l = props.HTTP_HEADERS_TO_MASK.get();
if (CollectionUtils.isNotEmpty(l)) {
for (String it : l) {
b.withHeader(it, Obfuscator.all());
}
}
HeaderObfuscator obfuscator = b.build();
if (BooleanUtils.isFalse(headers.isEmpty())) {
for (Entry> next : headers.entrySet()) {
String name = next.getKey();
boolean isNotCookie = BooleanUtils.isFalse(StringUtils.equalsIgnoreCase(name, HttpHeaders.SET_COOKIE));
if (isNotCookie) {
if (CollectionUtils.isNotEmpty(next.getValue())) {
for (String value : next.getValue()) {
buffer.write(String.format("Header: %s = %s", name, obfuscator.obfuscateHeader(name, value)));
buffer.newLine();
}
}
}
}
}
}
@Override
public void writeCookies(ClientRequestContext req, ClientResponseContext resp) throws IOException {
Map cookies = resp.getCookies();
if (BooleanUtils.isFalse(cookies.isEmpty())) {
for (Entry next : cookies.entrySet()) {
NewCookie cookie = next.getValue();
if (cookie.isHttpOnly()) {
String cookieValue = StringUtils.isNotEmpty(cookie.getValue()) ? cookie.getValue() : StringUtils.EMPTY;
buffer.write(
String.format("Cookie: %s=%s Domain: %s, Path: %s, MaxAge: %s, Expire: %s, HttpOnly: %s, Secure: %s",
cookie.getName(),
cookie.isHttpOnly() ? Obfuscator.all().obfuscateText(cookieValue) : cookieValue,
cookie.getDomain(),
cookie.getPath(),
cookie.getMaxAge(),
cookie.getExpiry(),
cookie.isHttpOnly(), cookie.isSecure()));
} else {
buffer.write(String.format("Cookie: %s", COOKIE_PRINTER.toString(cookie)));
}
buffer.newLine();
}
}
}
@Override
public void writeBody(ClientRequestContext req, ClientResponseContext resp) throws IOException {
if (resp.hasEntity()) {
ClientInvoker invoker = clientInvoker(req);
Class> resource = invoker.getDeclaring();
Method method = invoker.getMethod();
boolean doNotPrintBody = false;
if (Objects.nonNull(resource.getAnnotation(ApiEndpoint.class))) {
ApiEndpoint api = resource.getAnnotation(ApiEndpoint.class);
doNotPrintBody = api.doNotPrintResponseBody();
}
if (Objects.nonNull(method.getAnnotation(ApiEndpoint.class))) {
ApiEndpoint api = method.getAnnotation(ApiEndpoint.class);
doNotPrintBody = api.doNotPrintResponseBody();
}
if (doNotPrintBody) {
buffer.write("Body: Hidden{*}");
} else {
InputStream io = resp.getEntityStream();
if (Objects.nonNull(io)) {
byte[] bytes = IOUtils.toByteArray(io);
resp.setEntityStream(new ByteArrayInputStream(bytes));
Charset charset = StandardCharsets.UTF_8;
MediaType mediaType = resp.getMediaType();
if (Objects.nonNull(mediaType)) {
String charsetName = mediaType.getParameters().get("charset");
if (Objects.nonNull(charsetName)) {
try {
charset = Charset.forName(charsetName);
} catch (Exception err) {
log.trace(err.getMessage(), err);
}
}
}
buffer.write("Body: " + new String(bytes, charset));
}
}
}
}
@Override
public void doOutPut(ClientRequestContext req, ClientResponseContext resp) {
try {
writeStart(req, resp);
writeUri(req, resp);
writeStatus(req, resp);
writeHeaders(req, resp);
writeCookies(req, resp);
writeBody(req, resp);
buffer.flush();
LOGGING_FILTER_LOGGER.debug(writer.toString());
buffer.close();
writer.close();
} catch (IOException err) {
log.error(err.getMessage(), err);
}
}
}