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

davsclaus pushed a commit to branch fix/CAMEL-24274
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 6074326a7cdaf05e7a44625a772f36936a999256
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jul 27 16:14:56 2026 +0200

    CAMEL-24274: camel-tui - Send Message uses HTTP for platform-http routes
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../dsl/jbang/core/commands/tui/ActionsPopup.java  |   2 +-
 .../jbang/core/commands/tui/SendMessagePopup.java  | 136 ++++++++++++++++++++-
 2 files changed, 135 insertions(+), 3 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ActionsPopup.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ActionsPopup.java
index c5aff66eb649..0319f66cafed 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ActionsPopup.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ActionsPopup.java
@@ -1180,7 +1180,7 @@ class ActionsPopup {
             setNotification("No routes available", true);
             return;
         }
-        sendMessagePopup.open(ctx, pid, info.name, info.routes, 
preSelectedRouteId, info.directory);
+        sendMessagePopup.open(ctx, pid, info.name, info.routes, 
preSelectedRouteId, info.directory, info.httpServer);
         preSelectedRouteId = null;
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SendMessagePopup.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SendMessagePopup.java
index 3125e4c6cc7e..56ae976f99d9 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SendMessagePopup.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SendMessagePopup.java
@@ -17,9 +17,17 @@
 package org.apache.camel.dsl.jbang.core.commands.tui;
 
 import java.io.File;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.ExecutorService;
 
@@ -67,6 +75,7 @@ class SendMessagePopup {
     private boolean sending;
     private String pid;
     private String integrationName;
+    private String httpServer;
     private List<RouteInfo> routes;
     private int selectedRouteIndex;
     private final TextAreaState bodyState = new TextAreaState("");
@@ -104,17 +113,18 @@ class SendMessagePopup {
     }
 
     void open(MonitorContext ctx, String pid, String name, List<RouteInfo> 
routes, String preSelectRouteId) {
-        open(ctx, pid, name, routes, preSelectRouteId, null);
+        open(ctx, pid, name, routes, preSelectRouteId, null, null);
     }
 
     void open(
             MonitorContext ctx, String pid, String name, List<RouteInfo> 
routes,
-            String preSelectRouteId, String sourceDirectory) {
+            String preSelectRouteId, String sourceDirectory, String 
httpServer) {
         if (pid == null || routes == null || routes.isEmpty()) {
             return;
         }
         this.pid = pid;
         this.integrationName = name;
+        this.httpServer = httpServer;
         this.routes = new ArrayList<>(routes);
         this.selectedRouteIndex = findSmartDefault(preSelectRouteId);
         this.bodyState.clear();
@@ -507,6 +517,18 @@ class SendMessagePopup {
         List<FormHelper.HeaderEntry> hdrs = headers != null ? new 
ArrayList<>(headers) : null;
         String routeId = route.routeId;
 
+        // platform-http routes are consumer-only so we send an HTTP request 
directly
+        if (route.from != null && route.from.startsWith("platform-http:") && 
httpServer != null) {
+            executor.execute(() -> {
+                try {
+                    doSendHttp(route, sendBody, hdrs, captureInOut, routeId);
+                } finally {
+                    sending = false;
+                }
+            });
+            return;
+        }
+
         executor.execute(() -> {
             try {
                 JsonObject root = new JsonObject();
@@ -627,6 +649,116 @@ class SendMessagePopup {
         });
     }
 
+    private void doSendHttp(
+            RouteInfo route, String body, List<FormHelper.HeaderEntry> hdrs,
+            boolean captureInOut, String routeId) {
+        try {
+            String path = extractPlatformHttpPath(route.from);
+            String baseUrl = httpServer.replace("0.0.0.0", "localhost");
+            String url = baseUrl + path;
+            String method = extractHttpMethod(route.from, body);
+
+            // read file content if body references a file
+            String sendBody = body;
+            if (sendBody != null && sendBody.startsWith("file:")) {
+                sendBody = Files.readString(Path.of(sendBody.substring(5)));
+            }
+
+            HttpClient client = HttpClient.newBuilder()
+                    .connectTimeout(Duration.ofSeconds(10))
+                    .build();
+
+            boolean hasBody = sendBody != null && !sendBody.isEmpty();
+            HttpRequest.BodyPublisher bodyPublisher = hasBody
+                    ? HttpRequest.BodyPublishers.ofString(sendBody)
+                    : HttpRequest.BodyPublishers.noBody();
+
+            HttpRequest.Builder reqBuilder = HttpRequest.newBuilder()
+                    .uri(URI.create(url))
+                    .timeout(Duration.ofSeconds(20))
+                    .method(method, bodyPublisher);
+
+            if (hdrs != null) {
+                for (FormHelper.HeaderEntry he : hdrs) {
+                    String k = he.keyInput().text().trim();
+                    String v = he.valueInput().text();
+                    if (!k.isEmpty()) {
+                        reqBuilder.header(k, v);
+                    }
+                }
+            }
+
+            long start = System.currentTimeMillis();
+            HttpResponse<String> response = client.send(reqBuilder.build(),
+                    HttpResponse.BodyHandlers.ofString());
+            long elapsed = System.currentTimeMillis() - start;
+
+            int httpStatus = response.statusCode();
+            boolean error = httpStatus >= 400;
+
+            List<String> hdrLines = new ArrayList<>();
+            hdrLines.add("HTTP " + method + " " + url);
+            hdrLines.add("status: " + httpStatus);
+
+            if (captureInOut) {
+                for (Map.Entry<String, List<String>> entry : 
response.headers().map().entrySet()) {
+                    String k = entry.getKey();
+                    if (k == null || k.startsWith(":")) {
+                        continue;
+                    }
+                    for (String v : entry.getValue()) {
+                        hdrLines.add(k + ": " + v);
+                    }
+                }
+            }
+
+            String rawBody = captureInOut ? response.body() : null;
+
+            applyResult(routeId, body, hdrs, captureInOut,
+                    String.valueOf(httpStatus), elapsed, null, hdrLines, 
rawBody,
+                    error, error ? "HTTP " + httpStatus : null);
+        } catch (Exception e) {
+            applyResult(routeId, body, hdrs, captureInOut,
+                    null, 0, null, null, null,
+                    true, "Error: " + e.getMessage());
+        }
+    }
+
+    private static String extractPlatformHttpPath(String fromUri) {
+        // platform-http:///path?opts or platform-http:/path?opts
+        String path = fromUri.substring("platform-http:".length());
+        // strip query parameters
+        int q = path.indexOf('?');
+        if (q >= 0) {
+            path = path.substring(0, q);
+        }
+        // strip leading slashes from scheme separator (platform-http:///path 
-> /path)
+        while (path.startsWith("//")) {
+            path = path.substring(1);
+        }
+        if (!path.startsWith("/")) {
+            path = "/" + path;
+        }
+        return path;
+    }
+
+    private static String extractHttpMethod(String fromUri, String body) {
+        int q = fromUri.indexOf('?');
+        if (q >= 0) {
+            String query = fromUri.substring(q + 1);
+            for (String param : query.split("&")) {
+                if (param.startsWith("httpMethodRestrict=")) {
+                    String methods = 
param.substring("httpMethodRestrict=".length());
+                    // take the first method if comma-separated
+                    int comma = methods.indexOf(',');
+                    return comma > 0 ? methods.substring(0, comma).trim() : 
methods.trim();
+                }
+            }
+        }
+        // default: POST if body is present, GET otherwise
+        return (body != null && !body.isEmpty()) ? "POST" : "GET";
+    }
+
     private void applyResult(
             String routeId, String body, List<FormHelper.HeaderEntry> hdrs, 
boolean wasInOut,
             String status, long elapsed, String exchangeId,

Reply via email to