【问题标题】:cURL not sending POST data in some requestscURL 未在某些请求中发送 POST 数据
【发布时间】:2011-12-11 02:51:27
【问题描述】:

我已经被这个问题困扰了几个小时:我正在使用 PHP 和 cURL 来编写一种 PHP 代理。几乎一切正常,设置 cookie、处理重定向和使用 POST 提交表单。

基本上,我正在尝试使用本地代理镜像远程网站。为此,我将每个请求重定向到http://localhost/resourcehttp://localhost/proxy.php?url=http://remotesite.com/resource,这将获取远程网站上的资源。重定向由 .htaccess 上的 404 错误页面处理,但我想使用 mod_rewrite 不会改变任何事情。

我正在远程服务器上部署的复杂应用程序(最新版本的 WordPress)上测试我的代理。 WordPress 登录工作正常并使用 POST。但是,我发现一个页面无法更新表单,并且根本没有将所有 POST 数据发送到服务器。

这是我在使用wireshark 监听环回接口时看到的:

POST /proxy/wp-admin/media.php?attachment_id=691&action=edit HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.23) Gecko/20110921 Ubuntu/10.04 (lucid) Firefox/3.6.23
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost/proxy/wp-admin/media.php?attachment_id=691&action=edit
Cookie: [snip]
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 501

attachments%5B691%5D%5Bmenu_order%5D=0&attachments%5B691%5D%5Bpost_title%5D=fb&attachments%5B691%5D%5Bimage_alt%5D=&attachments%5B691%5D%5Bpost_excerpt%5D=&attachments%5B691%5D%5Bpost_content%5D=foobar&attachments%5B691%5D%5Burl%5D=http%3A%2F%2Flocalhost%2Fproxy%2Fwp-content%2Fuploads%2F2009%2F04%2Ffb.gif&save=Aggiorna+media&post_id=&attachment_id=691&action=editattachment&_wp_original_http_referer=&_wpnonce=02caf30462&_wp_http_referer=%2Fwp-admin%2Fmedia.php%3Fattachment_id%3D691%26action%3Dedit

HTTP/1.1 200 OK
Date: Wed, 19 Oct 2011 16:18:56 GMT
Server: Apache/2.2.14 (Ubuntu)
X-Powered-By: PHP/5.3.2-1ubuntu4.10
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 5441
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

[content]

同时,如果在连接到互联网的接口上监听,我看到的是:

POST /wp-admin/media.php?attachment_id=691&action=edit HTTP/1.1
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.23) Gecko/20110921 Ubuntu/10.04 (lucid) Firefox/3.6.23
Host: www.remotesite.com
Accept: */*
Referer: http://www.remotesite.com/wp-admin/media.php?attachment_id=691&action=edit
Cookie: [snip]
X-Forwarded-For: 127.0.0.1
Content-Length: 0
Content-Type: application/x-www-form-urlencoded

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Wed, 19 Oct 2011 16:25:13 GMT
Server: LiteSpeed
Connection: close
X-Powered-By: PHP/5.2.17
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Last-Modified: Wed, 19 Oct 2011 16:25:13 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Pragma: no-cache
X-Frame-Options: SAMEORIGIN
Content-Type: text/html; charset=UTF-8

[content]

如您所见,我的代理没有将发布数据传输到远程服务器。 我希望这个问题与 POSTDATA 的编码有关,因为在这种情况下 POST 变量在一个数组中 (attachments[691][menu_order]=0; attachments[691][post_content]=foobar 等等... )。

我尝试了一些类似帖子所建议的更改,但根本没有设法更改脚本的行为。这一切都是因为显然第一个(本地)POST 将数据发送到 localhost,但 cURL 无法获取 POST 数据(实际上,下面代码中的 file_get_contents("php://input") 读取 0 个字节)。

我在这里粘贴了我的部分代码,希望有人可以帮助我:

$ch = curl_init( $url );
$headers = array();
if ( isset($_SERVER['CONTENT_TYPE']) ) {
    // commenting this out or changing to multipart/form-data does not change anything
    array_push($headers, "Content-Type: ".$_SERVER['CONTENT_TYPE'] );
}
if ( count($headers) > 0 ) {
        curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
}
$postdata = file_get_contents("php://input");  //this turns out to be empty - and so is $_POST

//REQUEST METHOD: since pages are redirected from a 404 error page, we have to handle
//a redirect, so the real method is specified in REDIRECT_REQUEST_METHOD
if ( isset($_SERVER['REDIRECT_REQUEST_METHOD']) && isset($postdata) ){
    if ($_SERVER['REDIRECT_REQUEST_METHOD'] == 'POST'){
        curl_setopt( $ch, CURLOPT_POST, true );
    }
}
else{
    if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' ){
                curl_setopt( $ch, CURLOPT_POST, true );
    }
}
if ( isset($_SERVER['CONTENT_LENGTH'] ) && $_SERVER['CONTENT_LENGTH'] > 0 ) {
    curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata );
}

//set cookies
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookietofwd');
curl_setopt($ch, CURLOPT_COOKIEFILE,'/tmp/cookietofwd');
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $ch, CURLOPT_HEADER, true );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );

$out=curl_exec( $ch );
[...]

【问题讨论】:

  • 这听起来可能有点不靠谱,但请尝试在该请求上调用 phpinfo() 以查看它是否是 PHP 破坏了某些东西,或者您的服务器是否正在损坏它。您要查找的信息应位于底部的“环境”或“PHP 变量”部分下。
  • 感谢@GigaWatt,phpinfo() 不显示任何 POST 数据。由于我坚持这一点,我启用了 mod_rewrite 以使用它来处理重定向,而不是使用 404 错误处理程序。现在正在传递 POST 数据。尽管如此,我还是不明白为什么以前的方法不起作用,因为不使用数组的普通 POST 正常通过没有任何问题。

标签: php post curl proxy


【解决方案1】:

为什么不从 $_POST 获取 POST 数据? application/x-www-form-urlencoded 标头似乎是 AJAX 请求而不是常规 POST,我不确定 php://input 是如何处理的。

你可以这样:

curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query($_POST) );

您是否有特定的原因需要在 PHP 中使用它?为什么不直接使用 nginx? (http://nginx.org/en/)

它可能会做得更好(更快)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-06
    • 1970-01-01
    • 2021-07-27
    • 2018-08-16
    • 1970-01-01
    相关资源
    最近更新 更多