I have a code written in PHP and currently running on my shared hosting. Now I'm going to move it on Google App Engine.
sendRequest() method sends post data and cookies to another website and returns a response.
private function sendRequest($url, array $data = array()) {
$ch = curl_init(self::URL_BASE);
$curlConfig = array(
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_COOKIE => "user_name=" . $this->username . "; user_password=" . md5($this->password));
if ($url == self::URL_LOGIN) {
$this->cookieFile = tempnam("/tmp", "CURLCOOKIE");
$curlConfig[CURLOPT_COOKIEJAR] = $this->cookieFile;
} else {
$curlConfig[CURLOPT_COOKIEFILE] = $this->cookieFile;
}
curl_setopt_array($ch, $curlConfig);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
Problems:
CURL module is not supported in App Engine
tempnam() function is disabled
I've searched a lot, but couldn't find any alternatives. fsockopen() is also disabled.
Use the stream context to set the cookies on the request, per the example here.
Not sure from your code why you want to persist the cookies and for how long - can you use memcache for this purpose instead?
Related
I have a PHP loop where i need to call another PHP file in the background to insert/update some information based on a variable send to it. I have tried to use CURL, but it does not seem to work.
I need it to call SQLupdate.php?symbol=$symbol - Is there another way of calling that PHP with the paramter in the background - and can it eventually be done Synchronously with a response back for each loop?
while(($row=mysqli_fetch_array($res)) and ($counter < $max))
{
$ch = curl_init();
$curlConfig = array(
CURLOPT_URL => "SQLinsert.php",
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => array(
'symbol' => $symbol,
)
);
curl_setopt_array($ch, $curlConfig);
$result = curl_exec($ch);
curl_close($ch);
}
I'm going to weigh in down here in hopes of getting this one "away & done".
Although it isn't entirely clear from your post, it seems you're trying to call your PHP file via an HTTP(s) protocol.
In many configurations of PHP, you could do this and avoid some potential cURL overhead by using file_get_contents() instead:
while(($row=mysqli_fetch_array($res)) and ($counter < $max)) {
$postdata = http_build_query(
array(
'symbol' => $row['symbol']
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = file_get_contents('http://example.com/SQLinsert.php', false, $context);
$counter++; // you didn't mention this, but you don't want a everloop...
}
That's pretty much a textbook example copied from the manual, actually.
To use cURL instead, as you tried to do originally, and in truth it seems pretty clean with one call to curl_setopt() inside the loop:
$ch = curl_init();
$curlConfig = array(
CURLOPT_URL => "http://example.com/SQLinsert.php",
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true
);
curl_setopt_array($ch, $curlConfig);
while(($row=mysqli_fetch_array($res)) and ($counter < $max)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, array('symbol' => $row['symbol']));
$result = curl_exec($ch);
$counter++; //see above
}
// do this *after* the loop
curl_close($ch);
Now the actual and original problem may be that $symbol isn't initialized; at least, it isn't in the example you have provided. I've attempted to fix this by using $row['symbol'] in both my examples. If this isn't the name of the column in the database then you would obviously need to use the correct name.
Finally, be advised that it's almost always better to access a secondary resource via the fastest available mechanism; if "SQLinsert.php" is local to the calling script, using HTTP(s) is going to be terribly under-performant, and you should rewrite both pieces of the system to work from a local (e.g. 'disk-based') point-of-view (which has already been recommended by a plethora of commenters):
//SQLinsert.php
function myInsert($symbol) {
// you've not given us any DB schema information ...
global $db; //hack, *cough*
$sql = "insert into `myTable` (symbol) values('$symbol')";
$res = $this->db->query($sql);
if ($res) return true;
return false;
}
//script.php
require_once("SQLinsert.php");
while(($row=mysqli_fetch_array($res)) and ($counter < $max)) {
$ins = myInsert($row['symbol']);
if ($ins) { // let's only count *good* inserts, which is possible
// because we've written 'myInsert' to return a boolean
$counter++;
}
}
I'm using a API to return a set a URLs, all URLs have redirects but how many redirects and where the URLs go are unknown.
So what I'm trying to do is to trace the path and find the last URL.
I basically want do the same as: http://wheregoes.com/retracer.php, but I only need to know the last URL
I've found a way to do it with CURL but the trace stops when it is a Meta-Refresh.
I've seen this thread: PHP: Can CURL follow meta redirects but it doesn't help me a lot.
This is my current code:
function trace_url($url){
$ch = curl_init($url);
curl_setopt_array($ch, array(
CURLOPT_FOLLOWLOCATION => TRUE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_SSL_VERIFYHOST => FALSE,
CURLOPT_SSL_VERIFYPEER => FALSE,
));
curl_exec($ch);
$url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close($ch);
return $url;
}
$lasturl = trace_url('http://myurl.org');
echo $lasturl;
well, there are a big difference between Header Redirects , which is basically under 3xx class and META refresh , simply one way relies on the server, and the other related to the client .
and as long as curl or as known cURL or libcurl which is executed in the server , it can handle the first type, 'Header redirects' or http redirects.
so , you can then extract the url using bunch of ways.
you will need to handle it manually .
1) scrap the web page contents.
2) extract the link from the meta tag.
3) grab this new link if you want.
from your example:
function trace_url($url){
$ch = curl_init($url);
curl_setopt_array($ch, array(
CURLOPT_FOLLOWLOCATION => TRUE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_SSL_VERIFYHOST => FALSE,
CURLOPT_SSL_VERIFYPEER => FALSE,
));
curl_exec($ch);
$url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close($ch);
return $url;
}
$response = trace_url('http://myurl.org');
// quick pattern for explanation purposes only, you may improve it as you like
preg_match('#\<meta.*?content="[0-9]*\;url=([^"]+)"\s*\/\>#', $response, $links);
$newLink = $links[1];
or as mentioned in your question about the solution provided which is use simplexml_load_file library .
$xml = simplexml_load_file($response);
$link = $xml->xpath("//meta[#http-equiv='refresh']");
I have a php script that sends a file via cURL, to a remote location.
This works great on a Mac.
On Windows w/ MAMP (I am stuck with this at present), no request reaches the remote server.
If I take away the CURLOPT_POSTFIELDS parameter, the request is sent, however without my data (obviously). This tells me that cURL is loaded ok, and is able to send a request.
What I can't work out, is what is causing this to do nothing when CURLOPT_POSTFIELDS is included (as per the code below) - no errors (that I am aware of).
Here is the code that I am running:
function getCurlValue($filename, $contentType, $postname)
{
if (function_exists('curl_file_create')) {
return curl_file_create($filename, $contentType, $postname);
}
// Use the old style if using an older version of PHP
$value = "#{$this->filename};filename=" . $postname;
if ($contentType) {
$value .= ';type=' . $contentType;
}
return $value;
}
$filename = 'c:\path\to\file\test.txt';
$cfile = getCurlValue($filename,'text/plain','test.txt');
$data = array('updateFile' => $cfile);
$ch = curl_init();
$options = array(CURLOPT_URL => 'http://url/to/my/service',
CURLOPT_RETURNTRANSFER => true,
CURLINFO_HEADER_OUT => true, //Request header
CURLOPT_HEADER => true, //Return header
CURLOPT_FAILONERROR => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data
);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
$header_info = curl_getinfo($ch,CURLINFO_HEADER_OUT);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($result, 0, $header_size);
$body = substr($result, $header_size);
curl_close($ch);
I have checked for cURL errors, of which there are none thrown.
Any thoughts would be most appreciated.
Thanks,
Nathan
This issue appears to have resolved itself. All is now working, with no changes on my part.
Must have been something at the server end....
What is the procedure for sending secure data (login id, password) over https to an Apache 2.2 server with self-signed certificates?
<?php
$uid=$_POST['user'];
$password=$_POST['pass'];
$url = "https://example.com/login";
$cert_file = './certificate.com.pem';
$cert_password = 'xxxxxx';
$ch = curl_init();
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POSTFIELDS => 'uid:'.$uid.'&password:'.$password,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_VERBOSE => true,
CURLOPT_URL => $url ,
CURLOPT_SSLCERT => $cert_file ,
CURLOPT_SSLCERTPASSWD => $cert_password ,
CURLOPT_POST => true
);
curl_setopt_array($ch , $options);
$output = curl_exec($ch);
if(!$output)
{
echo "Curl Error : " . curl_error($ch);
}
else
{
echo htmlentities($output);
}
?>
the ERROR we are getting is :
curl error:unable to use client certificate (no key found or wrong passphrase ?)
You'd need to think about it this way:
Your local server asks the remote server to validate the login info. — You would need to make an exception for the self-signed certificate and remember it. (It would be a really a bad habit to simply ignore certificate errors.)
Your local server then checks if the data the remote one sent back isn't an error message and is indeed valid JSON data.
Here's some info on how to make curl remember the self-signed certificate and trust it permanently: http://turboflash.wordpress.com/2009/06/23/curl-adding-installing-trusting-new-self-signed-certificate/ — It should work for the command-line utility just as well as the PHP module.
So, let's make a little function for it. — I'm not going to test its functionality, so I can't promise to have it perfectly error free. I'm also using some practices I wouldn't use in production code, don't account for an API key, use GET parameters and I also make the remote server responsible for any serious sort of error checking and sanitation.
<?php
function remote_login($username, $password) {
/*
Initialize the curl object
*/
$login = curl_init();
/*
Some sanitation. This is probably not enough though.
*/
$username = urlencode($username);
$password = urlencode($password);
/*
Set the url we're going to use.
REST services use clean urls, but here we simply use GET parapeters.
*/
$login_url = 'https://example.com/?username='+$username+'&password='+$password;
curl_setopt($login, CURLOPT_URL, $login_url);
/*
Tell curl we would like to use the data returned from the remote server
*/
curl_setopt($login, CURLOPT_RETURNTRANSFER, true);
/*
Set the returned data as a variable
*/
$login_data = curl_exec($login);
$login_json = json_decode($login_data);
/*
We're not going to do anything else if we encounter any sort of error.
*/
if (($login_data == false) || ($login_json == false)) {
return false;
}
/*
Return the login result as a JSON object
*/
return json_decode($login_data);
}
?>
Hope this helps.
I have an application that has a Web Services RESTful API. When I make HTTP GET requests in the browser I get XML responses back.
When I make the same request using PHP I get the correct information but it is not formatted in XML and so I can't pass it to Simple XML.
Here's my code.
<?php
//Deifne user credentials to use with requests
$user = "user";
$passwd = "user";
//Define header array for cURL requestes
$header = array('Contect-Type:application/xml', 'Accept:application/xml');
//Define base URL
$url = 'http://192.168.0.100:8080/root/restful/';
//Define http request nouns
$ls = $url . "landscapes";
//Initialise cURL object
$ch = curl_init();
//Set cURL options
curl_setopt_array($ch, array(
CURLOPT_HTTPHEADER => $header, //Set http header options
CURLOPT_URL => $ls, //URL sent as part of the request
CURLOPT_HTTPAUTH => CURLAUTH_BASIC, //Set Authentication to BASIC
CURLOPT_USERPWD => $user . ":" . $passwd, //Set username and password options
CURLOPT_HTTPGET => TRUE //Set cURL to GET method
));
//Define variable to hold the returned data from the cURL request
$data = curl_exec($ch);
//Close cURL connection
curl_close($ch);
//Print results
print_r($data);
?>
Any thoughts or suggestions would be really helpful.
S
EDIT:
So this is the response I get from the PHP code:
0x100000rhel-mlsptrue9.2.3.0101
This is the response if I use the WizTools Rest Client or a browser.
<?xml version="1.0" encoding="UTF-16"?>
<landscape-response total-landscapes="1" xmlns="http://www.url.com/root/restful/schema/response">
<landscape>
<id>0x100000</id>
<name>rhel-mlsp</name>
<isPrimary>true</isPrimary>
<version>9.2.3.010</version>
</landscape>
</landscape-response>
As you can see the information is there but the PHP is not really presenting this in a useful way.
I was able to find the answer to this question so I thought I would share the code here.
//Initialise curl object
$ch = curl_init();
//Define curl options in an array
$options = array(CURLOPT_URL => "http://192.168.0.100/root/restful/<URI>",
CURLOPT_PORT => "8080",
CURLOPT_HEADER => "Content-Type:application/xml",
CURLOPT_USERPWD => "<USER>:<PASSWD>",
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_RETURNTRANSFER => TRUE
);
//Set options against curl object
curl_setopt_array($ch, $options);
//Assign execution of curl object to a variable
$data = curl_exec($ch);
//Close curl object
curl_close($ch);
//Pass results to the SimpleXMLElement function
$xml = new SimpleXMLElement($data);
print_r($xml);
As you can see the code is not all that different, the main thing was separating the port option out of the URL and into its own option.
Hopefully this helps someone else out!!!
S
Try this
$resp = explode("\n<?", $data);
$response = "<?{$resp[1]}";
$xml = new SimpleXMLElement($response);
Does it print anything at all (your code)? Try using echo $data but hit F12 to view the results on the console.