如何说服 Zend Framework 发送重复的 headers?

How to convince Zend Framework to send duplicate headers?

对于Content-Security-Policy header,通常需要发送多个这样的header,或者在发送之前合并这些header。这是因为应用程序的每个 module/package 都可以定义自己的 CSP。

目前ZF3似乎没有办法处理这种情况。如果我尝试添加多个 CSP header,它们会不断相互覆盖,因此只会发送最后添加的 header。

重现问题的代码

$headers = $controller->getResponse()->getHeaders();
$headers->addHeader(new ContentSecurityPolicy($someDirectives));
$headers->addHeader(new ContentSecurityPolicy($someOtherDirectives));

预期结果

预期结果是具有两个 CSP header 的响应(或联合合并的 CSP)。

实际结果

第二次添加会覆盖第一次,响应只包含那个 CSP。

问题

如何让 ZF3 发送具有相同字段名的多个 header?


有关此问题的更多信息,另请参阅我自己在 github https://github.com/zendframework/zend-http/issues/159

上的问题

您应该能够使用 GenericMultipleHeader 作为参考(并将逗号分隔符更改为分号)创建一个简单的解决方法:

class MultiContentSecurityPolicy extends ContentSecurityPolicy implements MultipleHeaderInterface {

    public static function fromString($headerLine)
    {
        list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
        if (strpos($fieldValue, ';')) {
            $headers = [];
            foreach (explode(';', $fieldValue) as $multiValue) {
                $headers[] = new static($fieldName, $multiValue);
            }
            return $headers;
        } else {
            $header = new static($fieldName, $fieldValue);
            return $header;
        }
    }

    public function toStringMultipleHeaders(array $headers)
    {
        $name  = $this->getFieldName();
        $values = [$this->getFieldValue()];
        foreach ($headers as $header) {
            if (! $header instanceof static) {
                throw new Exception\InvalidArgumentException(
                    'This method toStringMultipleHeaders was expecting an array of headers of the same type'
                );
            }
            $values[] = $header->getFieldValue();
        }
        return $name . ': ' . implode(';', $values) . "\r\n";
    }

}

然后使用 class 而不是 ContentSecurityPolicy:

$headers = $controller->getResponse()->getHeaders();
$headers->addHeader(new MultiContentSecurityPolicy($someDirectives));
$headers->addHeader(new MultiContentSecurityPolicy($someOtherDirectives));

自 Zend checks the interface rather than the class 以来,应该可以正常工作。

这是公认的 HTTP 标准,PHP 核心支持这一标准。 http://php.net/manual/en/function.header.php

如果您在 PHP header("TESTHeader: Test1"); header("TESTHeader: Test2") 中设置 headers,则只有一个会通过,这符合规范 RFC2616 Section 4.2 Page 31&32

如果您希望发送多个值,您的 header 应该构建为 header("TESTHeader: Test1, Test2");。虽然可以通过 PHP 发送多个相同名称的 headers,但不推荐,因为浏览器和服务器接收 2 组相同的 header 应该将它们转换为上述样式,这可能会导致问题,因为您无法确定它们的格式。header("TESTHeader: Test1", false); header("TESTHeader: Test2", false)。取决于服务器或客户端是否遵守 RFC 或 HTTP 版本。

所以这个答案就是为什么你不能在 ZF3 中多次发送相同的 header 的原因,它无法根据你设置的header。要解决这个问题并使用 multi-valued headers 你可以使用 Jim's answer

创建您自己的多页眉 class,添加您需要的功能 (MultipleHeaderInterface),然后在多线程中添加您的页眉,最后在您的

中调用它
$headers = $controller->getResponse()->getHeaders();

(使用新的 fromStringHeaders 调用新函数)