2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.sensibo.internal.client;
15 import java.nio.charset.Charset;
16 import java.nio.charset.StandardCharsets;
17 import java.util.Locale;
18 import java.util.concurrent.atomic.AtomicLong;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jetty.client.api.Request;
22 import org.eclipse.jetty.http.HttpField;
23 import org.eclipse.jetty.http.HttpFields;
24 import org.eclipse.jetty.http.HttpHeader;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
28 import com.google.gson.Gson;
29 import com.google.gson.JsonElement;
30 import com.google.gson.JsonParser;
31 import com.google.gson.JsonSyntaxException;
34 * Logs HttpClient request/response traffic.
36 * @author Gili Tzabari - Initial contribution https://stackoverflow.com/users/14731/gili
37 * https://stackoverflow.com/questions/50318736/how-to-log-httpclient-requests-response-including-body
38 * @author Arne Seime - adapted for openHAB binding
41 public final class RequestLogger {
42 private final Logger logger = LoggerFactory.getLogger(RequestLogger.class);
43 private final AtomicLong nextId = new AtomicLong();
44 private final JsonParser parser;
45 private final Gson gson;
46 private final String prefix;
48 public RequestLogger(final String prefix, final Gson gson) {
49 parser = new JsonParser();
54 private void dump(final Request request, String[] stringsToRemove) {
55 final long idV = nextId.getAndIncrement();
56 if (logger.isDebugEnabled()) {
57 final String id = prefix + "-" + idV;
58 final StringBuilder group = new StringBuilder();
59 request.onRequestBegin(theRequest -> group.append(
60 String.format("Request %s%n%s > %s %s%n", id, id, theRequest.getMethod(), theRequest.getURI())));
61 request.onRequestHeaders(theRequest -> {
62 for (final HttpField header : theRequest.getHeaders()) {
63 group.append(String.format("%s > %s%n", id, header));
66 final StringBuilder contentBuffer = new StringBuilder();
67 request.onRequestContent((theRequest, content) -> contentBuffer
68 .append(getCharset(theRequest.getHeaders()).decode(content).toString()));
69 request.onRequestSuccess(theRequest -> {
70 if (contentBuffer.length() > 0) {
72 group.append(reformatJson(contentBuffer.toString()));
74 String dataToLog = group.toString();
75 scrambleAndLog(stringsToRemove, dataToLog);
76 contentBuffer.delete(0, contentBuffer.length());
77 group.delete(0, group.length());
79 request.onResponseBegin(theResponse -> {
80 group.append(String.format("Response %s%n%s < %s %s", id, id, theResponse.getVersion(),
81 theResponse.getStatus()));
82 if (theResponse.getReason() != null) {
84 group.append(theResponse.getReason());
88 request.onResponseHeaders(theResponse -> {
89 for (final HttpField header : theResponse.getHeaders()) {
90 group.append(String.format("%s < %s%n", id, header));
93 request.onResponseContent((theResponse, content) -> contentBuffer
94 .append(getCharset(theResponse.getHeaders()).decode(content).toString()));
95 request.onResponseSuccess(theResponse -> {
96 if (contentBuffer.length() > 0) {
98 group.append(reformatJson(contentBuffer.toString()));
101 String dataToLog = group.toString();
102 scrambleAndLog(stringsToRemove, dataToLog);
107 private void scrambleAndLog(String[] stringsToRemove, String dataToLog) {
108 String modifiedData = dataToLog;
109 for (String stringToRemove : stringsToRemove) {
110 modifiedData = modifiedData.replace(stringToRemove, "<HIDDEN>");
112 logger.debug("{}", modifiedData);
115 private Charset getCharset(final HttpFields headers) {
116 final String contentType = headers.get(HttpHeader.CONTENT_TYPE);
117 if (contentType == null) {
118 return StandardCharsets.UTF_8;
120 final String[] tokens = contentType.toLowerCase(Locale.US).split("charset=");
121 if (tokens.length != 2) {
122 return StandardCharsets.UTF_8;
125 final String encoding = tokens[1].replaceAll("[;\"]", "");
126 return Charset.forName(encoding);
129 public Request listenTo(final Request request, String[] stringToRemove) {
130 dump(request, stringToRemove);
134 private String reformatJson(final String jsonString) {
136 final JsonElement json = parser.parse(jsonString);
137 return gson.toJson(json);
138 } catch (final JsonSyntaxException e) {
139 logger.debug("Could not reformat malformed JSON due to '{}'", e.getMessage());