fix(server): serve draft-version requests statelessly per SEP-2567 (#999)
* fix(server): serve draft-version requests statelessly per SEP-2567 * refactor: address PR feedback * refactor!: rename stateful_mode to legacy_session_mode * fix: address PR feedback
This commit is contained in:
parent
7abbf29e93
commit
a5bb51c9d2
9 changed files with 103 additions and 34 deletions
|
|
@ -54,7 +54,7 @@ async fn discover_http_client_bootstraps_headers_without_initialize() {
|
|||
|| Ok(DiscoverHttpServer),
|
||||
Default::default(),
|
||||
StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(false)
|
||||
.with_legacy_session_mode(false)
|
||||
.with_json_response(true)
|
||||
.with_cancellation_token(ct.child_token()),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -32,16 +32,16 @@ impl ServerHandler for DiscoveryServer {
|
|||
}
|
||||
|
||||
async fn spawn_server(json_response: bool) -> (reqwest::Client, String, CancellationToken) {
|
||||
spawn_server_with_stateful_mode(json_response, false).await
|
||||
spawn_server_with_legacy_session_mode(json_response, false).await
|
||||
}
|
||||
|
||||
async fn spawn_server_with_stateful_mode(
|
||||
async fn spawn_server_with_legacy_session_mode(
|
||||
json_response: bool,
|
||||
stateful_mode: bool,
|
||||
legacy_session_mode: bool,
|
||||
) -> (reqwest::Client, String, CancellationToken) {
|
||||
let cancellation_token = CancellationToken::new();
|
||||
let config = StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(stateful_mode)
|
||||
.with_legacy_session_mode(legacy_session_mode)
|
||||
.with_json_response(json_response)
|
||||
.with_sse_keep_alive(None)
|
||||
.with_cancellation_token(cancellation_token.clone());
|
||||
|
|
@ -136,8 +136,8 @@ async fn discover_returns_server_metadata_without_session() {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn discover_does_not_require_initialization_in_stateful_mode() {
|
||||
let (client, url, cancellation_token) = spawn_server_with_stateful_mode(true, true).await;
|
||||
async fn discover_does_not_require_initialization_in_legacy_session_mode() {
|
||||
let (client, url, cancellation_token) = spawn_server_with_legacy_session_mode(true, true).await;
|
||||
|
||||
let response = post_discover(&client, &url, "2025-11-25", Some("2025-11-25")).await;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use common::calculator::Calculator;
|
|||
|
||||
fn stateless_json_config() -> StreamableHttpServerConfig {
|
||||
StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(false)
|
||||
.with_legacy_session_mode(false)
|
||||
.with_json_response(true)
|
||||
.with_sse_keep_alive(None)
|
||||
.with_cancellation_token(CancellationToken::new())
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ async fn spawn_stateless_server(json_response: bool) -> anyhow::Result<TestServe
|
|||
|
||||
let server_ct = CancellationToken::new();
|
||||
let config = StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(false)
|
||||
.with_legacy_session_mode(false)
|
||||
.with_json_response(json_response)
|
||||
// A short keep-alive lets the SSE server notice a dropped connection
|
||||
// quickly (hyper only observes the disconnect on its next write).
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ async fn stateless_json_response_returns_application_json() -> anyhow::Result<()
|
|||
let ct = CancellationToken::new();
|
||||
let (client, url, ct) = spawn_server(
|
||||
StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(false)
|
||||
.with_legacy_session_mode(false)
|
||||
.with_json_response(true)
|
||||
.with_sse_keep_alive(None)
|
||||
.with_cancellation_token(ct.child_token()),
|
||||
|
|
@ -145,7 +145,7 @@ async fn stateless_json_response_falls_back_to_sse_for_progress() -> anyhow::Res
|
|||
let ct = CancellationToken::new();
|
||||
let (client, url, ct) = spawn_progress_server(
|
||||
StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(false)
|
||||
.with_legacy_session_mode(false)
|
||||
.with_json_response(true)
|
||||
.with_sse_keep_alive(None)
|
||||
.with_cancellation_token(ct.child_token()),
|
||||
|
|
@ -197,7 +197,7 @@ async fn stateless_sse_mode_default_unchanged() -> anyhow::Result<()> {
|
|||
let ct = CancellationToken::new();
|
||||
let (client, url, ct) = spawn_server(
|
||||
StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(false)
|
||||
.with_legacy_session_mode(false)
|
||||
.with_sse_keep_alive(None)
|
||||
.with_cancellation_token(ct.child_token()),
|
||||
)
|
||||
|
|
@ -234,9 +234,9 @@ async fn stateless_sse_mode_default_unchanged() -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn json_response_ignored_in_stateful_mode() -> anyhow::Result<()> {
|
||||
async fn json_response_ignored_in_legacy_session_mode() -> anyhow::Result<()> {
|
||||
let ct = CancellationToken::new();
|
||||
// json_response: true has no effect when stateful_mode: true — server still uses SSE
|
||||
// json_response: true has no effect when legacy_session_mode: true — server still uses SSE
|
||||
let (client, url, ct) = spawn_server(
|
||||
StreamableHttpServerConfig::default()
|
||||
.with_json_response(true)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use common::calculator::Calculator;
|
|||
async fn test_priming_on_stream_start() -> anyhow::Result<()> {
|
||||
let ct = CancellationToken::new();
|
||||
|
||||
// stateful_mode: true automatically enables priming with DEFAULT_RETRY_INTERVAL (3 seconds)
|
||||
// legacy_session_mode: true automatically enables priming with DEFAULT_RETRY_INTERVAL (3 seconds)
|
||||
let service: StreamableHttpService<Calculator, LocalSessionManager> =
|
||||
StreamableHttpService::new(
|
||||
|| Ok(Calculator::new()),
|
||||
|
|
@ -416,7 +416,7 @@ async fn test_priming_on_stream_close() -> anyhow::Result<()> {
|
|||
let ct = CancellationToken::new();
|
||||
let session_manager = Arc::new(LocalSessionManager::default());
|
||||
|
||||
// stateful_mode: true automatically enables priming with DEFAULT_RETRY_INTERVAL (3 seconds)
|
||||
// legacy_session_mode: true automatically enables priming with DEFAULT_RETRY_INTERVAL (3 seconds)
|
||||
let service = StreamableHttpService::new(
|
||||
|| Ok(Calculator::new()),
|
||||
session_manager.clone(),
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ async fn spawn_server_with_manager(
|
|||
|
||||
fn stateless_json_config() -> StreamableHttpServerConfig {
|
||||
StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(false)
|
||||
.with_legacy_session_mode(false)
|
||||
.with_json_response(true)
|
||||
.with_sse_keep_alive(None)
|
||||
.with_cancellation_token(CancellationToken::new())
|
||||
|
|
@ -58,7 +58,7 @@ fn stateless_json_config() -> StreamableHttpServerConfig {
|
|||
|
||||
fn stateful_config() -> StreamableHttpServerConfig {
|
||||
StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(true)
|
||||
.with_legacy_session_mode(true)
|
||||
.with_sse_keep_alive(None)
|
||||
.with_cancellation_token(CancellationToken::new())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ fn make_service(
|
|||
) -> StreamableHttpService<Calculator, LocalSessionManager> {
|
||||
StreamableHttpService::new(|| Ok(Calculator::new()), Default::default(), {
|
||||
let mut cfg = StreamableHttpServerConfig::default();
|
||||
cfg.stateful_mode = true;
|
||||
cfg.legacy_session_mode = true;
|
||||
cfg.sse_keep_alive = None;
|
||||
cfg.cancellation_token = ct.child_token();
|
||||
cfg.session_store = Some(session_store);
|
||||
|
|
@ -147,7 +147,7 @@ async fn test_session_state_deleted_from_store_on_delete() -> anyhow::Result<()>
|
|||
|
||||
let service = StreamableHttpService::new(|| Ok(Calculator::new()), session_manager.clone(), {
|
||||
let mut cfg = StreamableHttpServerConfig::default();
|
||||
cfg.stateful_mode = true;
|
||||
cfg.legacy_session_mode = true;
|
||||
cfg.sse_keep_alive = None;
|
||||
cfg.cancellation_token = ct.child_token();
|
||||
cfg.session_store = Some(store.clone());
|
||||
|
|
@ -219,7 +219,7 @@ fn spawn_server(
|
|||
) -> (std::net::SocketAddr, tokio::task::JoinHandle<()>) {
|
||||
let svc = StreamableHttpService::new(|| Ok(Calculator::new()), session_manager, {
|
||||
let mut cfg = StreamableHttpServerConfig::default();
|
||||
cfg.stateful_mode = true;
|
||||
cfg.legacy_session_mode = true;
|
||||
cfg.sse_keep_alive = None;
|
||||
cfg.cancellation_token = ct.child_token();
|
||||
cfg.session_store = session_store;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ impl ServerHandler for HeaderValidationServer {
|
|||
|
||||
async fn spawn_server() -> (reqwest::Client, String, CancellationToken) {
|
||||
let config = StreamableHttpServerConfig::default()
|
||||
.with_stateful_mode(false)
|
||||
.with_legacy_session_mode(false)
|
||||
.with_json_response(true)
|
||||
.with_sse_keep_alive(None)
|
||||
.with_cancellation_token(CancellationToken::new());
|
||||
|
|
|
|||
Loading…
Reference in a new issue