我已经坚持这个问题几个小时了:我正在使用PHP和cURL编写一种PHP代理。几乎一切正常,设置cookie,处理重定向,并使用POST提交表单。
基本上,我正在尝试使用本地代理镜像远程网站。为此,我将每个请求重定向到http://localhost/resource
到http://localhost/proxy.php?url=http://remotesite.com/resource
,这将获取远程网站上的资源。重定向由.htaccess上的404错误页面处理,但我想使用mod_rewrite不会改变。
我正在远程服务器上部署的复杂应用程序(最新版本的WordPress)上测试我的代理。 WordPress登录工作正常并使用POST。但是,我找到了一个更新表单不起作用的页面,并且所有POST数据都没有发送到服务器。
这是我看到wireshark在loopback接口上监听的内容:
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变量在一个数组中(附件[691] [menu_order] = 0;附件[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 );
[...]
答案 0 :(得分:0)
为什么不从$ _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/)
它可能会做得更好(也更快)。