using php curl to pass variables to another site - php

I saw the following code on another post...
<?php
$ch = curl_init(); // create curl handle
$url = "http://www.google.com";
/**
* For https, there are more options that you must define, these you can get from php.net
*/
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query(['array_of_your_post_data']));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3); //timeout in seconds
curl_setopt($ch,CURLOPT_TIMEOUT, 20); // same for here. Timeout in seconds.
$response = curl_exec($ch);
curl_close ($ch); //close curl handle
echo $response;
?>
The only thing is I have no clue how to actually implement it or how it will work.
Here is what I am trying to do...
sitea.com/setup is setting php variables. If you visited that page, it would set $var1 = "hello" $var2="hi"
If someone visits siteb.com, I want to use php and somehow get those variables from sitea.com/setup to siteb.com and set them as new php variables. I'm assuming curl is the best option from what I've read, but can't figure out how to get it to work (or where to put it and how to call it) for that matter.
I'm experimenting with code trying to see how to do something for an upcoming project. Any help would be greatly appreciated.
I should note that I need this to be able to work from one domain on server1 to another domain on server2.

In a simple way it can be done like:
Site a: file.php
<?php
$a = 10;
$b = 20;
echo $a . ':' . $b;
?>
Site b: curl.php
<?php
$ch = curl_init(); // create curl handle
$url = "http://sitea/file.php";
/**
* For https, there are more options that you must define, these you can get from php.net
*/
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query(['array_of_your_post_data']));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3); //timeout in seconds
curl_setopt($ch,CURLOPT_TIMEOUT, 20); // same for here. Timeout in seconds.
$response = curl_exec($ch);
curl_close ($ch); //close curl handle
echo $response;
$parts = explode(':', $response);
$var1 = $parts[0];
$var2 = $parts[1];
?>

Related

Call JSON API from within PHP Cron Job

I have a large system with an API.
On the frontend, JavaScript uses AJAX to talk to the API.
I have a PHP file that runs every 5-min as a CRON job.
I want this PHP code to interact with the API.
All it has to submit is query-vars.
All that is sent back is a single number.
For Example:
https://examplesite.com/api/create?id=1&data=2
This replies with a simple number that is the SQL last-insert-id.
EXTRA:
The API also needs two Session variables (user-id and system-id)
Can I just start session and set them before calling the API I guess?
I need the PHP script, ran by the CRON system, to talk to this API.
I have tried using cURL but no luck yet:
//Need to add a user-id to session, does this work?
session_start();
$_SESSION['user-id'] = 1;
//HOW TO CALL API FROM CRON?
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($ch, CURLOPT_URL, 'https://example.com/api/create?id=1&gid=2');
//curl_setopt($ch, CURLOPT_URL, 'http://example.com/api/create?id=1&gid=2');
curl_setopt($ch, CURLOPT_URL, 'file://../framework/api/create.php?id=1&data=2');
$result = curl_exec($ch);
curl_close($ch);
$result = str_replace("\n", '', $result); // remove new lines
$result = str_replace("\r", '', $result); // remove carriage returns
//Expect Result to be a number only
file_put_contents("curl.log", "[".date('Y-m-d H:i:s')."] $result\n\n", FILE_APPEND);
The file method doesn't seem to work... maybe path issue with ../
The http method doesn't seem to work... server loopback issue?
Any advice on how to best have my PHP CRON robot use my API will be much appreciated.
I have simply copied API code into the CRON, but then I am duplicating code, and not allowing the robot to test the real API.
Thanks.
Assuming you still wanted to use a session. Your first curl should be a request that to a script that will create the SESSION then respond.
I created this get_cookie.php this to test this concept:
<?php
session_start();
$_SESSION['time'] = time();
echo 'Time=' . $_SESSION['time'];
?>
I called this script to get the PHPSESSID from the response cookie
$ch = curl_init('http://example.com/get_cookie.php');
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE));
$head = substr($response,0,$skip);
$data = substr($response,$skip);
$end = 0;
$start = strpos($head,'Set-Cookie: ',$end);
$start += 12;
$end = strpos($head,';',$start );
$cookie = substr($head,$start ,$end-$start );
file_put_contents('cookie.txt',$cookie);
echo "\ncookie=$cookie";
echo "\n$data\n";
RESPONSE:
cookie=PHPSESSID=bc65c95468d08dd02cc5ab8ab87bbd39
Time=1664237484
The CRON job URL, session.php:
<?php
session_start();
echo 'Time=' . $_SESSION['time'];
?>
This is the CRON job script.
$cookie = file_get_contents('cookie.txt');
$ch = curl_init('http://example.com/session.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIE, $cookie );
curl_setopt($ch, CURLOPT_HEADER, false);
$response = curl_exec($ch);
echo $response;
RESPONSE:
Time=1664237484
The result "Time" ($_SESSION['TIME']) is always the same as the time from the get_cookie.php.
Thanks for the help, but in the end my alternate approach will be easiest and work best. Here is the answer for others in need...
To have an external PHP (run via CRON) test an internal PHP API (that the frontend JavaScript usually talks to via AJAX), this is the easiest solution, including passing query-variables and session-vars.
STEP 1: Don't worry about start_session() or passing any query variables, just add what you need to the arrays ahead of time.
STEP 2: Capture the output buffer and simply include the PHP API file:
$_SESSION['user-id'] = ' works! ';
$_REQUEST['var'] = ' too ';
ob_start();
include '/var/www/sitename.com/framework/api/create.php';
$result = ob_get_contents();
ob_end_clean();
file_put_contents("/var/www/sitename.com/cron/curl.log", "[".date('Y-m-d H:i:s')."] Result: $result\n\n", FILE_APPEND);
/* OUTPUT in curl.log:
[2022-09-26 22:30:01] Result: works! / too
*/
/* create.php API
$user = $_SESSION['user-id']??' did not work ';
$req = $_REQUEST['var' ]??' novar ';
echo $user.'/'.$req;
*/
(obviously the CRON has to be on the same server as the website/api, otherwise you will have to use cURL with Cookie/Session/QueryVar-Arrays)

What is the best approch using CURLS in php?

I have the following code wherein I am calling a data through php CURL.
$URL = '//abc.com';
$gb = curl_init();
curl_setopt($gb,CURLOPT_URL,$URL);
curl_setopt($gb,CURLOPT_RETURNTRANSFER,1);
curl_setopt($gb,CURLOPT_CONNECTTIMEOUT,10);
curl_setopt($gb,CURLOPT_TIMEOUT,10);
curl_setopt($gb,CURLOPT_SSL_VERIFYPEER,false);
$res = curl_exec($gb);
curl_close($gb);
$data = json_decode($res,true);
What is the best way to call CURL request in case I have multiple variants of URL like?
1). //abc.com
2). //abc.com/abc
3). //abc.com/123
Should I call CURL multiple times or how to define it in php function?
You can do something like
function curlRequest($url){
$gb = curl_init();
curl_setopt($gb,CURLOPT_URL,$url);
curl_setopt($gb,CURLOPT_RETURNTRANSFER,1);
curl_setopt($gb,CURLOPT_CONNECTTIMEOUT,10);
curl_setopt($gb,CURLOPT_TIMEOUT,10);
curl_setopt($gb,CURLOPT_SSL_VERIFYPEER,false);
$res = curl_exec($gb);
$data = json_decode($res,true);
return $data;
}
$urls = ["http://url1","http://url2","http://url3"];
foreach($urls as $url){
curlRequest($url);//do something with data
}
I don't see difference calling the same domain or other since different routes retrieve different information. If all of these urls are equivalents, you don't need foreach or for solution.
It depends.
But if you connect to same website / service every time, you can freely use same connection.
This will allow you to set parameters for the connection one time only (eg. cookies or other headers).
You may also extract CURL handler creation to separated function and then only switch URLs for specific requests.
Your code should look like:
function init_my_curl() {
$h = curl_init();
curl_setopt($h, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($h, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($h, CURLOPT_TIMEOUT, 10);
curl_setopt($h, CURLOPT_SSL_VERIFYPEER, false);
return $h;
}
function do_request($handle, $url) {
curl_setopt($handle, CURLOPT_URL, $url);
$result = curl_exec($handle);
return json_decode($result, true);
}
Than you call:
$curl = init_my_curl();
do_request($curl, '//abc.com');
do_request($curl, '//abc.com/abc');
do_request($curl, '//abc.com/123');
curl_close($curl);
You can also wrap everything in class, but it depends on PHP version you are using and your code style.

how do php scripts for data mining from web pages work?

[Edited for better explanation and code included]
Hi! I have a php script on my web server that logs in to my heat pump web interface nibeuplink.com and gets all my temperature readings and so forth and returns them in a json-format.
freeboard.io is a free service for visualizing data, so I'm making a freeboard.io for my heat pump values. in freeboard.io I can add any json data as a data source, so I have added the link to my php-script. It fetches the data once but it seems there is some kind of cached values that it uses after that so they are not updated with new values from the script. freeboard.io uses a get-function to get the url. If i use a normal web browser to run the php script and refresh it, the values are updated - and also immediately updated in freeboard.io. Freeboard.io has a setting to automatically update the data source every 5 seconds.
It seems that there is something that triggers the script correctly when it is fetched from my web browser, but not when it is fetched from freeboard.io that uses a get function every 5 seconds to get new data.
in freeboard I can add headers to the get request, is there some header that would help me here to discard any cached data?
I hope that explains my problem better.
Is there anything i can add to my code in the beginning to always force an override of any cached data?
<?php
/*
* read nibe heatpump values from nibeuplink status web page and return them in json format.
* based on: https://www.symcon.de/forum/threads/25663-Heizung-Nibe-F750-Nibe-Uplink-auslesen-auswerten
* to get the code which is required as parameter, log into nibe uplink, open status page of your heatpump, and check url:
* https://www.nibeuplink.com/System/<code>/Status/Overview
*
* usage: nibe.php?email=<email>&password=<password>&code=<code>
*/
// to add additional debug output to the resulting page:
$debug = false;
date_default_timezone_set('Europe/Helsinki');
$date = time();
// Create temp file to store cookies
$ckfile = tempnam ("/tmp", "CURLCOOKIE");
// URL to login page
$url = "https://www.nibeuplink.com/LogIn";
// Get Login page and its cookies and save cookies in the temp file
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile); // Stores cookies in the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
// Now you have the cookie, you can POST login values
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, "Email=".$_GET['email']."&Password=".$_GET['password']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); // Uses cookies from the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Tells cURL to follow redirects
$output = curl_exec($ch);
curl_setopt($ch, CURLOPT_URL, "https://www.nibeuplink.com/System/".$_GET['code']."/Status/ServiceInfo");
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_POST, 0);
$result = curl_exec($ch);
$pattern = '/<h3>(.*?)<\/h3>\s*<table[^>]*>.+?<tbody>(.+?)<\/tbody>\s*<\/table>/s';
if ($debug) echo "pattern: <xmp>".$pattern."</xmp><br>";
$pattern2 = '/<tr>\s*<td>(.+?)<span[^>]*>[^<]*<\/span>\s*<\/td>\s*<td>\s*<span[^>]*>([^<]*)<\/span>\s*<\/td>\s*<\/tr>/s';
if ($debug) echo "pattern2: <xmp>".$pattern2."</xmp><br>";
preg_match_all($pattern, $result, $matches);
// build json format from matches
echo '{';
$first = true;
foreach ($matches[1] as $i => $title) {
echo ($first ? '"' : ',"').trim($title).'":{';
$content = $matches[2][$i];
preg_match_all($pattern2, $content, $values);
$nestedFirst = true;
foreach ($values[1] as $j => $field) {
echo ($nestedFirst ? '"' : ',"').trim($field).'":"'.$values[2][$j].'"';
$nestedFirst = false;
}
echo "}";
$first = false;
}
echo ",\"time\":{\"Last fetch\":\"$date\"}";
echo "}";
if ($debug) {
echo "<pre><xmp>";
echo print_r($matches);
echo "<br><br>";
echo $result;
echo "</xmp></pre>";
}
?>
You can make an ajax call to php script to refresh the part of webpage. I don't understand what do you mean by io i.e. are you talking about fetching the data from database and if any changes occurred in database then only newly added records must be fetched. If you mean it in that sense then you can use cookie to track any new records added into database and only if it finds new records it can make ajax call to php script to run your algorithm on fetched total dataset.

PHP echo statement with URL parameter

I wrote a mini script in PHP to send a POST request to the web server:
<?php
$cid = file_get_contents('cid');
function httpPost($url)
{
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_POST, true);
$output=curl_exec($ch);
curl_close($ch);
return $output;
}
echo httpPost("http://172.17.0.1:2375/containers/$cid/stop?t=5");
?>
Yes, this is Docker. I'm using the remote API in Docker, and this little piece of script works!
However, the ?t=5 at the end of the URL, gets ignored.
I guess it has to do with the ?.
How do I get this URL properly formatted, so that the ?t=5 works correctly?
(I tried 1,001 ways so far, with quotes and double quotes, with no luck. After more than 4 hours spent on this, I thought stackoverflow could help?)
Thanks...
NOTE: the "cid" is only a file on the hard-drive, that stores the container id. So I'm retrieving the container id from the file, and passing it to the URL (this part works, anyway).
The complete URL is written by me, i.e. not parsed.
Since there are no special requirements on your URL, why use an incomplete cURL wrapper function? You can simply do
echo file_get_contents("http://172.17.0.1:2375/containers/$cid/stop?t=5");
To answer your actual question as to why your query string gets ignored, it is because it is not being sent to the server properly. Google CURLOPT_POSTFIELDS
Edit Since it was mentioned that the request method has to be POST, you can change things a little in your cURL code to cater for that
curl_setopt($ch, CURLOPT_POSTFIELDS,"t=5");
Then you can call your function like
echo httpPost("http://172.17.0.1:2375/containers/$cid/stop");
Since you are trying a POST request you can modify your function a bit. For $data you can pass array("t"=>5).
function httpPost($url, $data = '')
{
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_POST, true);
if ($data != '')
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$output=curl_exec($ch);
curl_close($ch);
return $output;
}
You might try executing like this?
<?php
$cid = file_get_contents('cid');
function containeraction($cid, $action, $s) {
//Time in Seconds
$timedelay="t=".$s;
//Docker Container Host
$dockerhost="172.17.0.1";
//Host Port
$port="2375";
$url = "http://".$dockerhost.":".$port."/containers/".$cid."/".$action;
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_POSTFIELDS, $timedelay);
$output=curl_exec($ch);
curl_close($ch);
return $output;
}
//containeraction(container id, action, delay)
echo containeraction($cid, "stop", "5");
?>
Your curl setup works against Docker and passes the query string. You do need to trim whitespace when reading files in case there is a new line at the end.
<?php
$cid = trim(file_get_contents('cid'));
echo "$cid\n";
function httpPost($url)
{
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_POST, true);
$output=curl_exec($ch);
curl_close($ch);
return $output;
}
$url = "http://172.17.0.1:2375/containers/$cid/stop?t=6";
echo "$url\n";
echo httpPost($url)
?>

Getting multiple http response codes using cURL?

Please take a look at this sample code:
function http_response($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, TRUE); // remove body
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$head = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo $httpCode ;
}
this code will print the httpCode of the given url. I have couple of questions:
Can I get rid of some setopt() lines here and still getting httpCode?
What about if I want to check multiple urls at the same time? Can I modify the code to do that?
Can I do the same functionality in a simpler way using libraries different than cURL?
Thanks :)
You should be able to remove CURLOPT_HEADER and CURLOPT_NOBODY and still get the same result.
You could do that like this:
$urls = array(
'http://google.com',
'http://facebook.com'
);
$status = array();
foreach($urls as $url){
$status[$url] = http_response($url);
}
Try print_r($status); after this and you'll see the result.
You could do this with file_get_contents and $http_response_header, to learn more: http://www.php.net/manual/en/reserved.variables.httpresponseheader.php I would however recommend using cURL anyway.
*2. to check multiple urls you have to use this function in a loop, in any programming language 1 response from a server = 1 connection to that server. If you want to use 1 function to get responses from multiple servers you can always pass an array to the function and do the loop inside the function
*3. you can try this way:
function get_contents() {
file_get_contents("http://example.com");
var_dump($http_response_header);
}
get_contents();

Categories