neomerx/cors-psr7

框架无关(PSR-7)的CORS实现(www.w3.org/TR/cors/)

3.0.2 2022-11-28 03:29 UTC

README

Code Coverage License

描述

本包提供了框架无关的跨源资源共享(CORS)实现。它符合PSR-7 HTTP消息接口。

为什么选择这个包?

示例用法

该包旨在作为中间件使用。典型用法

use Neomerx\Cors\Analyzer;
use Psr\Http\Message\RequestInterface;
use Neomerx\Cors\Contracts\AnalysisResultInterface;

class CorsMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param RequestInterface $request
     * @param Closure          $next
     *
     * @return mixed
     */
    public function handle(RequestInterface $request, Closure $next)
    {
        $cors = Analyzer::instance($this->getCorsSettings())->analyze($request);
        
        switch ($cors->getRequestType()) {
            case AnalysisResultInterface::ERR_NO_HOST_HEADER:
            case AnalysisResultInterface::ERR_ORIGIN_NOT_ALLOWED:
            case AnalysisResultInterface::ERR_METHOD_NOT_SUPPORTED:
            case AnalysisResultInterface::ERR_HEADERS_NOT_SUPPORTED:
                // return 4XX HTTP error
                return ...;

            case AnalysisResultInterface::TYPE_PRE_FLIGHT_REQUEST:
                $corsHeaders = $cors->getResponseHeaders();
                // return 200 HTTP with $corsHeaders
                return ...;

            case AnalysisResultInterface::TYPE_REQUEST_OUT_OF_CORS_SCOPE:
                // call next middleware handler
                return $next($request);
            
            default:
                // actual CORS request
                $response    = $next($request);
                $corsHeaders = $cors->getResponseHeaders();
                
                // add CORS headers to Response $response
                ...
                return $response;
        }
    }
}

设置

分析器接受设置在 Analyzer::instance($settings) 中,必须实现 AnalysisStrategyInterface。您可以使用默认实现 \Neomerx\Cors\Strategies\Settings 来设置分析器。

例如,

use Neomerx\Cors\Strategies\Settings;

$settings = (new Settings())
    ->setServerOrigin('https', 'api.example.com', 443)
    ->setPreFlightCacheMaxAge(0)
    ->setCredentialsSupported()
    ->setAllowedOrigins(['https://www.example.com', ...]) // or enableAllOriginsAllowed()
    ->setAllowedMethods(['GET', 'POST', 'DELETE', ...])   // or enableAllMethodsAllowed()
    ->setAllowedHeaders(['X-Custom-Header', ...])         // or enableAllHeadersAllowed()
    ->setExposedHeaders(['X-Custom-Header', ...])
    ->disableAddAllowedMethodsToPreFlightResponse()
    ->disableAddAllowedHeadersToPreFlightResponse()
    ->enableCheckHost();

$cors = Analyzer::instance($settings)->analyze($request);

设置可以缓存以提高性能。如果您已经配置了如上所示的设置,您可以得到内部设置状态如下

/** @var array $dataToCache */
$dataToCache = $settings->getData();

应使用缓存状态

$settings = (new Settings())->setData($dataFromCache);
$cors     = Analyzer::instance($settings)->analyze($request);

安装

composer require neomerx/cors-psr7

调试模式

调试日志将提供如何处理请求的详细步骤描述。为了激活它,需要设置一个PSR-3 兼容的日志器Analyzer

/** @var \Psr\Log\LoggerInterface $logger */
$logger   = ...;

$analyzer = Analyzer::instance($settings);
$analyzer->setLogger($logger)
$cors     = $analyzer->analyze($request);

高级用法

处理跨源和同源请求的可能策略有很多,这些策略可能或可能不依赖于请求中的数据。

此内置策略 Settings 实现了对所有请求都相同的简单设置(相同的允许源列表,相同的允许方法等)。

然而,您可以自定义这种行为。例如,您可以根据请求发送不同的允许方法集合。当您拥有某种类型的访问控制系统并希望根据请求(例如其源)区分响应时,这可能很有用。您可以从头实现 AnalysisStrategyInterface 或者在需要时覆盖 Settings 类中的方法。新策略可以发送到 Analyzer 构造函数,或者可以使用 Analyzer::instance 方法进行注入。

示例

class CustomMethodsSettings extends Settings
{
    public function getRequestAllowedMethods(RequestInterface $request): string
    {
        // An external Access Control System could be used to determine
        // which methods are allowed for this request.
        
        return ...;
    }
}

$cors = Analyzer::instance(new CustomMethodsSettings())->analyze($request);

测试

composer test

有疑问?

不要犹豫,检查 问题 或发布一个新的。

贡献

如果您发现了与CORS 建议书不一致的任何合规性问题,请发布 问题。欢迎使用对文档和代码改进(PSR-2、测试)的拉取请求。

版本管理

本包使用 语义版本控制

许可证

Apache许可证(版本2.0)。请参阅许可文件获取更多信息。