mercureact/src/Http/Middleware/ResponseMiddleware.php

89 lines
3.5 KiB
PHP
Raw Normal View History

2024-03-10 19:22:28 +00:00
<?php
namespace NoccyLabs\Mercureact\Http\Middleware;
use NoccyLabs\Mercureact\Configuration;
2024-03-12 01:21:42 +00:00
use NoccyLabs\Mercureact\Exception\SecurityException;
2024-03-10 19:22:28 +00:00
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
2024-03-11 00:20:45 +00:00
use Psr\Log\LoggerInterface;
2024-03-10 19:22:28 +00:00
use React\Http\Message\Response;
use React\Promise\Promise;
use React\Promise\PromiseInterface;
use Throwable;
class ResponseMiddleware
{
public function __construct(
2024-03-11 00:20:45 +00:00
private Configuration $config,
private LoggerInterface $logger,
2024-03-10 19:22:28 +00:00
)
{
}
/**
* Wraps rejections into error messages, and also does some sanity checks on the returned
* data, making sure it is a response.
*
* @param ServerRequestInterface $request
* @param callable $next
* @return PromiseInterface
*/
public function __invoke(ServerRequestInterface $request, callable $next): PromiseInterface
{
$promise = new Promise(
function (callable $resolve) use ($request, $next) {
try {
$resolve($next($request));
} catch (SecurityException $t) {
$resolve(Response::plaintext("Access Denied")->withStatus(Response::STATUS_UNAUTHORIZED));
} catch (\Throwable $t) {
$this->logger->warning(get_class($t).": ".$t->getMessage(), [ 'file'=>$t->getFile(), 'line'=>$t->getLine() ]);
$resolve(Response::plaintext("500: Internal Server Error (".$t->getMessage().")\n")->withStatus(500));
}
2024-03-10 19:22:28 +00:00
}
);
return $promise->then(
function ($response) {
if ($response instanceof ResponseInterface) {
return $response;
}
if (is_array($response)) {
return Response::json($response);
}
if (is_string($response)) {
return Response::plaintext($response);
}
return Response::plaintext((string)$response);
}
)->then(
function ($response) use ($request) {
assert("\$response instanceof ResponseInterface");
2024-03-11 00:20:45 +00:00
$this->logger->debug(sprintf("%s %s %s → %3d (%d)",
2024-03-10 19:22:28 +00:00
$request->getServerParams()['REMOTE_ADDR'],
$request->getMethod(),
$request->getUri()->getPath(),
2024-03-11 00:20:45 +00:00
$response->getStatusCode(),
2024-03-10 19:22:28 +00:00
strlen($response->getBody())
2024-03-11 00:20:45 +00:00
), [
'remote' => $request->getServerParams()['REMOTE_ADDR'],
'status' => $response->getStatusCode(),
'method' => $request->getMethod(),
'path' => $request->getUri()->getPath(),
]);
2024-03-13 00:28:14 +00:00
2024-03-10 19:22:28 +00:00
return $response
2024-03-10 23:36:34 +00:00
// ->withAddedHeader('Link', '<https://'.$host.'/.well-known/mercure>; rel="mercure"')
// ->withAddedHeader('Link', '<wss://'.$host.'/.well-known/mercure>; rel="mercure+ws"')
2024-03-13 00:28:14 +00:00
->withHeader('Access-Control-Allow-Origin',
$this->config->get('server.cors.allow_origin', '*'))
->withHeader('Content-Security-Policy',
$this->config->get('server.cors.csp', "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"))
2024-03-10 19:22:28 +00:00
->withHeader('Cache-Control', 'must-revalidate')
->withHeader('Server', 'Mercureact/0.1.0');
}
);
}
}