slimphp:如何处理CORS请求而不添加;选项“;路线

slimphp:如何处理CORS请求而不添加;选项“;路线,php,cors,slim,Php,Cors,Slim,我有一个精简的应用程序,需要配置CORS,但当我检查时,如果我想处理请求方法,我必须向每个端点添加一个新的选项路由(摘自文档): $app->add(函数(Request$Request,RequestHandlerInterface$handler):响应{ $routeContext=routeContext::fromRequest($request); $routingResults=$routeContext->getRoutingResults(); $methods=$routin

我有一个精简的应用程序,需要配置CORS,但当我检查时,如果我想处理请求方法,我必须向每个端点添加一个新的
选项
路由(摘自文档):

$app->add(函数(Request$Request,RequestHandlerInterface$handler):响应{
$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',内爆(',',$Methods));
$response=$response->withHeader('Access-Control-Allow-Headers',$requestHeaders);
//可选:允许带有授权标头的Ajax CORS请求
//$response=$response->withHeader('Access-Control-Allow-Credentials','true');
返回$response;
});
//RoutingMiddleware应该在我们的CORS中间件之后添加,所以首先执行路由
$app->addRoutingMiddleware();
//路线
$app->get('/api/v0/users',函数(请求$Request,响应$Response):响应{
$response->getBody()->write('列出所有用户');
返回$response;
});
//允许飞行前请求
//由于浏览器在发送请求时的行为,
//您必须添加选项方法。阅读飞行前的信息。
$app->options('/api/v0/users',函数(请求$Request,响应$Response):响应{
//在这里什么都不做。只需返回响应。
返回$response;
});

如何避免每次创建新路由的痛苦?

经过一番挖掘,我可以通过创建自定义路由中间件来避免为每个路由添加新的处理程序。其思想是,它检查路由是否与
访问控制请求方法
头中发送的方法解析,如果有,则更改可调用的路由以避免调用实际的处理程序

类MyRoutingMiddleware扩展\Slim\Middleware\RoutingMiddleware
{
公共函数performRouting(ServerRequestInterface$request):ServerRequestInterface
{
$request=$request->withAttribute(RouteContext::ROUTE_PARSER,$this->routeParser);
$accessControlRequestMethod=$request->getHeaderLine(“访问控制请求方法”);
$isPreflight=$request->getMethod()==“选项”&&$accessControlRequestMethod!==”;
$routingResults=$this->resolveRoutingResultsFromRequest($request);
$routeStatus=$routingResults->getRouteStatus();
$request=$request->withAttribute(RouteContext::ROUTING_RESULTS,$routingResults);
交换机($routeStatus){
案例路由结果::找到:
$routeArguments=$routingResults->getRouteArguments();
$routeIdentifier=$routingResults->getRouteIdentifier();
$route=$this->routeResolver
->resolveRoute($routeIdentifier)
->准备($routeArguments);
如果($isPreflight){
$route->setCallable(函数(ServerRequestInterface$request、ResponseInterface$response、array$arguments){
返回$response;
});
}
返回$request->withAttribute(RouteContext::ROUTE,$ROUTE);
案例路由结果::未找到:
抛出新的HttpNotFoundException($request);
案例路由结果::不允许使用方法:
$exception=新的HttpMethodNotAllowedException($request);
$exception->setAllowedMethods($routingResults->getAllowedMethods());
抛出$exception;
违约:
抛出新的RuntimeException('执行路由时发生意外错误');
}
}
受保护函数resolveRoutingResultsFromRequest(ServerRequestInterface$request):RoutingResults
{
$accessControlRequestMethod=$request->getHeaderLine(“访问控制请求方法”);
$isPreflight=$request->getMethod()==“选项”&&$accessControlRequestMethod!==”;
返回$this->routeResolver->computeRoutingResults(
$request->getUri()->getPath(),
$isPreflight?$accessControlRequestMethod:$request->getMethod()
);
}
}
然后我不再使用默认路由中间件:

//全局添加cors中间件
$app->add(函数(Request$Request,RequestHandlerInterface$handler):响应{
$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',内爆(',',$Methods));
$response=$response->withHeader('Access-Control-Allow-Headers',$requestHeaders);
//可选:允许带有授权标头的Ajax CORS请求
//$response=$response->withHeader('Access-Control-Allow-Credentials','true');
返回$response;
});
//路线
$app->get('/api/v0/users',函数(请求$Request,响应$Response):响应{
$response->getBody()->write('列出所有用户');
返回$response;
});
//不再需要添加$app->options(…)了!
//使用自定义路由中间件
$app->add(新的MyRoutingMiddleware($app->getRouteResolver(),$app->getRouteCollector()->getRouteParser());
更新

如果代码中抛出异常(
HttpNotFoundException
),则没有CORS处理,这可能是一个问题,