0 关注者

类 yii\filters\Cors

继承yii\filters\Cors » yii\base\ActionFilter » yii\base\Behavior » yii\base\BaseObject
实现yii\base\Configurable
可用版本2.0
源代码 https://github.com/yiisoft/yii2/blob/master/framework/filters/Cors.php

Cors 过滤器实现 跨域资源共享.

确保仔细阅读 CORS 的功能和限制。 CORS 不会保护您的 API,而是允许开发人员授予第三方代码访问权限(来自外部域的 AJAX 调用)。

您可以通过将其作为行为附加到控制器或模块来使用 CORS 过滤器,例如以下内容,

public function behaviors()
{
    return [
        'corsFilter' => [
            'class' => \yii\filters\Cors::class,
        ],
    ];
}

CORS 过滤器可以专门用于限制参数,例如,MDN CORS 信息

public function behaviors()
{
    return [
        'corsFilter' => [
            'class' => \yii\filters\Cors::class,
            'cors' => [
                // restrict access to
                'Origin' => ['http://www.myserver.com', 'https://www.myserver.com'],
                // Allow only POST and PUT methods
                'Access-Control-Request-Method' => ['POST', 'PUT'],
                // Allow only headers 'X-Wsse'
                'Access-Control-Request-Headers' => ['X-Wsse'],
                // Allow credentials (cookies, authorization headers, etc.) to be exposed to the browser
                'Access-Control-Allow-Credentials' => true,
                // Allow OPTIONS caching
                'Access-Control-Max-Age' => 3600,
                // Allow the X-Pagination-Current-Page header to be exposed to the browser.
                'Access-Control-Expose-Headers' => ['X-Pagination-Current-Page'],
            ],

        ],
    ];
}

有关如何将 CORS 过滤器添加到控制器的更多信息,请参阅 REST 控制器指南.

公共属性

隐藏继承的属性

属性 类型 描述 定义于
$actions array 为特定操作定义特定 CORS 规则 yii\filters\Cors
$cors array 为 CORS 请求处理的基本头部。 yii\filters\Cors
$except array 此过滤器不应应用到的操作 ID 列表。 yii\base\ActionFilter
$only array 此过滤器应应用到的操作 ID 列表。 yii\base\ActionFilter
$owner yii\base\Component|null 此行为的拥有者 yii\base\Behavior
$request yii\web\Request|null 当前请求。 yii\filters\Cors
$response yii\web\Response|null 要发送的响应。 yii\filters\Cors

公共方法

隐藏继承的方法

方法 描述 定义于
__call() 调用不是类方法的命名方法。 yii\base\BaseObject
__construct() 构造函数。 yii\base\BaseObject
__get() 返回对象属性的值。 yii\base\BaseObject
__isset() 检查属性是否已设置,即已定义且不为空。 yii\base\BaseObject
__set() 设置对象属性的值。 yii\base\BaseObject
__unset() 将对象属性设置为 null。 yii\base\BaseObject
addCorsHeaders() 向响应添加 CORS 头部。 yii\filters\Cors
afterAction() 此方法在操作执行后立即调用。 yii\base\ActionFilter
afterFilter() yii\base\ActionFilter
attach() 将行为对象附加到组件。 yii\base\ActionFilter
beforeAction() 此方法在要执行的操作之前立即调用(在所有可能的过滤器之后)。您可以覆盖此方法以对操作进行最后一分钟的准备。 yii\filters\Cors
beforeFilter() yii\base\ActionFilter
canGetProperty() 返回一个值,指示是否可以读取属性。 yii\base\BaseObject
canSetProperty() 返回一个值,指示是否可以设置属性。 yii\base\BaseObject
className() 返回此类的完全限定名称。 yii\base\BaseObject
detach() 从组件中分离行为对象。 yii\base\ActionFilter
events() $owner 的事件声明事件处理程序。 yii\base\Behavior
extractHeaders() 从请求中提取 CORS 头部。 yii\filters\Cors
hasMethod() 返回一个值,指示是否定义了方法。 yii\base\BaseObject
hasProperty() 返回一个值,指示是否定义了属性。 yii\base\BaseObject
init() 初始化对象。 yii\base\BaseObject
overrideDefaultSettings() 覆盖特定操作的设置。 yii\filters\Cors
prepareHeaders() 为每个 CORS 头部创建特定的响应。 yii\filters\Cors

受保护的方法

隐藏继承的方法

方法 描述 定义于
getActionId() 通过将 yii\base\Action::$uniqueId 转换为相对于模块的 ID 来返回操作 ID。 yii\base\ActionFilter
headerize() 将任何字符串(包括带有 HTTP 前缀的 PHP 头部)转换为头部格式。 yii\filters\Cors
headerizeToPhp() 将任何字符串(包括带有 HTTP 前缀的 PHP 头部)转换为头部格式。 yii\filters\Cors
isActive() 返回一个值,指示过滤器对给定操作是否处于活动状态。 yii\base\ActionFilter
prepareAllowHeaders() 处理经典 CORS 请求以避免重复代码。 yii\filters\Cors

属性详细信息

隐藏继承的属性

$actions 公共属性

为特定操作定义特定 CORS 规则

public array $actions = []
$cors 公共属性

为 CORS 请求处理的基本头部。

public array $cors = [
    
'Origin' => [
        
'*',
    ],
    
'Access-Control-Request-Method' => [
        
'GET',
        
'POST',
        
'PUT',
        
'PATCH',
        
'DELETE',
        
'HEAD',
        
'OPTIONS',
    ],
    
'Access-Control-Request-Headers' => [
        
'*',
    ],
    
'Access-Control-Allow-Credentials' => null,
    
'Access-Control-Max-Age' => 86400,
    
'Access-Control-Expose-Headers' => [],
]
$request 公共属性

当前请求。如果未设置,则将使用 request 应用组件。

$response 公共属性

要发送的响应。如果未设置,则将使用 response 应用组件。

方法详情

隐藏继承的方法

__call() 公共方法

定义于: yii\base\BaseObject::__call()

调用不是类方法的命名方法。

不要直接调用此方法,因为它是一个 PHP 魔术方法,当调用未知方法时会隐式调用。

public mixed __call ( $name, $params )
$name string

方法名

$params array

方法参数

返回值 mixed

方法返回值

抛出异常 yii\base\UnknownMethodException

调用未知方法时

                public function __call($name, $params)
{
    throw new UnknownMethodException('Calling unknown method: ' . get_class($this) . "::$name()");
}

            
__construct() 公共方法

定义于: yii\base\BaseObject::__construct()

构造函数。

默认实现执行两件事

  • 使用给定的配置 $config 初始化对象。
  • 调用 init().

如果在子类中重写了此方法,建议

  • 构造函数的最后一个参数是一个配置数组,就像这里的 $config 一样。
  • 在构造函数的末尾调用父类的实现。
public void __construct ( $config = [] )
$config array

将用于初始化对象属性的名称-值对

                public function __construct($config = [])
{
    if (!empty($config)) {
        Yii::configure($this, $config);
    }
    $this->init();
}

            
__get() 公共方法

定义于: yii\base\BaseObject::__get()

返回对象属性的值。

不要直接调用此方法,因为它是一个 PHP 魔术方法,当执行 $value = $object->property; 时会隐式调用。

另请参见 __set().

public mixed __get ( $name )
$name string

属性名

返回值 mixed

属性值

抛出异常 yii\base\UnknownPropertyException

如果未定义属性

抛出异常 yii\base\InvalidCallException

如果属性是只写的

                public function __get($name)
{
    $getter = 'get' . $name;
    if (method_exists($this, $getter)) {
        return $this->$getter();
    } elseif (method_exists($this, 'set' . $name)) {
        throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name);
    }
    throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);
}

            
__isset() 公共方法

定义于: yii\base\BaseObject::__isset()

检查属性是否已设置,即已定义且不为空。

不要直接调用此方法,因为它是一个 PHP 魔术方法,当执行 isset($object->property) 时会隐式调用。

请注意,如果未定义属性,则将返回 false。

另请参见 https://php.ac.cn/manual/en/function.isset.php.

public boolean __isset ( $name )
$name string

属性名或事件名

返回值 boolean

命名的属性是否已设置(不为空)。

                public function __isset($name)
{
    $getter = 'get' . $name;
    if (method_exists($this, $getter)) {
        return $this->$getter() !== null;
    }
    return false;
}

            
__set() 公共方法

定义于: yii\base\BaseObject::__set()

设置对象属性的值。

不要直接调用此方法,因为它是一个 PHP 魔术方法,当执行 $object->property = $value; 时会隐式调用。

另请参见 __get().

public void __set ( $name, $value )
$name string

属性名或事件名

$value mixed

属性值

抛出异常 yii\base\UnknownPropertyException

如果未定义属性

抛出异常 yii\base\InvalidCallException

如果属性是只读的

                public function __set($name, $value)
{
    $setter = 'set' . $name;
    if (method_exists($this, $setter)) {
        $this->$setter($value);
    } elseif (method_exists($this, 'get' . $name)) {
        throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name);
    } else {
        throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name);
    }
}

            
__unset() 公共方法

定义于: yii\base\BaseObject::__unset()

将对象属性设置为 null。

不要直接调用此方法,因为它是一个 PHP 魔术方法,当执行 unset($object->property) 时会隐式调用。

请注意,如果未定义属性,则此方法将不会执行任何操作。如果属性是只读的,则会抛出异常。

另请参见 https://php.ac.cn/manual/en/function.unset.php.

public void __unset ( $name )
$name string

属性名

抛出异常 yii\base\InvalidCallException

如果属性是只读的。

                public function __unset($name)
{
    $setter = 'set' . $name;
    if (method_exists($this, $setter)) {
        $this->$setter(null);
    } elseif (method_exists($this, 'get' . $name)) {
        throw new InvalidCallException('Unsetting read-only property: ' . get_class($this) . '::' . $name);
    }
}

            
addCorsHeaders() 公共方法

向响应添加 CORS 头部。

public void addCorsHeaders ( $response, $headers )
$response yii\web\Response
$headers array

已计算的 CORS 头部

                public function addCorsHeaders($response, $headers)
{
    if (empty($headers) === false) {
        $responseHeaders = $response->getHeaders();
        foreach ($headers as $field => $value) {
            $responseHeaders->set($field, $value);
        }
    }
}

            
afterAction() 公共方法

定义于: yii\base\ActionFilter::afterAction()

此方法在操作执行后立即调用。

您可以重写此方法来对动作进行一些后期处理。

public mixed afterAction ( $action, $result )
$action yii\base\Action

刚刚执行的动作。

$result mixed

动作执行结果

返回值 mixed

已处理的动作结果。

                public function afterAction($action, $result)
{
    return $result;
}

            
afterFilter() 公共方法
public void afterFilter ( $event )
$event yii\base\ActionEvent

                public function afterFilter($event)
{
    $event->result = $this->afterAction($event->action, $event->result);
    $this->owner->off(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter']);
}

            
attach() 公共方法

定义于: yii\base\ActionFilter::attach()

将行为对象附加到组件。

默认实现将设置 $owner 属性,并将事件处理程序附加到 events() 中声明的事件。如果您覆盖此方法,请确保您调用了父级实现。

public void attach ( $owner )
$owner yii\base\Component

将要附加此行为的组件。

                public function attach($owner)
{
    $this->owner = $owner;
    $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']);
}

            
beforeAction() 公共方法

此方法在要执行的操作之前立即调用(在所有可能的过滤器之后)。您可以覆盖此方法以对操作进行最后一分钟的准备。

public boolean beforeAction ( $action )
$action yii\base\Action

要执行的操作。

返回值 boolean

操作是否应该继续执行。

                public function beforeAction($action)
{
    $this->request = $this->request ?: Yii::$app->getRequest();
    $this->response = $this->response ?: Yii::$app->getResponse();
    $this->overrideDefaultSettings($action);
    $requestCorsHeaders = $this->extractHeaders();
    $responseCorsHeaders = $this->prepareHeaders($requestCorsHeaders);
    $this->addCorsHeaders($this->response, $responseCorsHeaders);
    if ($this->request->isOptions && $this->request->headers->has('Access-Control-Request-Method')) {
        // it is CORS preflight request, respond with 200 OK without further processing
        $this->response->setStatusCode(200);
        return false;
    }
    return true;
}

            
beforeFilter() 公共方法
public void beforeFilter ( $event )
$event yii\base\ActionEvent

                public function beforeFilter($event)
{
    if (!$this->isActive($event->action)) {
        return;
    }
    $event->isValid = $this->beforeAction($event->action);
    if ($event->isValid) {
        // call afterFilter only if beforeFilter succeeds
        // beforeFilter and afterFilter should be properly nested
        $this->owner->on(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter'], null, false);
    } else {
        $event->handled = true;
    }
}

            
canGetProperty() 公共方法

定义于: yii\base\BaseObject::canGetProperty()

返回一个值,指示是否可以读取属性。

如果属性可读,则

  • 该类具有与指定名称关联的 getter 方法(在这种情况下,属性名称不区分大小写);
  • 该类具有与指定名称匹配的成员变量(当 $checkVars 为 true 时);

另请参阅 canSetProperty()

public boolean canGetProperty ( $name, $checkVars true )
$name string

属性名

$checkVars boolean

是否将成员变量视为属性

返回值 boolean

该属性是否可读

                public function canGetProperty($name, $checkVars = true)
{
    return method_exists($this, 'get' . $name) || $checkVars && property_exists($this, $name);
}

            
canSetProperty() 公共方法

定义于: yii\base\BaseObject::canSetProperty()

返回一个值,指示是否可以设置属性。

如果属性可写,则

  • 该类具有与指定名称关联的 setter 方法(在这种情况下,属性名称不区分大小写);
  • 该类具有与指定名称匹配的成员变量(当 $checkVars 为 true 时);

另请参阅 canGetProperty()

public boolean canSetProperty ( $name, $checkVars true )
$name string

属性名

$checkVars boolean

是否将成员变量视为属性

返回值 boolean

该属性是否可写

                public function canSetProperty($name, $checkVars = true)
{
    return method_exists($this, 'set' . $name) || $checkVars && property_exists($this, $name);
}

            
className() 公共静态方法
从 2.0.14 版本开始弃用。在 PHP >=5.5 中,请使用 ::class 代替。

定义于: yii\base\BaseObject::className()

返回此类的完全限定名称。

public static string className ( )
返回值 string

此类的完全限定名称。

                public static function className()
{
    return get_called_class();
}

            
detach() 公共方法

定义于: yii\base\ActionFilter::detach()

从组件中分离行为对象。

默认实现将取消设置 $owner 属性,并取消附加 events() 中声明的事件处理程序。如果您覆盖此方法,请确保您调用了父级实现。

public void detach ( )

                public function detach()
{
    if ($this->owner) {
        $this->owner->off(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']);
        $this->owner->off(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter']);
        $this->owner = null;
    }
}

            
events() 公共方法

定义于: yii\base\Behavior::events()

$owner 的事件声明事件处理程序。

子类可以覆盖此方法,以声明应附加到 $owner 组件事件的 PHP 回调。

当行为附加到所有者时,回调将附加到 $owner 的事件;当行为从组件中分离时,它们将从事件中分离。

回调可以是以下任何一种

  • 此行为中的方法:'handleClick',相当于 [$this, 'handleClick']
  • 对象方法:[$object, 'handleClick']
  • 静态方法:['Page', 'handleClick']
  • 匿名函数:function ($event) { ... }

以下是一个例子

[
    Model::EVENT_BEFORE_VALIDATE => 'myBeforeValidate',
    Model::EVENT_AFTER_VALIDATE => 'myAfterValidate',
]
public array events ( )
返回值 array

事件(数组键)和相应的事件处理程序方法(数组值)。

                public function events()
{
    return [];
}

            
extractHeaders() 公共方法

从请求中提取 CORS 头部。

public array extractHeaders ( )
返回值 array

要处理的 CORS 标头

                public function extractHeaders()
{
    $headers = [];
    foreach (array_keys($this->cors) as $headerField) {
        $serverField = $this->headerizeToPhp($headerField);
        $headerData = isset($_SERVER[$serverField]) ? $_SERVER[$serverField] : null;
        if ($headerData !== null) {
            $headers[$headerField] = $headerData;
        }
    }
    return $headers;
}

            
getActionId() 受保护方法 (从版本 2.0.7 开始可用)

定义于: yii\base\ActionFilter::getActionId()

通过将 yii\base\Action::$uniqueId 转换为相对于模块的 ID 来返回操作 ID。

protected string getActionId ( $action )
$action yii\base\Action

                protected function getActionId($action)
{
    if ($this->owner instanceof Module) {
        $mid = $this->owner->getUniqueId();
        $id = $action->getUniqueId();
        if ($mid !== '' && strpos($id, $mid) === 0) {
            $id = substr($id, strlen($mid) + 1);
        }
    } else {
        $id = $action->id;
    }
    return $id;
}

            
hasMethod() 公共方法

定义于: yii\base\BaseObject::hasMethod()

返回一个值,指示是否定义了方法。

默认实现是调用 php 函数 method_exists()。当您实现 php 魔术方法 __call() 时,您可以覆盖此方法。

public boolean hasMethod ( $name )
$name string

方法名

返回值 boolean

该方法是否已定义

                public function hasMethod($name)
{
    return method_exists($this, $name);
}

            
hasProperty() 公共方法

定义于: yii\base\BaseObject::hasProperty()

返回一个值,指示是否定义了属性。

如果属性已定义,则

  • 该类具有与指定名称关联的 getter 或 setter 方法(在这种情况下,属性名称不区分大小写);
  • 该类具有与指定名称匹配的成员变量(当 $checkVars 为 true 时);

另请参阅

public boolean hasProperty ( $name, $checkVars true )
$name string

属性名

$checkVars boolean

是否将成员变量视为属性

返回值 boolean

该属性是否已定义

                public function hasProperty($name, $checkVars = true)
{
    return $this->canGetProperty($name, $checkVars) || $this->canSetProperty($name, false);
}

            
headerize() 受保护方法

将任何字符串(包括带有 HTTP 前缀的 PHP 头部)转换为头部格式。

示例

  • X-PINGOTHER -> X-Pingother
  • X_PINGOTHER -> X-Pingother
protected string headerize ( $string )
$string string

要转换的字符串

返回值 string

"header" 格式的结果

                protected function headerize($string)
{
    $headers = preg_split('/[\\s,]+/', $string, -1, PREG_SPLIT_NO_EMPTY);
    $headers = array_map(function ($element) {
        return str_replace(' ', '-', ucwords(strtolower(str_replace(['_', '-'], [' ', ' '], $element))));
    }, $headers);
    return implode(', ', $headers);
}

            
headerizeToPhp() 受保护方法

将任何字符串(包括带有 HTTP 前缀的 PHP 头部)转换为头部格式。

示例

  • X-Pingother -> HTTP_X_PINGOTHER
  • X PINGOTHER -> HTTP_X_PINGOTHER
protected string headerizeToPhp ( $string )
$string string

要转换的字符串

返回值 string

"php $_SERVER header" 格式的结果

                protected function headerizeToPhp($string)
{
    return 'HTTP_' . strtoupper(str_replace([' ', '-'], ['_', '_'], $string));
}

            
init() 公共方法

定义于: yii\base\BaseObject::init()

初始化对象。

此方法在对象使用给定的配置初始化后,在构造函数的末尾调用。

public void init ( )

                public function init()
{
}

            
isActive() 受保护方法

定义于: yii\base\ActionFilter::isActive()

返回一个值,指示过滤器对给定操作是否处于活动状态。

protected boolean isActive ( $action )
$action yii\base\Action

正在过滤的动作

返回值 boolean

过滤器是否对给定动作有效。

                protected function isActive($action)
{
    $id = $this->getActionId($action);
    if (empty($this->only)) {
        $onlyMatch = true;
    } else {
        $onlyMatch = false;
        foreach ($this->only as $pattern) {
            if (StringHelper::matchWildcard($pattern, $id)) {
                $onlyMatch = true;
                break;
            }
        }
    }
    $exceptMatch = false;
    foreach ($this->except as $pattern) {
        if (StringHelper::matchWildcard($pattern, $id)) {
            $exceptMatch = true;
            break;
        }
    }
    return !$exceptMatch && $onlyMatch;
}

            
overrideDefaultSettings() 公共方法

覆盖特定操作的设置。

public void overrideDefaultSettings ( $action )
$action yii\base\Action

要覆盖的动作设置

                public function overrideDefaultSettings($action)
{
    if (isset($this->actions[$action->id])) {
        $actionParams = $this->actions[$action->id];
        $actionParamsKeys = array_keys($actionParams);
        foreach ($this->cors as $headerField => $headerValue) {
            if (in_array($headerField, $actionParamsKeys)) {
                $this->cors[$headerField] = $actionParams[$headerField];
            }
        }
    }
}

            
prepareAllowHeaders() 受保护方法

处理经典 CORS 请求以避免重复代码。

protected void prepareAllowHeaders ( $type, $requestHeaders, &$responseHeaders )
$type string

我们要处理的标题类型

$requestHeaders array

客户端请求的 CORS 标头

$responseHeaders array

发送给客户端的 CORS 响应标头

                protected function prepareAllowHeaders($type, $requestHeaders, &$responseHeaders)
{
    $requestHeaderField = 'Access-Control-Request-' . $type;
    $responseHeaderField = 'Access-Control-Allow-' . $type;
    if (!isset($requestHeaders[$requestHeaderField], $this->cors[$requestHeaderField])) {
        return;
    }
    if (in_array('*', $this->cors[$requestHeaderField])) {
        $responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]);
    } else {
        $requestedData = preg_split('/[\\s,]+/', $requestHeaders[$requestHeaderField], -1, PREG_SPLIT_NO_EMPTY);
        $acceptedData = array_uintersect($requestedData, $this->cors[$requestHeaderField], 'strcasecmp');
        if (!empty($acceptedData)) {
            $responseHeaders[$responseHeaderField] = implode(', ', $acceptedData);
        }
    }
}

            
prepareHeaders() 公共方法

为每个 CORS 头部创建特定的响应。

public array prepareHeaders ( $requestHeaders )
$requestHeaders array

我们检测到的 CORS 标头

返回值 array

准备发送的 CORS 标头

                public function prepareHeaders($requestHeaders)
{
    $responseHeaders = [];
    // handle Origin
    if (isset($requestHeaders['Origin'], $this->cors['Origin'])) {
        if (in_array($requestHeaders['Origin'], $this->cors['Origin'], true)) {
            $responseHeaders['Access-Control-Allow-Origin'] = $requestHeaders['Origin'];
        }
        if (in_array('*', $this->cors['Origin'], true)) {
            // Per CORS standard (https://fetch.spec.whatwg.org), wildcard origins shouldn't be used together with credentials
            if (isset($this->cors['Access-Control-Allow-Credentials']) && $this->cors['Access-Control-Allow-Credentials']) {
                if (YII_DEBUG) {
                    throw new InvalidConfigException("Allowing credentials for wildcard origins is insecure. Please specify more restrictive origins or set 'credentials' to false in your CORS configuration.");
                } else {
                    Yii::error("Allowing credentials for wildcard origins is insecure. Please specify more restrictive origins or set 'credentials' to false in your CORS configuration.", __METHOD__);
                }
            } else {
                $responseHeaders['Access-Control-Allow-Origin'] = '*';
            }
        }
    }
    $this->prepareAllowHeaders('Headers', $requestHeaders, $responseHeaders);
    if (isset($requestHeaders['Access-Control-Request-Method'])) {
        $responseHeaders['Access-Control-Allow-Methods'] = implode(', ', $this->cors['Access-Control-Request-Method']);
    }
    if (isset($this->cors['Access-Control-Allow-Credentials'])) {
        $responseHeaders['Access-Control-Allow-Credentials'] = $this->cors['Access-Control-Allow-Credentials'] ? 'true' : 'false';
    }
    if (isset($this->cors['Access-Control-Max-Age']) && $this->request->getIsOptions()) {
        $responseHeaders['Access-Control-Max-Age'] = $this->cors['Access-Control-Max-Age'];
    }
    if (isset($this->cors['Access-Control-Expose-Headers'])) {
        $responseHeaders['Access-Control-Expose-Headers'] = implode(', ', $this->cors['Access-Control-Expose-Headers']);
    }
    if (isset($this->cors['Access-Control-Allow-Headers'])) {
        $responseHeaders['Access-Control-Allow-Headers'] = implode(', ', $this->cors['Access-Control-Allow-Headers']);
    }
    return $responseHeaders;
}