cURL 和重定向 - 返回多个标题?

Posted

技术标签:

【中文标题】cURL 和重定向 - 返回多个标题?【英文标题】:cURL and redirects - returning multiple headers? 【发布时间】:2011-04-30 09:29:14 【问题描述】:

我正在编写一个专门的 php 代理,但被 cURL 的一个特性难住了。

如果设置了以下值:

curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $ch, CURLOPT_HEADER, true );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );

cURL 正确处理重定向,但返回所有页面标题,而不仅仅是最终(非重定向)页面,例如

HTTP/1.1 302 Found
Location: http://otherpage
Set-Cookie: someCookie=foo
Content-Length: 198

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3241

<!DOCTYPE HTML>
...rest of content

请注意,设置了 CURLOPT_HEADER 是因为我需要读取原始标头的一部分并将其复制到我的代理标头中。

我理解为什么它会返回所有这些标头(例如,我的代理代码必须检测 302 标头中设置的任何 cookie 并将它们传递)。但是,它也使得无法检测到标头何时结束以及内容何时开始。通常,只有一个标题,我们可以做一个简单的拆分:

$split = preg_split('/\r\n\r\n/', $fullPage, 2)

但这显然在这里行不通。嗯。我们可以尝试只在下一行是标题的一部分时才拆分的方法:

$split = preg_split('/\r\n\r\nHTML\/(1\.0|1\.1) \\d+ \\w+/', $fullPage)
// matches patterns such a "\r\n\r\nHTML/1.1 302 Found"

这几乎一直有效,但如果有人在他们的页面中有以下内容,就会窒息:

...and for all you readers out there, here is an example HTTP header:
<PRE>

HTTP/1.1 200 OK

球!

我们真的希望拆分在遇到\r\n\r\n 的任何模式时立即停止匹配,而HTML/1.x 没有紧随其后 - 有没有办法使用 PHP RegExs 做到这一点?即使是这种解决方案也可能会在某人将 HTTP 标头放在其内容的开头的(非常罕见的)情况下窒息。 cURL 中有没有办法将所有返回的页面作为数组获取?

【问题讨论】:

【参考方案1】:

你可以得到总头大小的信息,把字符串拆分成这样:

$buffer = curl_exec($ch);
$curl_info = curl_getinfo($ch);
curl_close($ch);
$header_size = $curl_info["header_size"];
$header = substr($buffer, 0, $header_size);
$body = substr($buffer, $header_size)

信息取自the helpful post by "grandpa"。

【讨论】:

很好的建议,我一直在想这个问题,每次我得到一个可能不是最后一个的已知 http 状态时,我都会检查接下来的几个标头。 $body = substr($buffer, $header_size + 1) => 这将删除正文的第一个字符。 substr($buffer, $header_size) 是正确的 @Claude:感谢指正!编辑以反映它。当您看到此类错误时,请随意点击按钮以建议更改答案;这样,即使作者早已不在,模组也可以进行修正。 当前面的页面(重定向跃点)返回响应正文以及 http 301/302 标头时,这将不起作用。示例:[moebel.de/dekoration/pflanzen/kunstpflanzen], [delta.com/skymiles/manage_account/skymiles_pin/index.jsp]【参考方案2】:
$header_size = $curl_info["header_size"];
$header = substr($buffer, 0, $header_size-1);
$body = substr($buffer, $header_size);

【讨论】:

【参考方案3】:

使用curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);

TRUE 后跟服务器作为 HTTP 标头的一部分发送的任何“Location:”标头(注意这是递归的,PHP 将跟随着它发送的尽可能多的“Location:”标头,除非设置了 CURLOPT_MAXREDIRS)。

【讨论】:

对不起,我只是想提一下重要性【参考方案4】:

需要添加,到 curl 配置:

curl_setopt( $ch, CURLOPT_HTTPHEADER, array("Expect:"));

这将解决问题。

【讨论】:

以上是关于cURL 和重定向 - 返回多个标题?的主要内容,如果未能解决你的问题,请参考以下文章

请求的转发和重定向

JSP转发和重定向之间的区别[重复]

spring 转发forward和重定向redirect

Servlet - 请求转发和重定向

HttpServlet的转发和重定向

ASP HttpWebRequest 和重定向