@@ -70,7 +70,8 @@ isolated function getHeartbeat() returns Heartbeat|error {
7070 main : check getMainArtifact ()
7171 },
7272 logLevels : getLogLevels (),
73- workflowCallbackUrl : enableWorkflowManagement ? getWorkflowCallbackUrl () : ()
73+ workflowCallbackUrl : enableWorkflowManagement ? getWorkflowCallbackUrl () : (),
74+ tryItHost : getTryItHost ()
7475 };
7576
7677 // Add runtime only if not empty
@@ -96,7 +97,8 @@ isolated function getHeartbeat() returns Heartbeat|error {
9697 runtimeHash : runtimeHash ,
9798 timestamp : time :utcNow (),
9899 logLevels : heartbeatForHash .logLevels ,
99- workflowCallbackUrl : heartbeatForHash ?.workflowCallbackUrl
100+ workflowCallbackUrl : heartbeatForHash ?.workflowCallbackUrl ,
101+ tryItHost : heartbeatForHash ?.tryItHost
100102 };
101103
102104 // Add runtime only if not empty
@@ -191,7 +193,11 @@ isolated function getMainArtifact() returns MainDetail?|error =
191193 'class : " io.ballerina.lib.wso2.icp.Artifacts"
192194} external ;
193195
194- isolated function getWorkflowCallbackUrl() returns string {
196+ // Strips trailing slashes and any path segment from the configured runtimeHostUrl, returning
197+ // both the cleaned scheme+host[:port] and the bare authority (host[:port], no scheme) — shared
198+ // by getWorkflowCallbackUrl (needs the scheme, to build a callable base URL) and getTryItHost
199+ // (needs just the host, since the Try-It proxy already knows the target port separately).
200+ isolated function getConfiguredHostUrl() returns [string , string ] {
195201 string hostUrl = runtimeHostUrl .trim ();
196202 // Strip trailing slashes to avoid a malformed "http://host/:port".
197203 while hostUrl .endsWith (" /" ) {
@@ -204,7 +210,13 @@ isolated function getWorkflowCallbackUrl() returns string {
204210 int ? pathIndex = authority .indexOf (" /" );
205211 if pathIndex is int {
206212 authority = authority .substring (0 , pathIndex );
213+ hostUrl = hostUrl .substring (0 , authorityStart ) + authority ;
207214 }
215+ return [hostUrl , authority ];
216+ }
217+
218+ isolated function getWorkflowCallbackUrl() returns string {
219+ var [hostUrl , authority ] = getConfiguredHostUrl ();
208220 // If runtimeHostUrl already includes a port, use it as-is rather than
209221 // appending the management port and producing "host:8080:9090".
210222 if authority .includes (" :" ) {
@@ -213,6 +225,15 @@ isolated function getWorkflowCallbackUrl() returns string {
213225 return string ` ${hostUrl }:${workflowManagementApiPort }` ;
214226}
215227
228+ // Bare, reachable host/IP for this runtime (no scheme, no port) reported in every heartbeat so
229+ // the ICP server can route Try-It proxy requests to it — the per-listener host captured
230+ // separately (Listeners.java) is often a bind-all address like 0.0.0.0, not a usable target.
231+ isolated function getTryItHost() returns string {
232+ var [_ , authority ] = getConfiguredHostUrl ();
233+ int ? portIndex = authority .indexOf (" :" );
234+ return portIndex is int ? authority.substring(0 , portIndex) : authority ;
235+ }
236+
216237isolated function stopListenerArtifact(string name ) returns boolean | error =
217238@java :Method {
218239 'class : " io.ballerina.lib.wso2.icp.Artifacts"
0 commit comments