feat(webflux): Add base URL support to WebFluxSseServerTransportProvider (#102)
Adds the ability to specify a base URL prefix for message endpoints in the WebFlux SSE server transport provider. This enhancement allows for proper URL construction when the server is running behind a proxy or in a context with a base path. - Add new constructor with baseUrl parameter - Add basePath() method to Builder class - Modify SSE endpoint event to include baseUrl prefix Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
parent
0db4c0f70d
commit
3fa4152287
1 changed files with 58 additions and 17 deletions
|
|
@ -82,8 +82,16 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
|
|||
*/
|
||||
public static final String DEFAULT_SSE_ENDPOINT = "/sse";
|
||||
|
||||
public static final String DEFAULT_BASE_URL = "";
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Base URL for the message endpoint. This is used to construct the full URL for
|
||||
* clients to send their JSON-RPC messages.
|
||||
*/
|
||||
private final String baseUrl;
|
||||
|
||||
private final String messageEndpoint;
|
||||
|
||||
private final String sseEndpoint;
|
||||
|
|
@ -102,29 +110,6 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
|
|||
*/
|
||||
private volatile boolean isClosing = false;
|
||||
|
||||
/**
|
||||
* Constructs a new WebFlux SSE server transport provider instance.
|
||||
* @param objectMapper The ObjectMapper to use for JSON serialization/deserialization
|
||||
* of MCP messages. Must not be null.
|
||||
* @param messageEndpoint The endpoint URI where clients should send their JSON-RPC
|
||||
* messages. This endpoint will be communicated to clients during SSE connection
|
||||
* setup. Must not be null.
|
||||
* @throws IllegalArgumentException if either parameter is null
|
||||
*/
|
||||
public WebFluxSseServerTransportProvider(ObjectMapper objectMapper, String messageEndpoint, String sseEndpoint) {
|
||||
Assert.notNull(objectMapper, "ObjectMapper must not be null");
|
||||
Assert.notNull(messageEndpoint, "Message endpoint must not be null");
|
||||
Assert.notNull(sseEndpoint, "SSE endpoint must not be null");
|
||||
|
||||
this.objectMapper = objectMapper;
|
||||
this.messageEndpoint = messageEndpoint;
|
||||
this.sseEndpoint = sseEndpoint;
|
||||
this.routerFunction = RouterFunctions.route()
|
||||
.GET(this.sseEndpoint, this::handleSseConnection)
|
||||
.POST(this.messageEndpoint, this::handleMessage)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new WebFlux SSE server transport provider instance with the default
|
||||
* SSE endpoint.
|
||||
|
|
@ -139,6 +124,46 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
|
|||
this(objectMapper, messageEndpoint, DEFAULT_SSE_ENDPOINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new WebFlux SSE server transport provider instance.
|
||||
* @param objectMapper The ObjectMapper to use for JSON serialization/deserialization
|
||||
* of MCP messages. Must not be null.
|
||||
* @param messageEndpoint The endpoint URI where clients should send their JSON-RPC
|
||||
* messages. This endpoint will be communicated to clients during SSE connection
|
||||
* setup. Must not be null.
|
||||
* @throws IllegalArgumentException if either parameter is null
|
||||
*/
|
||||
public WebFluxSseServerTransportProvider(ObjectMapper objectMapper, String messageEndpoint, String sseEndpoint) {
|
||||
this(objectMapper, DEFAULT_BASE_URL, messageEndpoint, sseEndpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new WebFlux SSE server transport provider instance.
|
||||
* @param objectMapper The ObjectMapper to use for JSON serialization/deserialization
|
||||
* of MCP messages. Must not be null.
|
||||
* @param baseUrl webflux messag base path
|
||||
* @param messageEndpoint The endpoint URI where clients should send their JSON-RPC
|
||||
* messages. This endpoint will be communicated to clients during SSE connection
|
||||
* setup. Must not be null.
|
||||
* @throws IllegalArgumentException if either parameter is null
|
||||
*/
|
||||
public WebFluxSseServerTransportProvider(ObjectMapper objectMapper, String baseUrl, String messageEndpoint,
|
||||
String sseEndpoint) {
|
||||
Assert.notNull(objectMapper, "ObjectMapper must not be null");
|
||||
Assert.notNull(baseUrl, "Message base path must not be null");
|
||||
Assert.notNull(messageEndpoint, "Message endpoint must not be null");
|
||||
Assert.notNull(sseEndpoint, "SSE endpoint must not be null");
|
||||
|
||||
this.objectMapper = objectMapper;
|
||||
this.baseUrl = baseUrl;
|
||||
this.messageEndpoint = messageEndpoint;
|
||||
this.sseEndpoint = sseEndpoint;
|
||||
this.routerFunction = RouterFunctions.route()
|
||||
.GET(this.sseEndpoint, this::handleSseConnection)
|
||||
.POST(this.messageEndpoint, this::handleMessage)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionFactory(McpServerSession.Factory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
|
|
@ -179,7 +204,8 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
|
|||
.then();
|
||||
}
|
||||
|
||||
// FIXME: This javadoc makes claims about using isClosing flag but it's not actually
|
||||
// FIXME: This javadoc makes claims about using isClosing flag but it's not
|
||||
// actually
|
||||
// doing that.
|
||||
/**
|
||||
* Initiates a graceful shutdown of all the sessions. This method ensures all active
|
||||
|
|
@ -245,7 +271,7 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
|
|||
logger.debug("Sending initial endpoint event to session: {}", sessionId);
|
||||
sink.next(ServerSentEvent.builder()
|
||||
.event(ENDPOINT_EVENT_TYPE)
|
||||
.data(messageEndpoint + "?sessionId=" + sessionId)
|
||||
.data(this.baseUrl + this.messageEndpoint + "?sessionId=" + sessionId)
|
||||
.build());
|
||||
sink.onCancel(() -> {
|
||||
logger.debug("Session {} cancelled", sessionId);
|
||||
|
|
@ -360,6 +386,8 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
|
|||
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
private String baseUrl = DEFAULT_BASE_URL;
|
||||
|
||||
private String messageEndpoint;
|
||||
|
||||
private String sseEndpoint = DEFAULT_SSE_ENDPOINT;
|
||||
|
|
@ -377,6 +405,19 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the project basePath as endpoint prefix where clients should send their
|
||||
* JSON-RPC messages
|
||||
* @param baseUrl the message basePath . Must not be null.
|
||||
* @return this builder instance
|
||||
* @throws IllegalArgumentException if basePath is null
|
||||
*/
|
||||
public Builder basePath(String baseUrl) {
|
||||
Assert.notNull(baseUrl, "basePath must not be null");
|
||||
this.baseUrl = baseUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the endpoint URI where clients should send their JSON-RPC messages.
|
||||
* @param messageEndpoint The message endpoint URI. Must not be null.
|
||||
|
|
@ -411,7 +452,7 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
|
|||
Assert.notNull(objectMapper, "ObjectMapper must be set");
|
||||
Assert.notNull(messageEndpoint, "Message endpoint must be set");
|
||||
|
||||
return new WebFluxSseServerTransportProvider(objectMapper, messageEndpoint, sseEndpoint);
|
||||
return new WebFluxSseServerTransportProvider(objectMapper, baseUrl, messageEndpoint, sseEndpoint);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue