Skip to content

Commit baebdaf

Browse files
committed
Add CORS middleware for documentation site API access
Allows cross-origin requests from trusted domains (php-collective.github.io and sandbox.dereuromark.de) so documentation sites can use sandbox APIs for interactive demos and playgrounds.
1 parent 9dad333 commit baebdaf

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

src/Application.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App;
44

5+
use App\Http\Middleware\CorsMiddleware;
56
use App\Http\Middleware\DemoRateLimitMiddleware;
67
use App\Http\Middleware\MissingControllerMiddleware;
78
use App\Http\Middleware\RedirectMiddleware;
@@ -85,6 +86,9 @@ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue {
8586
// Handle cached files
8687
->add(CacheMiddleware::class)
8788

89+
// CORS headers for API access from documentation sites
90+
->add(CorsMiddleware::class)
91+
8892
->add(RedirectMiddleware::class)
8993

9094
// Apply routing
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace App\Http\Middleware;
5+
6+
use Cake\Http\Response;
7+
use Psr\Http\Message\ResponseInterface;
8+
use Psr\Http\Message\ServerRequestInterface;
9+
use Psr\Http\Server\MiddlewareInterface;
10+
use Psr\Http\Server\RequestHandlerInterface;
11+
12+
/**
13+
* CORS Middleware
14+
*
15+
* Allows cross-origin requests from trusted domains for API endpoints.
16+
* This enables documentation sites to use sandbox APIs for live demos.
17+
*/
18+
class CorsMiddleware implements MiddlewareInterface {
19+
20+
/**
21+
* Allowed origins for CORS requests.
22+
*
23+
* @var array<string>
24+
*/
25+
protected array $allowedOrigins = [
26+
'https://php-collective.github.io',
27+
'https://sandbox.dereuromark.de',
28+
];
29+
30+
/**
31+
* Process the request and add CORS headers if origin is allowed.
32+
*
33+
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
34+
* @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
35+
* @return \Psr\Http\Message\ResponseInterface A response.
36+
*/
37+
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
38+
$origin = $request->getHeaderLine('Origin');
39+
40+
// Handle preflight OPTIONS requests
41+
if ($request->getMethod() === 'OPTIONS') {
42+
$response = new Response();
43+
$response = $response->withStatus(204);
44+
} else {
45+
$response = $handler->handle($request);
46+
}
47+
48+
// Only add CORS headers if origin is in allowlist
49+
if ($origin !== '' && in_array($origin, $this->allowedOrigins, true)) {
50+
$response = $response
51+
->withHeader('Access-Control-Allow-Origin', $origin)
52+
->withHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
53+
->withHeader('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With')
54+
->withHeader('Access-Control-Max-Age', '86400');
55+
}
56+
57+
return $response;
58+
}
59+
60+
}

0 commit comments

Comments
 (0)