如何在 PHP 中通过 HTTPS 发出 POST 请求?
我尝试使用 YouTube API 及其 ClientLogin。这意味着我需要向他们的服务器发出 POST 请求。
我发现这个简洁的函数可以进行 POST 调用(见下文),但它不使用 HTTPS,我认为我必须使用 HTTPS。这一切都有效,但我认为我的 POST 请求正在转发到 HTTPS,因此它没有给我正确的回调。当我尝试 var_dump
时,返回的数据网页会重新加载,最终会出现 https ://www.google.com/accounts/ClientLogin 我可以在其中获得正确的数据。但当然我需要这些数据作为数组或字符串。
那么如何使用 HTTPS 发出 POST 请求呢?
下面是我的代码(我在Jonas' Snippet Library找到):
function post_request($url, $data, $referer='') {
$data = http_build_query($data);
$url = parse_url($url);
$host = $url['host'];
$path = $url['path'];
$fp = fsockopen($host, 80, $errno, $errstr, 30);
if ($fp){
fputs($fp, "POST $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
if ($referer != '')
fputs($fp, "Referer: $referer\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ". strlen($data) ."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $data);
$result = '';
while(!feof($fp)) {
$result .= fgets($fp, 128);
}
}
else {
return array(
'status' => 'err',
'error' => "$errstr ($errno)"
);
}
fclose($fp);
$result = explode("\r\n\r\n", $result, 2);
$header = isset($result[0]) ? $result[0] : '';
$content = isset($result[1]) ? $result[1] : '';
return array(
'status' => 'ok',
'header' => $header,
'content' => $content
);
}
这是响应标头:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Date: Tue, 03 May 2011 12:15:20 GMT
Expires: Tue, 03 May 2011 12:15:20 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Length: 728
Server: GSE
Connection: close
我返回的内容是某种自动提交的表单,我认为这是因为我使用 HTTP 而不是 HTTPS:
function autoSubmit() {
document.forms["hiddenpost"].submit();
}
Processing...
那么,如何执行 HTTPS POST 请求?
正如 octopusgrabbus 善意指出的那样,我需要使用端口 443 而不是 80。所以我改变了这一点,但现在我什么也没得到。
函数返回的 var_dump:
array(3) {
["status"]=>
string(2) "ok"
["header"]=>
string(0) ""
["content"]=>
string(0) ""
}
我没有得到标题,也没有返回内容。怎么了?
I trying to work with the YouTube API and its ClientLogin. And that means that I need to make a POST request to their servers.
The URL to which I need to make the request to https://www.google.com/accounts/ClientLogin. The variables I need to send are Email
, Passwd
, source
and service
. So far, so good.
I found this neat function to make POST calls (see below), but it does not use HTTPS, which I think I must use. It all works but I think my POST request is being forwarded to HTTPS and therefore it does not give me the proper callback. When I try to var_dump
, the returned data web page reloads and I end up at https://www.google.com/accounts/ClientLogin where I get proper data. But of course I need this data as an array or string.
So how do I make a POST request using HTTPS?
Se my code (which I found at Jonas’ Snippet Library) below:
function post_request($url, $data, $referer='') {
$data = http_build_query($data);
$url = parse_url($url);
$host = $url['host'];
$path = $url['path'];
$fp = fsockopen($host, 80, $errno, $errstr, 30);
if ($fp){
fputs($fp, "POST $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
if ($referer != '')
fputs($fp, "Referer: $referer\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ". strlen($data) ."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $data);
$result = '';
while(!feof($fp)) {
$result .= fgets($fp, 128);
}
}
else {
return array(
'status' => 'err',
'error' => "$errstr ($errno)"
);
}
fclose($fp);
$result = explode("\r\n\r\n", $result, 2);
$header = isset($result[0]) ? $result[0] : '';
$content = isset($result[1]) ? $result[1] : '';
return array(
'status' => 'ok',
'header' => $header,
'content' => $content
);
}
This is the response headers:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Date: Tue, 03 May 2011 12:15:20 GMT
Expires: Tue, 03 May 2011 12:15:20 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Length: 728
Server: GSE
Connection: close
The content I get back is some kind of form autosubmitted, which I think is because I use HTTP instead of HTTPS:
function autoSubmit() {
document.forms["hiddenpost"].submit();
}
Processing...
So, how do I do a HTTPS POST request?
As octopusgrabbus kindly pointed out, I need to use port 443 instead of 80. So I changed this, but now I get nothing back.
var_dump from function return:
array(3) {
["status"]=>
string(2) "ok"
["header"]=>
string(0) ""
["content"]=>
string(0) ""
}
I get no header and no content back. What is wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为你不能直接谈论 HTTPS,因为它是使用你所连接的服务器的公共证书加密的 HTTP。也许您可以在 php 中使用一些 ssl 函数。但是,这将花费您一些时间,坦率地说,还有更简单的事情。
看看 cURL (客户端 URL),它支持 GET 和 POST 请求,还可以连接到 https服务器。
I think you cannot talk directly HTTPS, as it is HTTP encrypted with the public certificate of the server you are connecting to. Maybe you can use some of the ssl functions in php. But, this will take you some time and frankly, there are easier things.
Just take a look at cURL (client URL), that has support for GET and POST requests, and also connecting to https servers.
您正在端口 80 打开套接字。SSL 端口是 443。
You are opening your socket at port 80. The SSL port is 443.
如果这是 SSL,则有一个与该 Web 服务器上存在的安全证书相关联的官方计算机名称。您可能需要使用该官方名称进行连接。
If this is SSL, there is an official computer name tied to the secure cert that's present on that web server. You might need to connect using that official name.
当您打开套接字时,将端口更改为 443 并在主机前面添加 ssl:// 应该可以工作。 (我刚刚遇到了贝宝和一些第三方代码的问题)。这假设您的主机中还没有协议。
因此,
正如 Carlos 指出的那样,cUrl 对于此类事情很有用。但在这种情况下,没有必要完全改变您所使用的内容,特别是当它是单行更改时。
When you open the socket, changing the port to 443 and the prepending the host with ssl:// should work. (I just had this issue with paypal and some third party code). This assumes you don't have a protocol in your host already.
So
As Carlos pointed out cUrl is good for this sort of thing. But there's no need to completely change what you're using in this case, particularly when it's a single line change.