This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new bf3bf356907 CAMEL-21468: camel-http - Allow to log request/repsonse 
HTTP raw data to see what is sent over the wire.
bf3bf356907 is described below

commit bf3bf356907ad2f9f198e0fd21a496a981fc4395
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Dec 11 20:58:15 2024 +0100

    CAMEL-21468: camel-http - Allow to log request/repsonse HTTP raw data to 
see what is sent over the wire.
---
 .../catalog/beans/LoggingHttpActivityListener.json |   2 +-
 .../LoggingHttpActivityListenerConfigurer.java     |   6 ++
 .../camel/bean/LoggingHttpActivityListener.json    |   2 +-
 .../http/LoggingHttpActivityListener.java          | 109 ++++++++++++++-------
 4 files changed, 80 insertions(+), 39 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/LoggingHttpActivityListener.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/LoggingHttpActivityListener.json
index 2b402ccb946..b961bc96148 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/LoggingHttpActivityListener.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/LoggingHttpActivityListener.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-http",
     "version": "4.10.0-SNAPSHOT",
-    "properties": { "loggingLevel": { "index": 0, "kind": "property", 
"displayName": "Logging Level", "required": false, "type": "string", 
"javaType": "java.lang.String", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", 
"ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "INFO", "description": "" }, "showRouteId": { "index": 1, 
"kind": "property", "displayName": "Show Route Id", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated":  [...]
+    "properties": { "loggingLevel": { "index": 0, "kind": "property", 
"displayName": "Logging Level", "required": false, "type": "string", 
"javaType": "java.lang.String", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", 
"ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "INFO", "description": "" }, "showRouteId": { "index": 1, 
"kind": "property", "displayName": "Show Route Id", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated":  [...]
   }
 }
 
diff --git 
a/components/camel-http/src/generated/java/org/apache/camel/component/http/LoggingHttpActivityListenerConfigurer.java
 
b/components/camel-http/src/generated/java/org/apache/camel/component/http/LoggingHttpActivityListenerConfigurer.java
index cc2d8facf51..ee662d50e1c 100644
--- 
a/components/camel-http/src/generated/java/org/apache/camel/component/http/LoggingHttpActivityListenerConfigurer.java
+++ 
b/components/camel-http/src/generated/java/org/apache/camel/component/http/LoggingHttpActivityListenerConfigurer.java
@@ -30,6 +30,8 @@ public class LoggingHttpActivityListenerConfigurer extends 
org.apache.camel.supp
         case "maxchars":
         case "maxChars": target.setMaxChars(property(camelContext, int.class, 
value)); return true;
         case "multiline": target.setMultiline(property(camelContext, 
boolean.class, value)); return true;
+        case "showbinary":
+        case "showBinary": target.setShowBinary(property(camelContext, 
boolean.class, value)); return true;
         case "showbody":
         case "showBody": target.setShowBody(property(camelContext, 
boolean.class, value)); return true;
         case "showexchangeid":
@@ -58,6 +60,8 @@ public class LoggingHttpActivityListenerConfigurer extends 
org.apache.camel.supp
         case "maxchars":
         case "maxChars": return int.class;
         case "multiline": return boolean.class;
+        case "showbinary":
+        case "showBinary": return boolean.class;
         case "showbody":
         case "showBody": return boolean.class;
         case "showexchangeid":
@@ -87,6 +91,8 @@ public class LoggingHttpActivityListenerConfigurer extends 
org.apache.camel.supp
         case "maxchars":
         case "maxChars": return target.getMaxChars();
         case "multiline": return target.isMultiline();
+        case "showbinary":
+        case "showBinary": return target.isShowBinary();
         case "showbody":
         case "showBody": return target.isShowBody();
         case "showexchangeid":
diff --git 
a/components/camel-http/src/generated/resources/META-INF/services/org/apache/camel/bean/LoggingHttpActivityListener.json
 
b/components/camel-http/src/generated/resources/META-INF/services/org/apache/camel/bean/LoggingHttpActivityListener.json
index 2b402ccb946..b961bc96148 100644
--- 
a/components/camel-http/src/generated/resources/META-INF/services/org/apache/camel/bean/LoggingHttpActivityListener.json
+++ 
b/components/camel-http/src/generated/resources/META-INF/services/org/apache/camel/bean/LoggingHttpActivityListener.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-http",
     "version": "4.10.0-SNAPSHOT",
-    "properties": { "loggingLevel": { "index": 0, "kind": "property", 
"displayName": "Logging Level", "required": false, "type": "string", 
"javaType": "java.lang.String", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", 
"ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "INFO", "description": "" }, "showRouteId": { "index": 1, 
"kind": "property", "displayName": "Show Route Id", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated":  [...]
+    "properties": { "loggingLevel": { "index": 0, "kind": "property", 
"displayName": "Logging Level", "required": false, "type": "string", 
"javaType": "java.lang.String", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", 
"ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "INFO", "description": "" }, "showRouteId": { "index": 1, 
"kind": "property", "displayName": "Show Route Id", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated":  [...]
   }
 }
 
diff --git 
a/components/camel-http/src/main/java/org/apache/camel/component/http/LoggingHttpActivityListener.java
 
b/components/camel-http/src/main/java/org/apache/camel/component/http/LoggingHttpActivityListener.java
index 29184af7cc2..eaab950c5af 100644
--- 
a/components/camel-http/src/main/java/org/apache/camel/component/http/LoggingHttpActivityListener.java
+++ 
b/components/camel-http/src/main/java/org/apache/camel/component/http/LoggingHttpActivityListener.java
@@ -59,24 +59,27 @@ public class LoggingHttpActivityListener extends 
ServiceSupport implements Camel
 
     @Metadata(defaultValue = "INFO", enums = "TRACE,DEBUG,INFO,WARN,ERROR,OFF")
     private String loggingLevel;
-    @Metadata(defaultValue = "true", description = "Show route ID.")
+    @Metadata(defaultValue = "true", description = "Show route ID")
     private boolean showRouteId = true;
-    @Metadata(defaultValue = "true", description = "Show route Group.")
+    @Metadata(defaultValue = "true", description = "Show route Group")
     private boolean showRouteGroup = true;
-    @Metadata(defaultValue = "true", description = "Show the unique exchange 
ID.")
+    @Metadata(defaultValue = "true", description = "Show the unique exchange 
ID")
     private boolean showExchangeId = true;
-    @Metadata(defaultValue = "true", description = "Show the HTTP body.")
+    @Metadata(defaultValue = "true", description = "Show the HTTP body")
     private boolean showBody = true;
+    @Metadata(defaultValue = "true", label = "formatting", description = "Show 
the HTTP headers")
+    private boolean showHeaders = true;
     @Metadata(defaultValue = "true",
               description = "Whether to show HTTP body that are streaming 
based. Beware that Camel will have to read the content into memory to print to 
log, and will re-create the HttpEntity stored on the request/response object. 
If you have large payloads then this can impact performance.")
     private boolean showStreams = true;
-    @Metadata(defaultValue = "true", label = "formatting", description = "Show 
the HTTP headers.")
-    private boolean showHeaders = true;
-    @Metadata(defaultValue = "50000", description = "Limits the number of 
characters logged from the HTTP body.")
+    @Metadata(defaultValue = "false",
+              description = "Whether to show HTTP body that are binary based 
(uses content-type to determine whether binary)")
+    private boolean showBinary;
+    @Metadata(defaultValue = "50000", description = "Limits the number of 
characters logged from the HTTP body")
     private int maxChars = 50000;
-    @Metadata(description = "If true, mask sensitive information like password 
or passphrase in the log.")
+    @Metadata(description = "If true, mask sensitive information like password 
or passphrase in the log")
     private Boolean logMask;
-    @Metadata(defaultValue = "true", description = "If enabled then each 
information is outputted as separate LOG events.")
+    @Metadata(defaultValue = "true", description = "If enabled then each 
information is outputted as separate LOG events")
     private boolean multiline;
     @Metadata(defaultValue = "true",
               description = "If enabled then the source location of where the 
log endpoint is used in Camel routes, would be used as logger name, instead"
@@ -163,37 +166,48 @@ public class LoggingHttpActivityListener extends 
ServiceSupport implements Camel
                     if (e.isStreaming() && !showStreams) {
                         lines.add("WARN: Cannot log HTTP body because the body 
is streaming");
                     } else {
-                        Header ce = request != null
-                                ? 
request.getHeader(HttpHeaders.CONTENT_ENCODING)
-                                : 
response.getHeader(HttpHeaders.CONTENT_ENCODING);
-                        ByteArrayOutputStream bos = new 
ByteArrayOutputStream();
-                        e.writeTo(bos);
-                        String data;
-                        if (ce != null && GZIPHelper.isGzip(ce.getValue())) {
-                            ByteArrayInputStream bis = new 
ByteArrayInputStream(bos.toByteArray());
-                            InputStream is = 
GZIPHelper.uncompressGzip(ce.getValue(), bis);
-                            data = new String(is.readAllBytes());
-                            IOHelper.close(is);
-                        } else {
-                            data = bos.toString();
+                        ContentType ct = null;
+                        if (e.getContentType() != null) {
+                            ct = ContentType.parse(e.getContentType());
                         }
-                        if (data.length() > maxChars) {
-                            data = data.substring(0, maxChars) + " ... [Body 
clipped after " + maxChars
-                                   + " chars, total length is " + 
data.length() + "]";
+                        boolean accepted;
+                        if (showBinary || ct == null) {
+                            accepted = true;
+                        } else {
+                            // we do not want to show binary content
+                            accepted = !isBinaryData(ct);
                         }
-                        lines.add(getValue(false, data));
-                        if (!e.isRepeatable()) {
-                            // need to re-create body as stream is EOL
-                            byte[] arr = bos.toByteArray();
-                            ContentType ct = null;
-                            if (e.getContentType() != null) {
-                                ct = ContentType.parse(e.getContentType());
+                        if (!accepted) {
+                            lines.add("WARN: Cannot log HTTP body because the 
body is binary");
+                        } else {
+                            Header ce = request != null
+                                    ? 
request.getHeader(HttpHeaders.CONTENT_ENCODING)
+                                    : 
response.getHeader(HttpHeaders.CONTENT_ENCODING);
+                            ByteArrayOutputStream bos = new 
ByteArrayOutputStream();
+                            e.writeTo(bos);
+                            String data;
+                            if (ce != null && 
GZIPHelper.isGzip(ce.getValue())) {
+                                ByteArrayInputStream bis = new 
ByteArrayInputStream(bos.toByteArray());
+                                InputStream is = 
GZIPHelper.uncompressGzip(ce.getValue(), bis);
+                                data = new String(is.readAllBytes());
+                                IOHelper.close(is);
+                            } else {
+                                data = bos.toString();
+                            }
+                            if (data.length() > maxChars) {
+                                data = data.substring(0, maxChars) + " ... 
[Body clipped after " + maxChars
+                                       + " chars, total length is " + 
data.length() + "]";
                             }
-                            e = new ByteArrayEntity(arr, ct);
-                            if (request instanceof HttpEntityContainer ec) {
-                                ec.setEntity(e);
-                            } else if (response instanceof HttpEntityContainer 
ec) {
-                                ec.setEntity(e);
+                            lines.add(getValue(false, data));
+                            if (!e.isRepeatable()) {
+                                // need to re-create body as stream is EOL
+                                byte[] arr = bos.toByteArray();
+                                e = new ByteArrayEntity(arr, ct);
+                                if (request instanceof HttpEntityContainer ec) 
{
+                                    ec.setEntity(e);
+                                } else if (response instanceof 
HttpEntityContainer ec) {
+                                    ec.setEntity(e);
+                                }
                             }
                         }
                     }
@@ -214,6 +228,19 @@ public class LoggingHttpActivityListener extends 
ServiceSupport implements Camel
         }
     }
 
+    /**
+     * Determine whether the content type is binary or not
+     */
+    protected boolean isBinaryData(ContentType ct) {
+        String t = ct.getMimeType();
+        if (t.contains("text") || t.contains("xml") || t.contains("json") || 
t.contains("multipart")
+                || t.contains("x-www-form-urlencoded")) {
+            return false;
+        }
+        // assume binary
+        return true;
+    }
+
     private CamelLogger getLogger(Object source, Exchange exchange) {
         String name = null;
         if (sourceLocationLoggerName) {
@@ -295,6 +322,14 @@ public class LoggingHttpActivityListener extends 
ServiceSupport implements Camel
         this.showStreams = showStreams;
     }
 
+    public boolean isShowBinary() {
+        return showBinary;
+    }
+
+    public void setShowBinary(boolean showBinary) {
+        this.showBinary = showBinary;
+    }
+
     public boolean isShowHeaders() {
         return showHeaders;
     }

Reply via email to