Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 流\u上下文\u使用基于域名的HTTP选项创建_Php_Xml_Xslt_Cookies - Fatal编程技术网

Php 流\u上下文\u使用基于域名的HTTP选项创建

Php 流\u上下文\u使用基于域名的HTTP选项创建,php,xml,xslt,cookies,Php,Xml,Xslt,Cookies,如何告诉使用stream\u context\u create()创建的streamContext根据请求URI的域名使用不同的HTTP头? 我使用XSL在服务器端(PHP)转换XML 为此,我首先创建一个带有一些选项的流上下文,并将此流应用于libxml: $streamContextOptions = array( 'http' =>array( 'header'=>$clientHeadersString /* HTTP header */ )

如何告诉使用
stream\u context\u create()
创建的streamContext根据请求URI的域名使用不同的HTTP头?

我使用XSL在服务器端(PHP)转换XML

为此,我首先创建一个带有一些选项的流上下文,并将此流应用于
libxml

$streamContextOptions = array(
    'http' =>array(
        'header'=>$clientHeadersString /* HTTP header */
    )
);
$streamContext = stream_context_create($streamContextOptions);
libxml_set_streams_context($streamContext);
然后加载XML、XSL并进行转换

// Load the XML
$xmlDocument = new DOMDocument();
$xmlDocument->load($xmlURI);

// Load the XSL into
$xslDocument = new DOMDocument();
$xslDocument->load($xslURI);
$xslProcessor = new XSLTProcessor();
$xslProcessor->importStylesheet($xslDocument);

// Apply the XSL
$htmlDocument = $xslProcessor->transformToDoc($xmlDocument);
在XSL中,我有一些
document()
调用,因此PHP服务器使用流上下文调用指定的URI。但是我在这些
document()
调用中有不同的域(比如说我有www.foo.com和www.bar.com)


是否有方法告诉XSLTProcessor根据
document()
函数请求的域更改流选项?

也许您可以代理请求?即
文档('//mydomain/?doc=origin doc')


通过这种方式,您可以根据需要修改请求(例如使用cURL)。doc参数可用于有条件地修改请求。

对于流上下文选项,您无法区分不同的主机,因为通过流I/O操作,已分配了上下文-没有根据主机名进行差异的空间(对于PHP中的流,这也是不可能的。至少是AFAIK)

因此,您需要为URI分配适当的流选项

在您的场景中,在DOM设置之后但在转换之前,通过创建能够根据主机名不同的上下文选项,我认为这是最容易做到的:

...

$xslProcessor->importStylesheet($xslDocument);

$httpOptions       = [
    'timeout' => 1,
    'header'  => "User-Agent: Godzilla Gabba Gandalf Client 42.4 - Lord of the XSLT Weed Edition"
];
$httpOptionsByHost = [
    'www.foo.com' => [
        'header' => "X-Secret-Debug-Request-Flag: verbose-verbose-verbose"
    ],
    'www.bar.com' => [
        'header' => "User-Agent: 1' OR TRUE"
    ]
];

libxml_set_external_entity_loader(
    function ($public, $system, $context) use ($httpOptions, $httpOptionsByHost) {

        $url = new Net_URL2($system);
        $url->normalize();
        $host = $url->getHost();

        $options['http'] = [];

        if (isset($httpOptionsByHost[$host])) {
            $options['http'] = $httpOptionsByHost[$host];
        }

        $options['http'] += $httpOptions;

        $context = stream_context_create($options);

        return fopen($url, 'r', false, $context);
    }
);

// Apply the XSL
$htmlDocument = $xslProcessor->transformToDoc($xmlDocument);

...
您在问题中没有提供XML,外部URI也不起作用,因此我只能进行部分测试,但就我所能验证的而言,这应该是可行的


您可能需要在外部实体加载器函数中有更多不同之处,因为您可能会加载其他不应同等处理的实体。但是我想您可以找到答案。

您的外部资源不是依赖于请求头吗?Imho资源应该是静态和可缓存的。@RolandFranssen否,因为XML资源可能是用户的配置文件数据(用户名、化身、邮件…)。所以用户必须先登录才能检索这种XML。返回的XML也可以基于本地化数据的
Accept Language
libxml\u set\u external\u entity\u loader()
是否适用于XSL内部的
document()
调用?或者我必须在XML中切换并使用
实体
,而不是在XSL中使用
document()
?它适用于XSL中的
document()
调用,否则我不会建议这样做。在我的测试中,我可以为XSL文件中
document()
内的两个不同URI中的两个不同主机名创建两个不同的流上下文。因此,使用代理,当在客户端解析XSL时,浏览器将发送
mydomain
凭据(并代理到
otherDomain
),而不是使用正确的凭据直接调用
otherDomain
。我知道服务器端的
mydomain
不会有
otherDomain
凭据,但我希望
otherDomain
在服务器端被称为无凭据,在客户端被称为完全凭据。实际上,由于Chrome(webkit?)不接受XML/XSL文档的CORS,我将使用这种方式,并坚持使用本地URI(整个XSL只有一个流上下文)如果需要,由服务器提供。
$streamContextOptions = array(
    'http-for-foo' =>array(
        'header'=>$clientHeadersStringForFoo /* HTTP header only when document() calls for foo.com*/
    ),
    'http-for-bar' =>array(
        'header'=>$clientHeadersStringForBar /* HTTP header only when document() calls for bar.com*/
    )
);
...

$xslProcessor->importStylesheet($xslDocument);

$httpOptions       = [
    'timeout' => 1,
    'header'  => "User-Agent: Godzilla Gabba Gandalf Client 42.4 - Lord of the XSLT Weed Edition"
];
$httpOptionsByHost = [
    'www.foo.com' => [
        'header' => "X-Secret-Debug-Request-Flag: verbose-verbose-verbose"
    ],
    'www.bar.com' => [
        'header' => "User-Agent: 1' OR TRUE"
    ]
];

libxml_set_external_entity_loader(
    function ($public, $system, $context) use ($httpOptions, $httpOptionsByHost) {

        $url = new Net_URL2($system);
        $url->normalize();
        $host = $url->getHost();

        $options['http'] = [];

        if (isset($httpOptionsByHost[$host])) {
            $options['http'] = $httpOptionsByHost[$host];
        }

        $options['http'] += $httpOptions;

        $context = stream_context_create($options);

        return fopen($url, 'r', false, $context);
    }
);

// Apply the XSL
$htmlDocument = $xslProcessor->transformToDoc($xmlDocument);

...