CORS - 跨源资源共享
实现CORS支持的好流程图参考:
您可以在此处测试您的 CORS 支持:http://www.test-cors.org/
您可以在此处阅读规范:https://www.w3.org/TR/cors/
对于简单的 CORS 请求,服务器只需要在其响应中添加以下标头:
Access-Control-Allow-Origin: <domain>, ...
以下代码应启用惰性 CORS。
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response;
});
$app->add(function ($request, $handler) {
$response = $handler->handle($request);
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});
添加以下路由作为最后一条路由:
<?php
use Slim\Exception\HttpNotFoundException;
/**
* Catch-all route to serve a 404 Not Found page if none of the routes match
* NOTE: make sure this route is defined last
*/
$app->map(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], '/{routes:.+}', function ($request, $response) {
throw new HttpNotFoundException($request);
});
以下中间件可用于查询 Slim 的路由器并获取特定模式实现的方法列表。
这是一个完整的示例应用程序:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Factory\AppFactory;
use Slim\Routing\RouteCollectorProxy;
use Slim\Routing\RouteContext;
require_once __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->addBodyParsingMiddleware();
// This middleware will append the response header Access-Control-Allow-Methods with all allowed methods
$app->add(function (Request $request, RequestHandlerInterface $handler): Response {
$routeContext = RouteContext::fromRequest($request);
$routingResults = $routeContext->getRoutingResults();
$methods = $routingResults->getAllowedMethods();
$requestHeaders = $request->getHeaderLine('Access-Control-Request-Headers');
$response = $handler->handle($request);
$response = $response->withHeader('Access-Control-Allow-Origin', '*');
$response = $response->withHeader('Access-Control-Allow-Methods', implode(',', $methods));
$response = $response->withHeader('Access-Control-Allow-Headers', $requestHeaders);
// Optional: Allow Ajax CORS requests with Authorization header
// $response = $response->withHeader('Access-Control-Allow-Credentials', 'true');
return $response;
});
// The RoutingMiddleware should be added after our CORS middleware so routing is performed first
$app->addRoutingMiddleware();
// The routes
$app->get('/api/v0/users', function (Request $request, Response $response): Response {
$response->getBody()->write('List all users');
return $response;
});
$app->get('/api/v0/users/{id}', function (Request $request, Response $response, array $arguments): Response {
$userId = (int)$arguments['id'];
$response->getBody()->write(sprintf('Get user: %s', $userId));
return $response;
});
$app->post('/api/v0/users', function (Request $request, Response $response): Response {
// Retrieve the JSON data
$parameters = (array)$request->getParsedBody();
$response->getBody()->write('Create user');
return $response;
});
$app->delete('/api/v0/users/{id}', function (Request $request, Response $response, array $arguments): Response {
$userId = (int)$arguments['id'];
$response->getBody()->write(sprintf('Delete user: %s', $userId));
return $response;
});
// Allow preflight requests
// Due to the behaviour of browsers when sending a request,
// you must add the OPTIONS method. Read about preflight.
$app->options('/api/v0/users', function (Request $request, Response $response): Response {
// Do nothing here. Just return the response.
return $response;
});
// Allow additional preflight requests
$app->options('/api/v0/users/{id}', function (Request $request, Response $response): Response {
return $response;
});
// Using groups
$app->group('/api/v0/users/{id:[0-9]+}', function (RouteCollectorProxy $group) {
$group->put('', function (Request $request, Response $response, array $arguments): Response {
// Your code here...
$userId = (int)$arguments['id'];
$response->getBody()->write(sprintf('Put user: %s', $userId));
return $response;
});
$group->patch('', function (Request $request, Response $response, array $arguments): Response {
$userId = (int)$arguments['id'];
$response->getBody()->write(sprintf('Patch user: %s', $userId));
return $response;
});
// Allow preflight requests
$group->options('', function (Request $request, Response $response): Response {
return $response;
});
});
$app->run();
如果请求包含凭据(cookie、授权标头或 TLS 客户端证书),您可能需要Access-Control-Allow-Credentials
向响应对象添加标头。
$response = $response->withHeader('Access-Control-Allow-Credentials', 'true');