|
@@ -0,0 +1,85 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+namespace Middlewares;
|
|
|
|
|
+
|
|
|
|
|
+use Psr\Http\Message\ResponseInterface;
|
|
|
|
|
+use Psr\Http\Message\ServerRequestInterface;
|
|
|
|
|
+use React\Http\Message\Response;
|
|
|
|
|
+use React\Promise\PromiseInterface;
|
|
|
|
|
+
|
|
|
|
|
+class CorsMiddleware
|
|
|
|
|
+{
|
|
|
|
|
+ private ?string $forcedOrigin;
|
|
|
|
|
+
|
|
|
|
|
+ public function __construct()
|
|
|
|
|
+ {
|
|
|
|
|
+ $origin = $_ENV['CORS_ALLOWED_ORIGIN'] ?? '';
|
|
|
|
|
+ $this->forcedOrigin = $origin !== '' ? $origin : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function __invoke(ServerRequestInterface $request, callable $next)
|
|
|
|
|
+ {
|
|
|
|
|
+ $origin = $this->resolveOrigin($request);
|
|
|
|
|
+
|
|
|
|
|
+ if (strtoupper($request->getMethod()) === 'OPTIONS') {
|
|
|
|
|
+ return $this->preflightResponse($origin);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $response = $next($request);
|
|
|
|
|
+
|
|
|
|
|
+ return $this->decorateResponse($response, $origin);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param ResponseInterface|PromiseInterface $response
|
|
|
|
|
+ * @return ResponseInterface|PromiseInterface
|
|
|
|
|
+ */
|
|
|
|
|
+ private function decorateResponse($response, string $origin)
|
|
|
|
|
+ {
|
|
|
|
|
+ if ($response instanceof PromiseInterface) {
|
|
|
|
|
+ return $response->then(function ($actual) use ($origin) {
|
|
|
|
|
+ return $this->decorateResponse($actual, $origin);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ($response instanceof ResponseInterface) {
|
|
|
|
|
+ return $this->applyHeaders($response, $origin);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $response;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function preflightResponse(string $origin): ResponseInterface
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->applyHeaders(
|
|
|
|
|
+ Response::plaintext('')->withStatus(204),
|
|
|
|
|
+ $origin
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function applyHeaders(ResponseInterface $response, string $origin): ResponseInterface
|
|
|
|
|
+ {
|
|
|
|
|
+ $response = $response
|
|
|
|
|
+ ->withHeader('Access-Control-Allow-Origin', $origin)
|
|
|
|
|
+ ->withHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS')
|
|
|
|
|
+ ->withHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
|
|
|
|
|
+ ->withHeader('Access-Control-Max-Age', '86400')
|
|
|
|
|
+ ->withHeader('Vary', 'Origin');
|
|
|
|
|
+
|
|
|
|
|
+ if ($origin !== '*') {
|
|
|
|
|
+ $response = $response->withHeader('Access-Control-Allow-Credentials', 'true');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $response;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function resolveOrigin(ServerRequestInterface $request): string
|
|
|
|
|
+ {
|
|
|
|
|
+ if ($this->forcedOrigin !== null) {
|
|
|
|
|
+ return $this->forcedOrigin;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $origin = $request->getHeaderLine('Origin');
|
|
|
|
|
+ return $origin !== '' ? $origin : '*';
|
|
|
|
|
+ }
|
|
|
|
|
+}
|