You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2026/05/18 14:51:57 UTC
(camel) 07/39: TUI: add HTTP Services tab (REST DSL + Platform-HTTP unified view)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch feat/camel-tui
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 12f0ef22011b183aefe5b686f494a46c0407f09e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon May 18 10:06:08 2026 +0200
TUI: add HTTP Services tab (REST DSL + Platform-HTTP unified view)
New tab 9 "HTTP" shows all HTTP endpoints exposed by the selected
integration — both REST DSL service definitions and Platform-HTTP
bindings — in a unified table with a detail panel.
Layout:
- Server info row: binding address, REST/HTTP/Mgmt endpoint counts
- Table: METHOD (color-coded), PATH, PRODUCES, SOURCE, STATE
- Detail panel: full URL, consumes/produces, source type, in/out types,
description (REST DSL fields shown when applicable)
Method colors: GET=green, POST=yellow, PUT=cyan, DELETE=red, PATCH=orange
Data model:
- HttpEndpointInfo class with fields from both REST DSL and Platform-HTTP
- Parsed from "rests" and "platform-http" JSON sections in status file
- IntegrationInfo.httpEndpoints + httpServer fields added
Controls:
- s/S: sort by method/path/source (toggle, reverse)
- f: cycle filter — all / REST DSL only / Platform-HTTP only
- m: toggle management endpoint visibility (off by default)
Co-Authored-By: Claude Sonnet 4.6 <no...@anthropic.com>
---
.../dsl/jbang/core/commands/tui/CamelMonitor.java | 390 ++++++++++++++++++++-
1 file changed, 381 insertions(+), 9 deletions(-)
diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
index 5cef03fcc771..4bb2862a8527 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
@@ -31,6 +31,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -114,7 +115,7 @@ public class CamelMonitor extends CamelCommand {
private static final int MAX_ENDPOINT_CHART_POINTS = 60;
private static final int MAX_LOG_LINES = 3000;
private static final int MAX_TRACES = 200;
- private static final int NUM_TABS = 8;
+ private static final int NUM_TABS = 9;
// Tab indices
private static final int TAB_OVERVIEW = 0;
@@ -125,6 +126,7 @@ public class CamelMonitor extends CamelCommand {
private static final int TAB_HEALTH = 5;
private static final int TAB_HISTORY = 6;
private static final int TAB_CIRCUIT_BREAKER = 7;
+ private static final int TAB_HTTP = 8;
// Overview sort columns
private static final String[] OVERVIEW_SORT_COLUMNS = { "pid", "name", "version", "status", "total", "fail" };
@@ -141,6 +143,9 @@ public class CamelMonitor extends CamelCommand {
// Circuit breaker sort columns (order matches table column order)
private static final String[] CB_SORT_COLUMNS = { "route", "id", "component", "state" };
+ // HTTP sort columns
+ private static final String[] HTTP_SORT_COLUMNS = { "method", "path", "source" };
+
@CommandLine.Parameters(description = "Name or pid of running Camel integration", arity = "0..1")
String name = "*";
@@ -158,6 +163,7 @@ public class CamelMonitor extends CamelCommand {
private final TableState healthTableState = new TableState();
private final TableState endpointTableState = new TableState();
private final TableState cbTableState = new TableState();
+ private final TableState httpTableState = new TableState();
private final TableState processorTableState = new TableState();
private final TableState routeHeaderTableState = new TableState();
private final TabsState tabsState = new TabsState(TAB_OVERVIEW);
@@ -222,6 +228,14 @@ public class CamelMonitor extends CamelCommand {
private int cbSortIndex = 0;
private boolean cbSortReversed;
+ // HTTP tab sort/filter state
+ private String httpSort = "method";
+ private int httpSortIndex = 0;
+ private boolean httpSortReversed;
+ // httpFilter: 0=all, 1=REST DSL only, 2=Platform-HTTP only
+ private int httpFilter;
+ private boolean httpShowManagement;
+
// Health filter state
private boolean showOnlyDown;
@@ -420,6 +434,9 @@ public class CamelMonitor extends CamelCommand {
if (ke.isChar('8')) {
return handleTabKey(TAB_CIRCUIT_BREAKER);
}
+ if (ke.isChar('9')) {
+ return handleTabKey(TAB_HTTP);
+ }
// Tab cycling
if (ke.isFocusNext()) {
@@ -585,6 +602,26 @@ public class CamelMonitor extends CamelCommand {
return true;
}
+ // HTTP tab: sort, filter, management toggle
+ if (tab == TAB_HTTP && ke.isChar('s')) {
+ httpSortIndex = (httpSortIndex + 1) % HTTP_SORT_COLUMNS.length;
+ httpSort = HTTP_SORT_COLUMNS[httpSortIndex];
+ httpSortReversed = false;
+ return true;
+ }
+ if (tab == TAB_HTTP && ke.isChar('S')) {
+ httpSortReversed = !httpSortReversed;
+ return true;
+ }
+ if (tab == TAB_HTTP && ke.isCharIgnoreCase('f')) {
+ httpFilter = (httpFilter + 1) % 3;
+ return true;
+ }
+ if (tab == TAB_HTTP && ke.isCharIgnoreCase('m')) {
+ httpShowManagement = !httpShowManagement;
+ return true;
+ }
+
// Endpoints tab: sort and filter
if (tab == TAB_ENDPOINTS && ke.isChar('s')) {
endpointSortIndex = (endpointSortIndex + 1) % ENDPOINT_SORT_COLUMNS.length;
@@ -969,6 +1006,7 @@ public class CamelMonitor extends CamelCommand {
}
case TAB_ROUTES -> routeTableState.selectPrevious();
case TAB_CIRCUIT_BREAKER -> cbTableState.selectPrevious();
+ case TAB_HTTP -> httpTableState.selectPrevious();
case TAB_LOG -> {
logFollowMode = false;
logScroll = Math.max(0, logScroll - 1);
@@ -1004,6 +1042,10 @@ public class CamelMonitor extends CamelCommand {
IntegrationInfo info = findSelectedIntegration();
cbTableState.selectNext(info != null ? info.circuitBreakers.size() : 0);
}
+ case TAB_HTTP -> {
+ List<HttpEndpointInfo> visible = visibleHttpEndpoints(findSelectedIntegration());
+ httpTableState.selectNext(visible.size());
+ }
case TAB_LOG -> logScroll++;
case TAB_HISTORY -> {
if (!traces.get().isEmpty()) {
@@ -1090,6 +1132,7 @@ public class CamelMonitor extends CamelCommand {
? sel.healthChecks.stream().filter(hc -> "DOWN".equals(hc.state)).count() : 0;
int historyCount = hasSelection ? historyEntries.size() : 0;
boolean hasTraces = hasSelection && !traces.get().isEmpty();
+ int httpCount = hasSelection ? sel.httpEndpoints.size() : 0;
// Row 0: label-only titles — fixed width so the tab bar never shifts when badges appear
Line[] labels = {
@@ -1101,6 +1144,7 @@ public class CamelMonitor extends CamelCommand {
Line.from(" 6 Health "),
Line.from(" 7 Inspect "),
Line.from(" 8 Circuit Breaker "),
+ Line.from(" 9 HTTP "),
};
Tabs tabs = Tabs.builder()
@@ -1120,7 +1164,7 @@ public class CamelMonitor extends CamelCommand {
int badgeY = area.y();
int dividerW = CharWidth.of(" | ");
- String[] badgeTexts = { "", "", "", "", "", "", "", "" };
+ String[] badgeTexts = { "", "", "", "", "", "", "", "", "" };
Style[] badgeStyles = new Style[labels.length];
Style yellow = Style.EMPTY.fg(Color.YELLOW).bold();
Style cyan = Style.EMPTY.fg(Color.CYAN).bold();
@@ -1161,6 +1205,9 @@ public class CamelMonitor extends CamelCommand {
} else if (cbCount > 0) {
badgeTexts[7] = "(" + cbCount + ")";
}
+ if (httpCount > 0) {
+ badgeTexts[8] = "(" + httpCount + ")";
+ }
int tabX = 0;
for (int i = 0; i < labels.length; i++) {
@@ -1192,6 +1239,7 @@ public class CamelMonitor extends CamelCommand {
case TAB_HEALTH -> renderHealth(frame, area);
case TAB_LOG -> renderLog(frame, area);
case TAB_HISTORY -> renderInspect(frame, area);
+ case TAB_HTTP -> renderHttp(frame, area);
}
}
@@ -3426,6 +3474,233 @@ public class CamelMonitor extends CamelCommand {
return entry;
}
+ // ---- Tab 9: HTTP Services ----
+
+ private List<HttpEndpointInfo> visibleHttpEndpoints(IntegrationInfo info) {
+ if (info == null) {
+ return Collections.emptyList();
+ }
+ List<HttpEndpointInfo> result = new ArrayList<>();
+ for (HttpEndpointInfo ep : info.httpEndpoints) {
+ if (ep.management && !httpShowManagement) {
+ continue;
+ }
+ if (httpFilter == 1 && !ep.fromRest) {
+ continue;
+ }
+ if (httpFilter == 2 && ep.fromRest) {
+ continue;
+ }
+ result.add(ep);
+ }
+ return result;
+ }
+
+ private void renderHttp(Frame frame, Rect area) {
+ IntegrationInfo info = findSelectedIntegration();
+ if (info == null) {
+ renderNoSelection(frame, area);
+ return;
+ }
+
+ List<HttpEndpointInfo> visible = visibleHttpEndpoints(info);
+
+ // Sort
+ visible.sort((a, b) -> {
+ int result = switch (httpSort) {
+ case "path" -> {
+ String pa = a.path != null ? a.path : "";
+ String pb = b.path != null ? b.path : "";
+ yield pa.compareToIgnoreCase(pb);
+ }
+ case "source" -> Boolean.compare(b.fromRest, a.fromRest);
+ default -> { // method
+ String ma = a.method != null ? a.method : "";
+ String mb = b.method != null ? b.method : "";
+ yield ma.compareToIgnoreCase(mb);
+ }
+ };
+ return httpSortReversed ? -result : result;
+ });
+
+ // Layout: server info row (1) + table (fill) + detail (10)
+ List<Rect> chunks = Layout.vertical()
+ .constraints(Constraint.length(1), Constraint.fill(), Constraint.length(10))
+ .split(area);
+
+ // Server info row
+ renderHttpServerInfo(frame, chunks.get(0), info, visible);
+
+ // Table
+ renderHttpTable(frame, chunks.get(1), visible);
+
+ // Detail panel
+ renderHttpDetail(frame, chunks.get(2), visible);
+ }
+
+ private void renderHttpServerInfo(Frame frame, Rect area, IntegrationInfo info, List<HttpEndpointInfo> visible) {
+ List<Span> spans = new ArrayList<>();
+ if (info.httpServer != null) {
+ spans.add(Span.styled(" Server: ", Style.EMPTY.fg(Color.YELLOW).bold()));
+ spans.add(Span.styled(info.httpServer, Style.EMPTY.fg(Color.CYAN)));
+ spans.add(Span.raw(" "));
+ }
+ long restCount = info.httpEndpoints.stream().filter(e -> e.fromRest).count();
+ long httpCount = info.httpEndpoints.stream().filter(e -> !e.fromRest && !e.management).count();
+ long mgmtCount = info.httpEndpoints.stream().filter(e -> e.management).count();
+ if (restCount > 0) {
+ spans.add(Span.styled("REST: ", Style.EMPTY.fg(Color.GREEN)));
+ spans.add(Span.raw(restCount + " "));
+ }
+ if (httpCount > 0) {
+ spans.add(Span.styled("HTTP: ", Style.EMPTY.fg(Color.CYAN)));
+ spans.add(Span.raw(httpCount + " "));
+ }
+ if (mgmtCount > 0) {
+ spans.add(Span.styled("Mgmt: ", Style.EMPTY.fg(Color.YELLOW).dim()));
+ spans.add(Span.raw(mgmtCount + ""));
+ }
+ frame.renderWidget(Paragraph.from(Line.from(spans)), area);
+ }
+
+ private static Style methodStyle(String method) {
+ if (method == null) {
+ return Style.EMPTY;
+ }
+ // Use first verb if comma-separated
+ String m = method.split(",")[0].trim().toUpperCase(Locale.ENGLISH);
+ return switch (m) {
+ case "GET" -> Style.EMPTY.fg(Color.GREEN);
+ case "POST" -> Style.EMPTY.fg(Color.YELLOW);
+ case "PUT" -> Style.EMPTY.fg(Color.CYAN);
+ case "DELETE" -> Style.EMPTY.fg(Color.LIGHT_RED);
+ case "PATCH" -> Style.EMPTY.fg(Color.rgb(0xFF, 0x80, 0x00));
+ default -> Style.EMPTY.dim();
+ };
+ }
+
+ private void renderHttpTable(Frame frame, Rect area, List<HttpEndpointInfo> visible) {
+ List<Row> rows = new ArrayList<>();
+ for (HttpEndpointInfo ep : visible) {
+ String method = ep.method != null ? ep.method : "";
+ String path = ep.path != null ? ep.path : (ep.url != null ? ep.url : "");
+ String produces = ep.produces != null ? ep.produces : "";
+ String source;
+ if (ep.management) {
+ source = "Mgmt";
+ } else if (ep.fromRest) {
+ source = ep.contractFirst ? "REST(contract)" : "REST(code)";
+ } else {
+ source = "HTTP";
+ }
+ String state = ep.state != null ? ep.state : "";
+ rows.add(Row.from(
+ Cell.from(Span.styled(method, methodStyle(method))),
+ Cell.from(path),
+ Cell.from(produces),
+ Cell.from(Span.styled(source,
+ ep.fromRest ? Style.EMPTY.fg(Color.GREEN) : Style.EMPTY.fg(Color.CYAN))),
+ Cell.from(Span.styled(state,
+ "Stopped".equals(state) ? Style.EMPTY.fg(Color.LIGHT_RED) : Style.EMPTY))));
+ }
+
+ String sortLabel = httpSort + (httpSortReversed ? " ↓" : " ↑");
+ String title = String.format(" HTTP Services [%d] sort:%s ", visible.size(), sortLabel);
+
+ Row header = Row.from(
+ Cell.from(Span.styled("METHOD", Style.EMPTY.bold())),
+ Cell.from(Span.styled("PATH", Style.EMPTY.bold())),
+ Cell.from(Span.styled("PRODUCES", Style.EMPTY.bold())),
+ Cell.from(Span.styled("SOURCE", Style.EMPTY.bold())),
+ Cell.from(Span.styled("STATE", Style.EMPTY.bold())));
+
+ Table table = Table.builder()
+ .rows(rows)
+ .header(header)
+ .widths(
+ Constraint.length(14),
+ Constraint.fill(),
+ Constraint.length(24),
+ Constraint.length(15),
+ Constraint.length(8))
+ .highlightStyle(Style.EMPTY.fg(Color.WHITE).bold().onBlue())
+ .highlightSpacing(Table.HighlightSpacing.ALWAYS)
+ .block(Block.builder().borderType(BorderType.ROUNDED).title(title).build())
+ .build();
+
+ frame.renderStatefulWidget(table, area, httpTableState);
+ }
+
+ private void renderHttpDetail(Frame frame, Rect area, List<HttpEndpointInfo> visible) {
+ Integer sel = httpTableState.selected();
+ if (sel == null || sel < 0 || sel >= visible.size()) {
+ frame.renderWidget(
+ Paragraph.builder()
+ .text(Text.from(Line.from(
+ Span.styled(" Select an endpoint to view details",
+ Style.EMPTY.dim()))))
+ .block(Block.builder().borderType(BorderType.ROUNDED)
+ .title(" Detail ").build())
+ .build(),
+ area);
+ return;
+ }
+
+ HttpEndpointInfo ep = visible.get(sel);
+ List<Span> titleSpans = new ArrayList<>();
+ if (ep.method != null) {
+ titleSpans.add(Span.raw(" "));
+ titleSpans.add(Span.styled(ep.method, methodStyle(ep.method).bold()));
+ titleSpans.add(Span.raw(" "));
+ }
+ if (ep.path != null) {
+ titleSpans.add(Span.raw(ep.path + " "));
+ }
+ Title detailTitle = Title.from(Line.from(titleSpans));
+
+ List<Line> lines = new ArrayList<>();
+ addDetailLine(lines, "URL", ep.url);
+ addDetailLine(lines, "Consumes", ep.consumes);
+ addDetailLine(lines, "Produces", ep.produces);
+ String sourceStr;
+ if (ep.management) {
+ sourceStr = "Platform-HTTP (management)";
+ } else if (ep.fromRest) {
+ sourceStr = "REST DSL (" + (ep.contractFirst ? "contract-first" : "code-first") + ")";
+ } else {
+ sourceStr = "Platform-HTTP";
+ }
+ addDetailLine(lines, "Source", sourceStr);
+ if (ep.state != null) {
+ addDetailLine(lines, "State", ep.state);
+ }
+ if (ep.inType != null) {
+ addDetailLine(lines, "In type", ep.inType);
+ }
+ if (ep.outType != null) {
+ addDetailLine(lines, "Out type", ep.outType);
+ }
+ if (ep.description != null) {
+ addDetailLine(lines, "Desc", ep.description);
+ }
+
+ frame.renderWidget(
+ Paragraph.builder()
+ .text(Text.from(lines))
+ .block(Block.builder().borderType(BorderType.ROUNDED).title(detailTitle).build())
+ .build(),
+ area);
+ }
+
+ private static void addDetailLine(List<Line> lines, String label, String value) {
+ if (value == null || value.isEmpty()) {
+ return;
+ }
+ lines.add(Line.from(
+ Span.styled(String.format(" %-10s ", label + ":"), Style.EMPTY.fg(Color.YELLOW).bold()),
+ Span.raw(value)));
+ }
+
// ---- Tab 7: Inspect (merged Last + Tracer) ----
private void renderInspect(Frame frame, Rect area) {
@@ -4019,7 +4294,7 @@ public class CamelMonitor extends CamelCommand {
hint(spans, "p", selInfo.routeStarted > 0 ? "stop" : "start");
}
}
- hint(spans, "1-8", "tabs");
+ hint(spans, "1-9", "tabs");
} else if (tab == TAB_ROUTES && showSource) {
hint(spans, "c/Esc", "close");
hint(spans, "\u2191\u2193\u2190\u2192", "scroll");
@@ -4059,27 +4334,27 @@ public class CamelMonitor extends CamelCommand {
} else if (routeState != null) {
hint(spans, "p", "start");
}
- hint(spans, "1-8", "tabs");
+ hint(spans, "1-9", "tabs");
} else if (tab == TAB_CONSUMERS) {
hint(spans, "Esc", "back");
hint(spans, "s", "sort");
- hint(spans, "1-8", "tabs");
+ hint(spans, "1-9", "tabs");
} else if (tab == TAB_ENDPOINTS) {
hint(spans, "Esc", "back");
hint(spans, "s", "sort");
String[] filterLabels = { "all", "remote", "remote+stub" };
hint(spans, "f", "filter [" + filterLabels[endpointFilter] + "]");
hint(spans, "a", "chart " + (showEndpointChart ? "[all]" : "[off]"));
- hint(spans, "1-8", "tabs");
+ hint(spans, "1-9", "tabs");
} else if (tab == TAB_CIRCUIT_BREAKER) {
hint(spans, "Esc", "back");
hint(spans, "\u2191\u2193", "navigate");
hint(spans, "s", "sort");
- hint(spans, "1-8", "tabs");
+ hint(spans, "1-9", "tabs");
} else if (tab == TAB_HEALTH) {
hint(spans, "Esc", "back");
hint(spans, "d", "toggle DOWN");
- hint(spans, "1-8", "tabs");
+ hint(spans, "1-9", "tabs");
} else if (tab == TAB_LOG && showLogLevelPopup) {
hint(spans, "\u2191\u2193", "navigate");
hint(spans, "Enter", "set level");
@@ -4095,6 +4370,13 @@ public class CamelMonitor extends CamelCommand {
}
hint(spans, "l", "level");
hintLast(spans, "f", "follow" + (logFollowMode ? " [on]" : " [off]"));
+ } else if (tab == TAB_HTTP) {
+ hint(spans, "Esc", "back");
+ hint(spans, "↑↓", "navigate");
+ hint(spans, "s", "sort");
+ String[] filterLabels = { "all", "rest", "http" };
+ hint(spans, "f", "filter [" + filterLabels[httpFilter] + "]");
+ hintLast(spans, "m", "management" + (httpShowManagement ? " [on]" : " [off]"));
} else if (tab == TAB_HISTORY) {
boolean tracerActive = !traces.get().isEmpty();
if (tracerActive && traceDetailView) {
@@ -4132,7 +4414,7 @@ public class CamelMonitor extends CamelCommand {
} else {
hint(spans, "Esc", "back");
hint(spans, "\u2191\u2193", "navigate");
- hint(spans, "1-8", "tabs");
+ hint(spans, "1-9", "tabs");
}
frame.renderWidget(Paragraph.from(Line.from(spans)), area);
@@ -5098,9 +5380,78 @@ public class CamelMonitor extends CamelCommand {
parseCbSection(root, "fault-tolerance", info);
parseCbSection(root, "circuit-breaker", info);
+ // Parse REST DSL services
+ JsonObject restsObj = (JsonObject) root.get("rests");
+ if (restsObj != null) {
+ JsonArray restList = (JsonArray) restsObj.get("rests");
+ if (restList != null) {
+ for (Object r : restList) {
+ JsonObject rj = (JsonObject) r;
+ HttpEndpointInfo ep = new HttpEndpointInfo();
+ ep.fromRest = true;
+ ep.url = rj.getString("url");
+ ep.method = rj.getString("method");
+ if (ep.method != null) {
+ ep.method = ep.method.toUpperCase(Locale.ENGLISH);
+ }
+ ep.consumes = rj.getString("consumes");
+ ep.produces = rj.getString("produces");
+ ep.description = rj.getString("description");
+ ep.contractFirst = Boolean.TRUE.equals(rj.get("contractFirst"));
+ ep.state = rj.getString("state");
+ ep.inType = rj.getString("inType");
+ ep.outType = rj.getString("outType");
+ // derive path from url (strip scheme+host+port)
+ ep.path = extractPath(ep.url);
+ info.httpEndpoints.add(ep);
+ }
+ }
+ }
+
+ // Parse Platform-HTTP services
+ JsonObject phpObj = (JsonObject) root.get("platform-http");
+ if (phpObj != null) {
+ info.httpServer = phpObj.getString("server");
+ parseHttpEndpoints(phpObj, "endpoints", false, info);
+ parseHttpEndpoints(phpObj, "managementEndpoints", true, info);
+ }
+
return info;
}
+ private static void parseHttpEndpoints(JsonObject phpObj, String key, boolean management, IntegrationInfo info) {
+ JsonArray arr = (JsonArray) phpObj.get(key);
+ if (arr == null) {
+ return;
+ }
+ for (Object e : arr) {
+ JsonObject ej = (JsonObject) e;
+ HttpEndpointInfo ep = new HttpEndpointInfo();
+ ep.fromRest = false;
+ ep.management = management;
+ ep.server = phpObj.getString("server");
+ ep.url = ej.getString("url");
+ ep.path = ej.getString("path");
+ ep.method = ej.getString("verbs");
+ ep.consumes = ej.getString("consumes");
+ ep.produces = ej.getString("produces");
+ info.httpEndpoints.add(ep);
+ }
+ }
+
+ private static String extractPath(String url) {
+ if (url == null) {
+ return null;
+ }
+ // strip scheme://host:port prefix — find third '/' or return url as-is
+ int idx = url.indexOf("://");
+ if (idx < 0) {
+ return url;
+ }
+ int slash = url.indexOf('/', idx + 3);
+ return slash >= 0 ? url.substring(slash) : "/";
+ }
+
private static void parseCbSection(JsonObject root, String key, IntegrationInfo info) {
JsonObject section = (JsonObject) root.get(key);
if (section == null) {
@@ -5291,6 +5642,8 @@ public class CamelMonitor extends CamelCommand {
final List<HealthCheckInfo> healthChecks = new ArrayList<>();
final List<EndpointInfo> endpoints = new ArrayList<>();
final List<CircuitBreakerInfo> circuitBreakers = new ArrayList<>();
+ final List<HttpEndpointInfo> httpEndpoints = new ArrayList<>();
+ String httpServer; // platform-http server binding, e.g. http://0.0.0.0:8080
}
static class RouteInfo {
@@ -5373,6 +5726,25 @@ public class CamelMonitor extends CamelCommand {
double failureRate; // -1 means not available
}
+ // HTTP endpoint from REST DSL or Platform-HTTP
+ static class HttpEndpointInfo {
+ String method; // HTTP method(s), e.g. "GET" or "GET,POST"
+ String path; // URI path, e.g. /api/orders
+ String url; // full URL including server
+ String consumes;
+ String produces;
+ // REST DSL only
+ boolean fromRest;
+ boolean contractFirst;
+ String description;
+ String inType;
+ String outType;
+ String state;
+ // Platform-HTTP only
+ boolean management;
+ String server; // e.g. http://0.0.0.0:8080
+ }
+
static class TraceEntry {
String pid;
String uid;