如何根据请求的URI的域名告诉使用stream_context_create()
创建的streamContext使用不同的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)。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<xsl:value-of select="document('http://www.foo.com/with-user-agent.xml.php')/root"/>
<xsl:value-of select="document('http://www.bar.com/with-accept-language.php')/root"/>
</xsl:template>
</xsl:stylesheet>
我想要的是更改libxml在XSL内进行document()
调用时使用的HTTP头,这样我就可以将[cookies + user-agent]发送到foo.com,以及[其他cookie +当在XSL document()
电话中请求时,bar.com接受语言。
我不想发送太多&#34;标题为foo.com(也就是说,我不想发送Accept-Language
到foo.com),也不是bar.com,我也不想把cookie混在一起(cookies发送到foo) .com不得发送到bar.com)。
不知何故,如:
$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*/
)
);
有没有办法告诉XSLTProcessor根据document()
函数请求的域更改streamOptions?
答案 0 :(得分:1)
您不能告诉流上下文选项的不同主机,因为使用流I / O操作,已分配上下文 - 根据主机名,libxml_set_streams_context
没有空间不同(也适用于PHP中的流)这也是不可能的。至少AFAIK)。
因此,您需要为URI分配适当的流选项。
在您的方案中,我觉得在 DOM设置之后最容易完成 转换之前通过创建your own external entity loader来实现基于主机名的上下文选项:
...
$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工作,所以我只能部分测试,但据我可以验证,这应该有效。
您可能需要在外部实体加载程序功能方面有所不同,因为您可能需要加载其他其他实体,而这些实体不应该被平等处理。但我认为你可以解决这个问题。
答案 1 :(得分:0)
也许您可以代理请求?即document('//mydomain/?doc=origin-doc')
这样您就可以根据需要修改请求(例如使用cURL)。 doc参数可用于有条件地修改请求。