Skip to content

Commit a152386

Browse files
sveneldVolodymyr Panivko
authored andcommitted
Add Middleware handlers to StreamableHttpTransport
1 parent ba3ea56 commit a152386

File tree

2 files changed

+60
-35
lines changed

2 files changed

+60
-35
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the official PHP MCP SDK.
5+
*
6+
* A collaboration between Symfony and the PHP Foundation.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Mcp\Server\Transport\Http;
13+
14+
use Psr\Http\Message\ResponseInterface;
15+
use Psr\Http\Message\ServerRequestInterface;
16+
use Psr\Http\Server\MiddlewareInterface;
17+
use Psr\Http\Server\RequestHandlerInterface;
18+
19+
/**
20+
* A request handler that processes a middleware pipeline before dispatching
21+
* the request to the core transport handler.
22+
*
23+
* @author Volodymyr Panivko <sveneld300@gmail.com>
24+
* @internal
25+
*/
26+
class MiddlewareRequestHandler implements RequestHandlerInterface
27+
{
28+
/**
29+
* @param list<MiddlewareInterface> $middleware
30+
*/
31+
public function __construct(
32+
private array $middleware,
33+
private \Closure $application,
34+
) {
35+
}
36+
37+
public function handle(ServerRequestInterface $request): ResponseInterface
38+
{
39+
$middleware = array_shift($this->middleware);
40+
if (null === $middleware) {
41+
return ($this->application)($request);
42+
}
43+
44+
return $middleware->process($request, $this);
45+
}
46+
}

src/Server/Transport/StreamableHttpTransport.php

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
namespace Mcp\Server\Transport;
1313

1414
use Http\Discovery\Psr17FactoryDiscovery;
15+
use Mcp\Exception\InvalidArgumentException;
1516
use Mcp\Schema\JsonRpc\Error;
17+
use Mcp\Server\Transport\Http\MiddlewareRequestHandler;
1618
use Psr\Http\Message\ResponseFactoryInterface;
1719
use Psr\Http\Message\ResponseInterface;
1820
use Psr\Http\Message\ServerRequestInterface;
@@ -39,19 +41,19 @@ class StreamableHttpTransport extends BaseTransport
3941
private array $corsHeaders;
4042

4143
/** @var list<MiddlewareInterface> */
42-
private array $middlewares = [];
44+
private array $middleware = [];
4345

4446
/**
45-
* @param array<string, string> $corsHeaders
46-
* @param iterable<MiddlewareInterface> $middlewares
47+
* @param array<string, string> $corsHeaders
48+
* @param iterable<MiddlewareInterface> $middleware
4749
*/
4850
public function __construct(
4951
private ServerRequestInterface $request,
5052
?ResponseFactoryInterface $responseFactory = null,
5153
?StreamFactoryInterface $streamFactory = null,
5254
array $corsHeaders = [],
5355
?LoggerInterface $logger = null,
54-
iterable $middlewares = [],
56+
iterable $middleware = [],
5557
) {
5658
parent::__construct($logger);
5759

@@ -65,11 +67,11 @@ public function __construct(
6567
'Access-Control-Expose-Headers' => 'Mcp-Session-Id',
6668
], $corsHeaders);
6769

68-
foreach ($middlewares as $middleware) {
69-
if (!$middleware instanceof MiddlewareInterface) {
70-
throw new \InvalidArgumentException('Streamable HTTP middleware must implement Psr\\Http\\Server\\MiddlewareInterface.');
70+
foreach ($middleware as $m) {
71+
if (!$m instanceof MiddlewareInterface) {
72+
throw new InvalidArgumentException('Streamable HTTP middleware must implement Psr\\Http\\Server\\MiddlewareInterface.');
7173
}
72-
$this->middlewares[] = $middleware;
74+
$this->middleware[] = $m;
7375
}
7476
}
7577

@@ -289,32 +291,9 @@ private function createRequestHandler(): RequestHandlerInterface
289291
/**
290292
* @see self::handleRequest
291293
*/
292-
$handler = new class(\Closure::fromCallable([$this, 'handleRequest'])) implements RequestHandlerInterface {
293-
public function __construct(private \Closure $handler)
294-
{
295-
}
296-
297-
public function handle(ServerRequestInterface $request): ResponseInterface
298-
{
299-
return ($this->handler)($request);
300-
}
301-
};
302-
303-
foreach (array_reverse($this->middlewares) as $middleware) {
304-
$handler = new class($middleware, $handler) implements RequestHandlerInterface {
305-
public function __construct(
306-
private MiddlewareInterface $middleware,
307-
private RequestHandlerInterface $handler,
308-
) {
309-
}
310-
311-
public function handle(ServerRequestInterface $request): ResponseInterface
312-
{
313-
return $this->middleware->process($request, $this->handler);
314-
}
315-
};
316-
}
317-
318-
return $handler;
294+
return new MiddlewareRequestHandler(
295+
$this->middleware,
296+
\Closure::fromCallable([$this, 'handleRequest']),
297+
);
319298
}
320299
}

0 commit comments

Comments
 (0)