2012-02-05 71 views
10

我试图通过PHP cURL登录到一个网站,我只收到“错误的请求”响应。PHP cURL内容长度和内容类型错误

我玩过hosts文件并将其设置到我的服务器,以检查我的浏览器发送了哪个请求头,并将其与由cURL发送的请求头进行比较。

一切都是平等的,除外:

浏览器:

Content-Type: application/x-www-form-urlencoded 
Content-Length: 51 

PHP卷曲:

Content-Length: 51, 359 
Content-Type: application/x-www-form-urlencoded; boundary=----------------------------5a377b7e6ba7 

我已经设定值,使用此命令,但它仍然发出了错误的头:

curl_setopt($this->hCurl, CURLOPT_HTTPHEADER, array(
    'Expect:', 
    'Content-Type: application/x-www-form-urlencoded', 
    'Content-Length: 51' 
)); 

回答

31

您不应该自己设置内容长度。如果您使用cURL发送HTTP POST,它将为您计算内容长度。

如果您将CURLOPT_POSTFIELDS值设置为数组,它将自动提交请求multipart/form-data并使用边界。如果你传递一个字符串,它将使用application/x-www-form-urlencoded,所以确保你传递一个urlencoded字符串到CURLOPT_POSTFIELDS而不是一个数组,因为你想要表单urlencoded。

你必须这样做:

$data = 'name=' . urlencode($value) . '&name2=' . urlencode($value2); 
curl_setopt($this->hCurl, CURLOPT_POSTFIELDS, $data); 

// NOT 

$dataArray = array('name' => 'value', 'name2' => 'value2'); 
curl_setopt($this->hCurl, CURLOPT_POSTFIELDS, $dataArray); 

在这两种情况下,你不需要设置内容长度,但你必须使用第一种方法来获取表单上application/x-www-form-urlencoded编码。

如果这没有帮助,请发布与设置curl请求相关的所有代码(所有选项以及您传递给它的数据),这应该有助于解决问题。

编辑:

添加是我想出了工作(我得到失败的登录)的一个例子。

<?php 

$URL_HOME = 'http://ilocalis.com/'; 
$LOGIN_URL = 'https://ilocalis.com/login.php'; 

$ch = curl_init($URL_HOME); 
curl_setopt($ch, CURLOPT_HEADER, 0); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 

$home = curl_exec($ch); 

//echo $home; 

$post = array('username' => 'drew', 'password' => 'testing 123'); 
$query = http_build_query($post); 

curl_setopt($ch, CURLOPT_URL, $LOGIN_URL); 
curl_setopt($ch, CURLOPT_POST, 1); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $query); 

$login = curl_exec($ch); 

echo $login; 
+1

感谢您的评论,我不知道传递数组和传递字符串是有区别的。但http_build_query($ array)也应该可以工作,不是吗?无论如何 - 不幸的是,它也不管用。当我自己没有指定内容长度时,页面返回“HTTP错误411长度要求”错误。我正在尝试登录http://ilocalis.com/(发布到https://ilocalis.com/login.php) - 如果您想自己尝试,则不需要帐户,因为我甚至不要来加载页面,并检查给定的凭据是否正确...谢谢! – Simon 2012-02-07 18:39:20

+0

由于内容长度未设置,我不知道请求方法是不是POST,或者也许其他一些选项重写。无论如何,我通过一个实例更新了这篇文章。希望它能让你走上正轨。它使用1个卷曲对象来创建2个独立的请求。请注意,如果您需要再次进行GET查询,则必须将CURLOPT_POST重置为0. – drew010 2012-02-07 23:42:50

+0

谢谢。您。所以。许多。我没有看到树木的森林。我将curlopt_customrequest设置为“POST”,因为我用来传递一个数组到curlopt_postfields .....使用一个字符串,因为你已经提到它应该工作,但我偶然忘记删除customrequest的东西..这是小事情,怪胎当我们不明白为什么它不起作用时,我们程序员的狗屎......;) – Simon 2012-02-08 09:10:19