PHP - CURL using HTTPS [closed] - php

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am trying to get Json Data from a https url.
I have tested and working code to do just this for http but I am yet to find a working version for https. This needs to be secure code.
This is my http version that works:
<?php
$key = "admin"; //user
$secret = "admin"; //pass
$api_ep = "http://$Hostname:$Port/$address";
if ($key && $secret){
$curl_opts = array(
CURLOPT_HTTPHEADER=>array("Accept: application/json"),
CURLOPT_VERBOSE=>false,
CURLOPT_HEADER=>false,
CURLOPT_POST=>false,
CURLOPT_RETURNTRANSFER=>true,
CURLOPT_HTTPAUTH=>CURLAUTH_DIGEST,
CURLOPT_USERPWD=>$key.":".$secret,
CURLOPT_URL=> $api_ep
);
}
function disp($opts,$var){
$ch = curl_init();
curl_setopt_array($ch, $opts);
$raw_resp = curl_exec($ch);
// $array_resp = json_decode($raw_resp);
//print_r($array_resp);
print_r($raw_resp);
curl_close($ch);
//$array = json_decode($raw_resp, true);
//print_r($array_resp);
//disp_table($array_resp, $var);
}
disp($curl_opts,$Type);
?>

If you don't have any sensitive data you can try setting CURLOPT_SSL_VERIFYPEER to FALSE
Else you will have to verify the certificate.
Since Curl doesn't have built-in root certificates. You need to explicitly point it to a cacert.pem file:
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/file/cacert.pem');
Without this, curl cannot verify the certificate sent back via ssl. This same root certificate file can be used every time you use SSL in curl.
You can get the cacert.pem file here: http://curl.haxx.se/docs/caextract.html
Note:
Setting CURLOPT_SSL_VERIFYPEER to false allows for man-in-the-middle-attacks. rmckay at webaware dot com dot au warns for this on nl3.php.net/manual/en/function.curl-setopt.php and gives an alternative solution that works: downloading a CA root certificate bundle at the curl website and saving it on your server. See at the given site, scroll down to the user comments

This code below works for https.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $basicAuthUrl);
$header = array();
$header[] = 'Content-length: 29';
$header[] = 'Content-type: application/x-www-form-urlencoded;charset=UTF-8';
$header[] = 'Authorization: Basic ' . $keyAndSecretEncoded;
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_credentials");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$result = curl_exec($ch);
curl_close($ch);

Add the following to disable SSL verification.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
Curl SSL fails to verify self signed certificates and hence, you will not be able to connect with https hosts if they are using self signed certificates.
function disp($opts,$var){
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt_array($ch, $opts);
$raw_resp = curl_exec($ch);
print_r($raw_resp);
curl_close($ch);
}

Related

Converting curl in bash to php [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Well, here's my cURL script inside bash that works without any issues!
#!/bin/bash
fileid="1yvklOFopnep8twiqAQecmMUoAbQVzU0r"
filename="MyFile.mp4"
curl -c ./cookie -s -L "https://drive.google.com/uc?export=download&id=${fileid}" > /dev/null
curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk '/download/ {print $NF}' ./cookie`&id=${fileid}" -o ${filename}
However I'm trying to rewrite this into a simple PHP script, although it appears not to be working correctly; here's the code:
<?php
define('FILENAME', 'MyFile.mp4');
define('FILE_ID', '1yvklOFopnep8twiqAQecmMUoAbQVzU0r');
$GlobalFileHandle = null;
function get_confirm($id)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://drive.google.com/uc?export=download&id=".$id);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
preg_match_all("/confirm=([0-9A-Za-z]+)&/", $result, $output_array);
return $output_array[1][0];
}
function get_file($id, $confirm)
{
global $GlobalFileHandle;
$GlobalFileHandle = fopen(FILENAME, 'w+');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://drive.google.com/uc?export=download&confirm='.$confirm.'&id='.$id);
curl_setopt($ch, CURLOPT_FILE, $GlobalFileHandle);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'curlWriteFile');
curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
fclose($GlobalFileHandle);
}
function curlWriteFile($cp, $data)
{
global $GlobalFileHandle;
return fwrite($GlobalFileHandle, $data);
}
$confirm_code = get_confirm(FILE_ID);
echo "We got our confirm code! ".$confirm_code;
get_file(FILE_ID, $confirm_code);
However it appears the file is not being downloaded & the MyFile.mp4 remains empty?
You seem to mix several options in an invalid way here.
Since you set CURLOPT_RETURNTRANSFER the data is returned by curl_exec().
So
$data = curl_exec($ch);
fwrite($GlobalFileHandle, $data);
should do the trick. If you want to use the callbacks, do not set CURLOPT_RETURNTRANSFER at all.
Another option is, to set CURLOPT_FILE to write the data directly to a file handle (don't set CURLOPT_RETURNTRANSFER either then):
curl_setopt(CURL_FILE, $GlobalFileHandle);
Furthermore, you need to set the CURLOPT_COOKIEFILE to your cookiejar to have the cookies read correctly. The CURLOPT_COOKIEJAR option only sets the file where to store cookies to. You need both, so add:
curl_setopt(CURL_COOKIEFILE, 'cookies.txt');
For more details, refer to the curl_setopt PHP manpage
Seems like a curl_exec is missing in function get_file.

Unable to receive inbound XML sent via cURL on remote API server

I am tasked with building an API to receive inbound XML data. On my client, I have this code.
$url = "http://stackoverflow.com";
$xml = '<?xml version="1.0" encoding="UTF-8"?><Request PartnerID="asasdsadsa" Type="TrackSearch"> <TrackSearch> <Title>love</Title> <Tags> <MainGenre>Blues</MainGenre> </Tags> <Page Number="1" Size="20"/> </TrackSearch> </Request>';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt( $ch, CURLOPT_POSTFIELDS, "xml=".$payload );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$request = curl_exec($ch);
curl_close($ch);
On my remote server, I have this code
function TransmitRx()
{
$xml = trim(file_get_contents('php://input'));
file_put_contents("newStandard/".rand(100,500)."received.xml", $xml);
}
//Listen for inbound data
TransmitRx()
If I open up the server endpoint URL, there is an empty file saved. I don't know why. But when I run the client-side script. I get nothing. No errors. Nothing.
I have looked at several of the pages here and every one of them has a similar cURL statement to send data.
Why am I not receiving any post data at the API endpoint?
I have been unsuccessful at any information via the WWW.
UPDATE
Final Code that works:
function get_url($request_url, $payload)
{
$headers = [
"Access-Control-Allow-Origin: *",
"Content-type: text/xml",
"Content-length: " . strlen($payload),
"Connection: close",
];
$data = ['xml' => $payload];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request_url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$response = curl_exec($ch) or die(curl_error($ch));;
if (curl_errno($ch)) {
print curl_error($ch);
} else {
curl_close($ch);
}
return $response;
}
$request_url = 'https://stackoverflow.com/posts';
$response = get_url($request_url, $payload);
I wish I knew for sure what caused it to start working. I was reading this page last.
https://www.php.net/manual/en/curlfile.construct.php
Okay, so if adding the lines I suggested to disable certification / peer validation enabled the process to work, then that just means the remote server is using an SSL certificate that is not trusted by cURL.
Those lines are NOT the final fix. You never want to disable SSL validation in a real environment. I only suggested you temporarily disable them to see if that was truly the problem. If you leave them disabled, then you are leaving your code vulnerable to man-in-the-middle (MITM) attacks.
The correct fix is usually to point cURL at an updated CA bundle. The official cURL website graciously provides these here:
https://curl.haxx.se/docs/caextract.html
The process is that you download the CA bundle file and put it somewhere where your script can find it, and then add this curl option:
curl_setopt ($ch, CURLOPT_CAINFO, "full path to the CA bundle file.pem");
If the remote server's certificate came from any of the major CA vendors out there, this should be all you need to do.
If the remote server's certificate is self-signed or something then you might need to download the specific CA certificate and any supporting intermediate CA certificates and tell cURL to find them.

Backendless standalone cannot check isvalidusertoken REST API

I've been using the cloud environment, which works fine. I just recently downloaded the standalone version and am successfully running it on my ubuntu server. All the PHP SDK calls work, and the api/v1/data/[X Table Name] CuRL requests work.
However, I cannot get the CuRL request for valid login and logout to work. With the cloud implementation this was working:
function isValidToken($userToken){
$ch = curl_init();
$appId = APP_ID_FOR_CLOUD;
$restKey = REST_KEY_FOR_CLOUD;
$headers = array("application-id:$appId","secret-key:$restKey","application-type:REST");
curl_setopt($ch, CURLOPT_URL, "https://api.backendless.com/v1/users/isvalidusertoken/" . $userToken);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
This returns the proper response.
Now the only thing that changes are the IDs, keys, and URL, but it cannot find the requested URL. Here is the call to the standalone implementation:
function isValidToken($userToken){
$ch = curl_init();
$appId = APP_ID_STANDALONE;
$restKey = REST_KEY_STANDALONE;
$headers = array("application-id:$appId","secret-key:$restKey","application-type:REST");
curl_setopt($ch, CURLOPT_URL, "http://[my_server_ip_address]/v1/users/isvalidusertoken/" . $userToken);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
echo curl_error($ch);
curl_close($ch);
return $response;
}
The response I get is:
The requested URL /v1/users/isvalidusertoken/35A977A7-60DB-3772-FFC9-29E72AFAA200 was not found on this server.
Does anyone know how to resolve this issue? Thanks in advance!
I was just able to figure this out, the issue was due to a simple typo in the URL. For anyone who may make the same mistake, the standalone URL (for isvaliduesrtoken) is:
http://[my_server_ip_address]/api/<your_app_version>/users/isvalidusertoken/<user-token>

Php converting file_get_contents fails to connect Bing Search API using Windows Azure

When try to create a new API request with the Windows Azure new Bing based API, Using the code below
$url= 'https://'.$this->m_host.'/Web?Query={keyword}&Adult=%27Off%27&$top=50&$format=Atom';
$url=str_replace('{keyword}', urlencode($this->m_keywords), $url);
// Replace this value with your account key
$accountKey = $this->key;
$WebSearchURL = $url;
$context = stream_context_create(array(
'http' => array(
'proxy' => 'tcp://127.0.0.1:8888',
'request_fulluri' => true,
'header' => "Authorization: Basic " . base64_encode($accountKey . ":" . $accountKey)
)
));
$request = $WebSearchURL;
$response = file_get_contents($request, 0, $context);
print_r($response);
i get following error.
Warning: file_get_contents() [function.file-get-contents]:
Couldn't connect to server in /home/xxxxx on line 43
Warning: file_get_contents(https://api.datamarket.azure.com/
failed to open stream: operation failed in /home/xxxx/ bing_search.php on line 43
Any idea why this fails ? or is it best to use the CURL Library than the file_get_contents() ?
The below code works for me, it is to search news but it will work for web searches too.
Just replace appkey with your one, leave username as it is (i.e. username) since it is ignored by the server
function getBingResult($keyword)
{
$credentials = "username:appkey";
$url= "https://api.datamarket.azure.com/Data.ashx/Bing/Search/v1/News?Query=%27{keyword}%27". "&\$format=json";
$url=str_replace('{keyword}', urlencode($keyword), $url);
$ch = curl_init();
$headers = array(
"Authorization: Basic " . base64_encode($credentials)
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,5);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($session, CURLOPT_VERBOSE, TRUE);
$rs = curl_exec($ch);
$jsonobj = json_decode($rs);
curl_close($ch);
return $jsonobj;
}
Testing the function:
$bingResult = getBingResult("John");
foreach($bingResult->d->results as $value)
{
echo '<pre>'."URL:". $value->Url.'</pre>';
echo '<pre>'."Title:". $value->Title.'</pre>';
echo '<pre>'."Description:". $value->Description.'</pre>';
echo '<pre>'."Source:". $value->Source.'</pre>';
echo '<pre>'."Date:". $value->Date.'</pre>';
}
Either file_get_contents or CURL will work for the Bing API, you can use what will work on your system and what you are comfortable with.
First I would check your server can connect to the Windows Azure server. Try running a ping and then a wget from the command line to see if it can. Do you go through a proxy? You'll need to set those details in your stream context.
I'm not sure what you have $this->m_host set to, but the new Bing API should be at either:
https://api.datamarket.azure.com/Bing/Search/ or https://api.datamarket.azure.com/Bing/SearchWeb/. The URL https://api.datamarket.azure.com/Web comes back as invalid.
Here is working example of Search API just replace your access key with "XXXX". Even i wasted quite a few hours to get it work using cURL but it was failing cause of "CURLOPT_SSL_VERIFYPEER" on local :(
$process = curl_init('https://api.datamarket.azure.com/Bing/Search/Web?Query=%27xbox%27');
curl_setopt($process, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($process, CURLOPT_USERPWD, "username:XXXX");
curl_setopt($process, CURLOPT_TIMEOUT, 30);
curl_setopt($process, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($process);
# Deliver
return $response;
# Have a great day!
curl_close($process);
1.) You do not need str_replace(). Use the var directly inside the url:
$url= 'https://'.$this->m_host.'/Web?Query='.urlencode($this->m_keywords).'&Adult=%27Off%27&$top=50&$format=Atom';
2.) You defined three different vars with the same value:
$WebSearchURL = $url;
$request = $WebSearchURL;
Use $url only.
3.) base64_encode($accountKey . ":" . $accountKey) can be reduced to base64_encode(":" . $accountKey)
4.) Add Accept-Encoding: gzip to your header to reduce traffic and raise speed.
5.) Your problem should be this line:
'proxy' => 'tcp://127.0.0.1:8888',
Remove it or change it to the correct value.

REST API Implementation Sample Code

I know nothing about implementing an API. I do know PHP a bit. I have a situation where I need to call a REST API method to purge cache on a CDN server. Can somebody help me with some sample code?
The following is the sample request:
PUT <<url>>
Authorization: TOK:12345-12345
Accept: application/json
Content-Type: application/json
Host: api.edgecast.com
Content-Length: 87
{
"MediaPath":"<<urlhere>>"
"MediaType":"3"
}
Can somebody help me with code to implement this rest api request?
Thanks in advance.
I had to find the hard way too. This has been tested (with slight modifications from my original code)
//## GoGrid PHP REST API Call
define('TOKEN','XXXXX-XXXXX-XXXXX-XXXXXX'); // found on the cdn admin My Settings
define('ACCOUNT_NUMBER','XXXX'); // found on the cdn admin Top Right corner
function purgeCacheFileFromCDN($urlToPurge) {
//## Build the request
$request_params = (object) array('MediaPath' => $urlToPurge, 'MediaType' => 8); // MediaType 8=small 3=large
$data = json_encode($request_params);
//## setup the connection and call.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.edgecast.com/v2/mcc/customers/'.ACCOUNT_NUMBER.'/edge/purge');
curl_setopt($ch, CURLOPT_PORT , 443);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1); // For debugging
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); // no caching
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1); // no caching
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: tok:'.TOKEN, 'Content-Type: application/json','Accept: application/json', 'Content-length: '.strlen($data)));
$head = curl_exec($ch);
$httpCode = curl_getinfo($ch);
curl_close($ch);
//## check if error
if ($httpCode['http_code'] != 200) {
echo 'Error reported: '.print_r(array($head,$httpCode),1); // output it to stdout this will be emailed to me via cron capture.
}
}
Was too lazy to write from the scratch so copied from amazingly pink site that Google advises in the first page of results.
$data = array("a" => $a);
$ch = curl_init($this->_serviceUrl . $id);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));
$response = curl_exec($ch);
if(!$response) {
return false;
}
PS: The source search request: http://www.google.ru/search?q=php+sample+put+request+curl
Here is my source gist for my fully implemented Grunt task for anyone else thinking about working with the EdgeCast API. You'll find in my example that I use a node module to execute the curl command which purges the CDN.
This was that I ended up with after spending hours trying to get an HTTP request to work within Node. I was able to get one working in Ruby and Python, but did not meet the requirements of this project.

Categories