From fuse-php
Use when building framework-agnostic HTTP code in PHP — PSR-7 messages, PSR-15 middleware pipelines, PSR-17 factories, PSR-18 HTTP clients. Covers immutable Request/Response/Stream/Uri, RequestHandler + Middleware, factory interfaces, and reference implementations (nyholm/psr7, guzzlehttp/psr7, laminas-diactoros). Do NOT use for Laravel HTTP (use laravel-expert) or Symfony HttpFoundation (not PSR-7 — see references/implementations.md).
How this skill is triggered — by the user, by Claude, or both
Slash command
/fuse-php:php-http-psrThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Before ANY implementation, use `TeamCreate` to spawn 3 agents:
Before ANY implementation, use TeamCreate to spawn 3 agents:
After implementation, run fuse-ai-pilot:sniper for validation.
These four PSR standards let libraries handle HTTP without coupling to any framework. Code depends on interfaces (Psr\Http\*); a concrete implementation is injected.
| Standard | Package | Provides |
|---|---|---|
| PSR-7 | psr/http-message | Immutable HTTP messages: MessageInterface, RequestInterface, ResponseInterface, ServerRequestInterface, StreamInterface, UriInterface, UploadedFileInterface |
| PSR-15 | psr/http-server-handler + psr/http-server-middleware | RequestHandlerInterface, MiddlewareInterface — the middleware pipeline |
| PSR-17 | psr/http-factory | Factories that create PSR-7 objects without naming a concrete class |
| PSR-18 | psr/http-client | ClientInterface::sendRequest() — send a PSR-7 request, get a PSR-7 response |
with*() returns a NEW instance; the original is unchanged. $r->withHeader(...) alone is a no-op — reassign.ResponseInterface, inject a ResponseFactoryInterface. NEVER new Response() inside reusable code.StreamInterface wraps a real resource; use read-only streams for requests/responses.NetworkExceptionInterface) or malformed requests (RequestExceptionInterface).getHeaderLine('foo') == getHeaderLine('FOO'); original case is preserved in getHeaders().src/
├── Http/
│ ├── Middleware/ # implements Psr\Http\Server\MiddlewareInterface
│ │ ├── ErrorHandlerMiddleware.php
│ │ └── AuthMiddleware.php
│ ├── Handler/ # implements Psr\Http\Server\RequestHandlerInterface
│ │ └── Dispatcher.php # the pipeline runner
│ └── Client/ # wraps a Psr\Http\Client\ClientInterface
└── interfaces/ # your own contracts (SOLID)
→ See middleware-pipeline.md for a complete runnable pipeline
| Topic | Reference | When to Consult |
|---|---|---|
| Messages | psr7-messages.md | Reading/building requests, responses, streams, URIs |
| Middleware | psr15-middleware.md | Building a middleware + handler pipeline |
| Factories | psr17-factories.md | Creating PSR-7 objects implementation-agnostically |
| HTTP Client | psr18-client.md | Sending outbound requests, exception handling |
| Implementations | implementations.md | Choosing nyholm / guzzle / laminas + PSR-18 clients |
| Template | When to Use |
|---|---|
| middleware-pipeline.md | Building a PSR-15 dispatcher with middleware queue |
$response = $response
->withStatus(201)
->withHeader('Content-Type', 'application/json');
final class AuthMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (!$request->hasHeader('Authorization')) {
return $this->responseFactory->createResponse(401);
}
return $handler->handle($request);
}
}
$request = $requestFactory->createRequest('GET', 'https://api.example.com');
$request = $request->withBody($streamFactory->createStream('{"ping":true}'));
→ See psr17-factories.md for all six factory interfaces
ResponseFactoryInterface so middleware never names a concrete classnyholm/psr7 when you want a lightweight, strict PSR-7 + PSR-17 in one packagewith*() callwith*() returns a new objectHttpFoundation with PSR-7 — they are different; bridge via symfony/psr-http-message-bridgenew GuzzleHttp\Psr7\Response() in library code — depend on the factorynpx claudepluginhub fusengine/agents --plugin fuse-phpCreates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.