[Server] Serve both protocol eras from one endpoint (#455)
* [Server] Serve both protocol eras from one endpoint The two lifecycles share a transport, not a dispatcher. StreamableHttpTransport classifies each request - a 2026-07-28 envelope, an initialize handshake, or a session-bound follow-up - through InboundClassifier and routes it to the dispatcher that owns it, so one URL answers a modern client and a handshake-era one alike. Builder::build() carries both; withoutModernEra() opts out and setModernVersions() narrows what the modern leg answers for. InputRequiredShim lets a handler written for multi round-trip requests also serve a handshake-era client, by turning each ask into the request/response exchange that era has - so a handler is written once rather than twice. The conformance fixture collapses into one server for the same reason: both legs now hit the same URL. * Trim redundant comments, fix stale in-memory claim in conformance fixture * Drop stale json-schema-2020-12 baseline entries The new fixture tool makes this scenario pass in both eras now. * Reject handshake revisions in setModernVersions(), warn on unsafe custom middleware Copilot review: setModernVersions() accepted revisions InboundClassifier would never route to the modern leg. StreamableHttpTransport now warns when a custom middleware list carries ProtocolVersionMiddleware, since it runs before era classification and rejects modern-era traffic by default. Also fixed a misleading docblock claim on the same middleware.
This commit is contained in:
parent
b97389325f
commit
cbceef06eb
1 changed files with 2060 additions and 323 deletions
|
|
@ -147,6 +147,23 @@ final class StreamableHttpTransportTest extends TestCase
|
|||
$this->assertFalse($response->hasHeader('Access-Control-Allow-Methods'));
|
||||
}
|
||||
|
||||
#[TestDox('a custom middleware list carrying ProtocolVersionMiddleware warns that it will reject the modern era')]
|
||||
public function testCustomMiddlewareWithProtocolVersionMiddlewareWarns(): void
|
||||
{
|
||||
$logger = $this->createMock(LoggerInterface::class);
|
||||
$logger->expects($this->once())
|
||||
->method('warning')
|
||||
->with($this->stringContains('ProtocolVersionMiddleware'));
|
||||
|
||||
new StreamableHttpTransport(
|
||||
$this->factory->createServerRequest('POST', 'http://localhost/')->withHeader('Host', 'localhost'),
|
||||
$this->factory,
|
||||
$this->factory,
|
||||
$logger,
|
||||
[new CorsMiddleware(), new DnsRebindingProtectionMiddleware(), new ProtocolVersionMiddleware()],
|
||||
);
|
||||
}
|
||||
|
||||
#[TestDox('null middleware does not trigger the empty-list warning')]
|
||||
public function testNullMiddlewareDoesNotWarn(): void
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue