curl POST 作为 GET 执行
Curl POST is executed as a GET
我正在尝试用 PHP
开发一种浏览器。
到目前为止,我的 class
可以使用此 Content Type
处理 GET
或 POST
请求:application/x-www-form-urlencoded
.
现在我需要换一个 JSON
了。我已经将 Content-Type
header 设置为 application/json
.
事实是,对于这种类型,我遇到了以下问题:设置 POST 请求将导致 GET 请求。这真的很奇怪。
这是我的代码:
private function request($url, $reset_cookies, $post_data = null, $custom_headers = null)
{
// Create options
$options = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 0,
CURLINFO_HEADER_OUT => 1,
CURLOPT_FAILONERROR => 1,
CURLOPT_USERAGENT => $this->user_agent,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 10,
CURLOPT_AUTOREFERER => 1,
CURLOPT_COOKIESESSION => $reset_cookies ? 1 : 0,
CURLOPT_COOKIEJAR => $this->cookies_file,
CURLOPT_COOKIEFILE => $this->cookies_file,
CURLOPT_HTTPHEADER => array('Accept-language: en'),
// SSL
/*
CURLOPT_SSL_CIPHER_LIST => 'TLSv1',
CURLOPT_SSL_VERIFYPEER => 1,
CURLOPT_CAINFO => dirname(__FILE__) . '/Entrust.netCertificationAuthority(2048).crt',
*/
);
// Add headers
if (isset($custom_headers)) $options[CURLOPT_HTTPHEADER] = array_merge($options[CURLOPT_HTTPHEADER], $custom_headers);
// Add POST data
if (isset($post_data))
{
$options[CURLOPT_POST] = 1;
$options[CURLOPT_POSTFIELDS] = is_string($post_data) ? $post_data : http_build_query($post_data);
}
// Attach options
curl_setopt_array($this->curl, $options);
// Execute the request and read the response
$content = curl_exec($this->curl);
print_r($options);
print_r(curl_getinfo($this->curl, CURLINFO_HEADER_OUT));
// Clean local variables
unset($url);
unset($reset_cookies);
unset($post_data);
unset($custom_headers);
unset($options);
// Handle any error
if (curl_errno($this->curl))
{
unset($content);
throw new Exception(curl_error($this->curl));
}
return $content;
}
为了说明我的问题,这里有一个例子:
CUrl
选项作为 Array
:
Array
(
[10002] => http://mywebsite.com/post/
[19913] => 1
[42] => 0
[2] => 1
[45] => 1
[10018] => Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
[78] => 30
[13] => 30
[52] => 1
[68] => 10
[58] => 1
[96] => 0
[10082] => C:\wamp\www\v2\_libs/../_cookies/14d0fd2b-9f15-4ac5-8fae-4246cc6cef49.cookie
[10031] => C:\wamp\www\v2\_libs/../_cookies/14d0fd2b-9f15-4ac5-8fae-4246cc6cef49.cookie
[10023] => Array
(
[0] => Accept-language: en
[1] => RequestVerificationToken: 4PMxvJsQzFJ5oFt3JdUPe6Bp_geIj4obDJCYIRoU09PrrfcBSUgJT9iB3mXnGFc2KSlYrPcRHF7iHdQhGNu0GKLUzd5FywfaADbGS8wjhXraF36W0
[2] => Content-Type: application/json
)
[47] => 1
[10015] => {"usernameOrFeedId":"manitoba","feed_message_body":"Dummy message goes here"}
)
所以请求header对我来说似乎不错,但我可能错了。
这是 CUrl
发送的 real
header:
GET /post/ HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Host: mywebsite.com
Accept: */*
Referer: http://mywebsite.com/post/
Cookie: ADRUM_BT=R%3a53%7cclientRequestGUID%3a9787a51b-b24d-4400-9d6a-efbd618c74c0%7cbtId%3a18790%7cbtERT%3a44; CSRFToken=o_eoIVji7pWclOsrLaJpZEbOFSBJBm851rHbH0Xqwdzw2tC5j07EAc23mlj-opWowgpj0RkHyiktl1cS6onBqI43afM1; WebSessionId=3aem0m2xpwmvesgphna5gaop; prod=rd101o00000000000000000000ffff0a5a2a74o80; AuthenticateCookie=AAAAAtsQgeb8+UXrJ+wa7CGVJKnqizEAo2bMuFvqvwYMAl1NRaa6z68LBRx9hiHzPBC8tYqiayHID6pHChGXB7VywemwTpGivcRQ3nRlUVuaYQKyxQt21p1mx7OMlLCsRA==; web_lang.prod=fr
Accept-language: en
RequestVerificationToken: 4PMxvJsQzFJ5oFt3JdUPe6Bp_geIj4obDJCYIRoU09PrrfcBSUgJT9iB3mXnGFc2KSlYrPcRHF7iHdQhGNu0GKLUzd5FywfaADbGS8wjhXraF34W0
Content-Type: application/json
如您所见,这是一个 GET
请求,post 数据似乎已经消失。
我做错了吗?
CURLOPT_FOLLOWLOCATION
似乎是
显示的原因
Referer: http://mywebsite.com/post/
似乎服务器正在执行 PRG?
通过将其设置为 false 并从您的代码中删除 curlopt_maxredirs 来禁用跟踪位置。
CURLOPT_FOLLOWLOCATION => false,
// CURLOPT_MAXREDIRS => 10,
您正在跟踪重定向,这意味着您得到一个 3xx 响应代码并且 curl 向新 URL.
发出第二个请求
curl 将根据特定的 3xx 代码执行操作,对于某些重定向,它将 将 请求方法从 POST 更改为 GET - 启用 VERBOSE 将显示是否它这样做与否。使 curl 更改方法的响应代码是 301、302 和 303。之所以这样做,是因为浏览器就是这样处理这些响应代码的。
libcurl 提供了一个名为 CURLOPT_POSTREDIR 的选项,您可以使用该选项告诉 curl 不 更改特定 HTTP 响应的方法。使用它,即使在使用这些响应代码之一重定向后,您也可以让 curl 发送 POST。
我正在尝试用 PHP
开发一种浏览器。
到目前为止,我的 class
可以使用此 Content Type
处理 GET
或 POST
请求:application/x-www-form-urlencoded
.
现在我需要换一个 JSON
了。我已经将 Content-Type
header 设置为 application/json
.
事实是,对于这种类型,我遇到了以下问题:设置 POST 请求将导致 GET 请求。这真的很奇怪。
这是我的代码:
private function request($url, $reset_cookies, $post_data = null, $custom_headers = null)
{
// Create options
$options = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 0,
CURLINFO_HEADER_OUT => 1,
CURLOPT_FAILONERROR => 1,
CURLOPT_USERAGENT => $this->user_agent,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 10,
CURLOPT_AUTOREFERER => 1,
CURLOPT_COOKIESESSION => $reset_cookies ? 1 : 0,
CURLOPT_COOKIEJAR => $this->cookies_file,
CURLOPT_COOKIEFILE => $this->cookies_file,
CURLOPT_HTTPHEADER => array('Accept-language: en'),
// SSL
/*
CURLOPT_SSL_CIPHER_LIST => 'TLSv1',
CURLOPT_SSL_VERIFYPEER => 1,
CURLOPT_CAINFO => dirname(__FILE__) . '/Entrust.netCertificationAuthority(2048).crt',
*/
);
// Add headers
if (isset($custom_headers)) $options[CURLOPT_HTTPHEADER] = array_merge($options[CURLOPT_HTTPHEADER], $custom_headers);
// Add POST data
if (isset($post_data))
{
$options[CURLOPT_POST] = 1;
$options[CURLOPT_POSTFIELDS] = is_string($post_data) ? $post_data : http_build_query($post_data);
}
// Attach options
curl_setopt_array($this->curl, $options);
// Execute the request and read the response
$content = curl_exec($this->curl);
print_r($options);
print_r(curl_getinfo($this->curl, CURLINFO_HEADER_OUT));
// Clean local variables
unset($url);
unset($reset_cookies);
unset($post_data);
unset($custom_headers);
unset($options);
// Handle any error
if (curl_errno($this->curl))
{
unset($content);
throw new Exception(curl_error($this->curl));
}
return $content;
}
为了说明我的问题,这里有一个例子:
CUrl
选项作为 Array
:
Array
(
[10002] => http://mywebsite.com/post/
[19913] => 1
[42] => 0
[2] => 1
[45] => 1
[10018] => Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
[78] => 30
[13] => 30
[52] => 1
[68] => 10
[58] => 1
[96] => 0
[10082] => C:\wamp\www\v2\_libs/../_cookies/14d0fd2b-9f15-4ac5-8fae-4246cc6cef49.cookie
[10031] => C:\wamp\www\v2\_libs/../_cookies/14d0fd2b-9f15-4ac5-8fae-4246cc6cef49.cookie
[10023] => Array
(
[0] => Accept-language: en
[1] => RequestVerificationToken: 4PMxvJsQzFJ5oFt3JdUPe6Bp_geIj4obDJCYIRoU09PrrfcBSUgJT9iB3mXnGFc2KSlYrPcRHF7iHdQhGNu0GKLUzd5FywfaADbGS8wjhXraF36W0
[2] => Content-Type: application/json
)
[47] => 1
[10015] => {"usernameOrFeedId":"manitoba","feed_message_body":"Dummy message goes here"}
)
所以请求header对我来说似乎不错,但我可能错了。
这是 CUrl
发送的 real
header:
GET /post/ HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Host: mywebsite.com
Accept: */*
Referer: http://mywebsite.com/post/
Cookie: ADRUM_BT=R%3a53%7cclientRequestGUID%3a9787a51b-b24d-4400-9d6a-efbd618c74c0%7cbtId%3a18790%7cbtERT%3a44; CSRFToken=o_eoIVji7pWclOsrLaJpZEbOFSBJBm851rHbH0Xqwdzw2tC5j07EAc23mlj-opWowgpj0RkHyiktl1cS6onBqI43afM1; WebSessionId=3aem0m2xpwmvesgphna5gaop; prod=rd101o00000000000000000000ffff0a5a2a74o80; AuthenticateCookie=AAAAAtsQgeb8+UXrJ+wa7CGVJKnqizEAo2bMuFvqvwYMAl1NRaa6z68LBRx9hiHzPBC8tYqiayHID6pHChGXB7VywemwTpGivcRQ3nRlUVuaYQKyxQt21p1mx7OMlLCsRA==; web_lang.prod=fr
Accept-language: en
RequestVerificationToken: 4PMxvJsQzFJ5oFt3JdUPe6Bp_geIj4obDJCYIRoU09PrrfcBSUgJT9iB3mXnGFc2KSlYrPcRHF7iHdQhGNu0GKLUzd5FywfaADbGS8wjhXraF34W0
Content-Type: application/json
如您所见,这是一个 GET
请求,post 数据似乎已经消失。
我做错了吗?
CURLOPT_FOLLOWLOCATION
似乎是
显示的原因Referer: http://mywebsite.com/post/
似乎服务器正在执行 PRG?
通过将其设置为 false 并从您的代码中删除 curlopt_maxredirs 来禁用跟踪位置。
CURLOPT_FOLLOWLOCATION => false,
// CURLOPT_MAXREDIRS => 10,
您正在跟踪重定向,这意味着您得到一个 3xx 响应代码并且 curl 向新 URL.
发出第二个请求curl 将根据特定的 3xx 代码执行操作,对于某些重定向,它将 将 请求方法从 POST 更改为 GET - 启用 VERBOSE 将显示是否它这样做与否。使 curl 更改方法的响应代码是 301、302 和 303。之所以这样做,是因为浏览器就是这样处理这些响应代码的。
libcurl 提供了一个名为 CURLOPT_POSTREDIR 的选项,您可以使用该选项告诉 curl 不 更改特定 HTTP 响应的方法。使用它,即使在使用这些响应代码之一重定向后,您也可以让 curl 发送 POST。