I am building an API in PHP and want the user to include some plug-ins written in any language of choice in a designated directory. The way this should work is that the API sends a request to that user's plug-in file and returns the result.
This should be accomplished without cURL, because cURL is unavailable in this particular environment, so answers using cURL won't be helpful.
The issue that I am having is that my function literally reads the contents of the file (without executing it) when the plug-in is also written in PHP.
This is my code:
function sendRequest($url, $method, $body){
$http = array(
'method' => $method,
'header' => 'Authorization: sometoken' . "\r\n".
'Content-Type: application/json' . "\r\n",
'content' => $body
);
$context = stream_context_create(array('http' => $http));
if($file = file_get_contents($url, false, $context)){
return $file;
}
else{
return 'Error';
}
}
This is an example of a simple plug-in file written in PHP:
<?php
$input = file_get_contents('php://input');
$input = json_decode($input, true);
echo($input['a'] + $input['b']);
?>
When it is requested from the API it should return the value of a + b. The above code could also be implemented in any other language, it should work either way. These files are stored locally, not on a remote server (where it would work flawlessly).
Is there any way force the file to be executed without cURL? I imagine include and require are also not an option, since the plug-in file should be in a language of choice, not necessarily PHP.
Thanks in advance!
You'll want to look at the PHP command exec
This would allow you do to something like:
exec('php plugin.php param1', $output);
Then read the results back via the $output variable.
Similar things could be done with other applications/scripts (provided they process with absolutely no interaction).
Related
I am using PHP to get JSON from a remote server via file_get_contents command. Here is the piece of code I used:
$opts = array(
'https'=>array(
'method'=>'GET',
'header'=>'Accept-language: en\r\n' .
'Authorization: MAC ["3","ios2.5.0","123","123abc","123=","abc="]\r\n' .
'User-Agent: abc/1.1.1 iOS/10.0.2 iPhone/iPhone7,1\r\n'
)
);
$context = stream_context_create($opts);
$file = file_get_contents('https://www.google.com/v11/file?search=ios&with=users%2Cfiles%2Cquestions', false, $context);
echo $file;
I did a quick debugging:
Using Postman I was able to get the json file with the same header.
I tried a different json from a different url, it works.
I tried a local file, it works.
You have to understand what file_get_contents is. This command is a request to get the file on the server, in this case it is requesting to get https://www.google.com/v11/file/index.html on the server as in one single step. Since your url seems to use header to verify your origin, it might be an ajax request, meaning the server components didn't set up to allow an output from file_get_contents requests, instead they probably accept cURL requests.
So you can use:
curl_exec()
have a look at below snippet inside my PHP code :
function SMS(){
$msg1="".$bookingNo."\n".$guestName."\n".$guestEmail."\n".$guestPhone."\n".$guestAddress."\n".$place."\n".$account."\n".$reportingDate."\n".$reportingTime."";
file('http://sms.xxxxxxxxxxxxx.co.in/api/webxxxx.php?workingkey=76565xxxxxx&sender=ILUVU&to=9897xxxxxxx&message='.$msg1.'');}
The problem is this that this http link is sending SMS successfully when run on browser window,
with some dummy text in &message=.
But when I am assigning all defined and tested variables inside $msg1 & calling it in same url.
Woosh, it shows NO ERROR & nothing happens, on calling this function. NO SMS.
I wonder where m wrong ?
Thanks
UPDATED CODE :
function SMS(){
$bookingNo=$_REQUEST['bookingNo'];
$guestName=$_REQUEST['guestName'];
$guestEmail=$_REQUEST['guestEmail'];
$guestPhone=$_REQUEST['guestPhone'];
$guestAddress=$_REQUEST['guestAddress'];
$place=$_REQUEST['place'];
$account=$_REQUEST['account'];
$reportingDate=$_REQUEST['reportingDate'];
$reportingTime=$_REQUEST['reportingTime'];
$msg1="".$bookingNo."\n".$guestName."\n".$guestEmail."\n".$guestPhone."\n".$guestAddress."\n".$place."\n".$account."\n".$reportingDate."\n".$reportingTime."";
file('http://sms.xxxxxxxxxxxxx.co.in/api/webxxxx.php?workingkey=76565xxxxxx&sender=ILUVU&to=9897xxxxxxx&message='.$msg1.'');}
}
SMStoDriver();
Newline characters are not allowed in URLs. You need to encode the message:
function SMS(){
$bookingNo=$_REQUEST['bookingNo'];
$guestName=$_REQUEST['guestName'];
$guestEmail=$_REQUEST['guestEmail'];
$guestPhone=$_REQUEST['guestPhone'];
$guestAddress=$_REQUEST['guestAddress'];
$place=$_REQUEST['place'];
$account=$_REQUEST['account'];
$reportingDate=$_REQUEST['reportingDate'];
$reportingTime=$_REQUEST['reportingTime'];
$msg1=urlencode("Booking No: $bookingNo\nName: $guestName\n Email: $guestEmail\nPhone: $guestPhone\nAddress: $guestAddress\nPlace: $place\nAccount: $account\nDate: $reportingDate\nTime: $reportingTime");
file('http://sms.xxxxxxxxxxxxx.co.in/api/webxxxx.php?workingkey=76565xxxxxx&sender=ILUVU&to=9897xxxxxxx&message='.$msg1.'');}
}
It looks like you are trying to use the file method to make the web request. Perhaps your PHP ini is configured to not allow file I/O requests to URLs.
You would be better off making the web request with something like cURL.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'http://sms.xxxxxxxxxxxxx.co.in/api/webxxxx.php?workingkey=76565xxxxxx&sender=ILUVU&to=9897xxxxxxx&message=test',
));
$resp = curl_exec($curl);
curl_close($curl);
I'm having some trouble using gae php as a simple proxy using "file_get_contents"
When i load a file for the first time I get the latest version available.
But if I change the content of the file, I dont get the latest version immediately.
$result = file_get_contents('http://example.com/'.$url);
The temporary solution I found was to add a random variable at the end of the query string, which allowed me to get a fresh version of the file every time :
$result = file_get_contents('http://example.com/'.$url.'?r=' . rand(0, 9999));
But this trick doesn't work for api calls with parameters for example.
I tried disabling APC cache in the php.ini of gae (using apc.enabled = "0") and i used clearstatcache(); in my script, but neither work.
Any ideas ?
Thanks.
As described in the appengine documentation the http stream wrapper uses urlfetch. As seen in another question urlfetch provides a public/shared cache and as such does not allow individual apps to clear it. For your own services you can set the HTTP cache headers to reduce or void the cache as necessary.
Additionally, you can also add HTTP request headers indicating the maximum age of data that is allowed to be returned. The python example given in mailing list thread is:
result = urlfetch.fetch(url, headers = {'Cache-Control' : 'max-age=300'})
Per php.net file_get_contents http header example and HTTP header documentation a modified example would be:
<?php
$opts = [
'http' => [
'method' => 'GET',
'header' => "Cache-Control: max-age=60\r\n",
],
];
$context = stream_context_create($opts);
$file = file_get_contents('http://www.example.com/', false, $context);
?>
I am putting up website & the domain hosting (1&1) only provide base PHP 5.4 (No external libraries like PECL_HTTP or CURL etc, No installed libraries ).
I can add PHP class files to my code. I am trying to do a Http/Https get on this URL
$url ="https://www.googleapis.com/freebase/v1/search?query=chocolate&count=2";
I have tried Snoopy, & at least 6 different class libraries from PHPClasses none of them return anything (result is blank), I don't know why? But they all return page results.
Can anyone suggest a PHP class library that I can include (and NOT any installed library) which can do a simple Http/Https get & return results.
Your best bet for full http functionality (including headers, etc.) is to use file functions with a stream context.
From php.net:
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);
$context = stream_context_create($opts);
$fp = fopen('http://www.example.com', 'r', false, $context);
fpassthru($fp);
fclose($fp)
If you just want the content of this "file" you could use file_get_contents() (see first example). See #OkekeEmmanuelOluchukwu's comment on how to send header.
Are you looking for the page output?
As you probably have found, include something.php?foo=bar does not work as php actually looks for a file ending in ?for=bar, but you can set all the get variables like this:
function getRequest($url, $data) {
foreach ($data as $key => $value) {
$_GET[$key] = $value;
}
include $url;
}
However, get variables on "full paths" (can't think of the proper name) work, eg include 'http://something.com/foo.php?bar=baz'. You can find examples here http://php.net/manual/en/function.include.php of the "variable passing" and get variables on a non-local-system.
I was trying to make an RESTful API call to upload videos through POST method. What I am lacking is that I don't know the best practices for writing this kind of API as well I don't find any resource on the internet to follow. Right now I am doing this:
I am working in PHP and zend framework ( Zend_Rest_Route ).
First approach:
using file_get_contents on client side and POST it to API using curl, and on server side using file_put_contents to write that data and sending an appropriate response.
Second:
using Zend_File_Treansfer to receive file at server side, and putting address of my upload api end point in zend_form with setting method as post. In this case file is uploaded to server, but after submitting the form, the url in address bar points to the api server and never comes back to the form.
Am I doing it right?, if not do let me know what are the best practices and how to accomplish this.
Thank you for your time.
Something like this worked for me:
public function postAttachment($fileName, $fileMimetype, $fileContents, $postURL, $username, $password)
{
$auth = base64_encode($username . ':' . base64_decode($password));
$header = array("Authorization: Basic ".$auth);
array_push($header, "Accept: */*");
$boundary = "----------------------------".substr(md5(rand(0,32000)), 0, 12);
$data = "";
$data .= "--".$boundary."\r\n";
//Collect Filedata
$data .= "Content-Disposition: form-data; name=\"file\"; filename=\"".$fileName."\"\r\n";
$data .= "Content-Type: ".$fileMimetype."\r\n";
$data .= "\r\n";
$data .= $fileContents."\r\n";
$data .= "--".$boundary."--";
// add more parameters or files here
array_push($header, 'Content-Type: multipart/form-data; boundary='.$boundary);
$params = array('http' => array(
'method' => 'POST',
'protocol_version' => 1.1,
'user_agent' => 'File Upload Agent',
'header' => $header,
'content' => $data
));
$ctx = stream_context_create($params);
$fp = fopen($postURL, 'rb', false, $ctx);
if (!$fp) {
throw new Exception("Problem with ".$postURL." ".$php_errormsg);
}
$responseBody = #stream_get_contents($fp);
if ($responseBody === false) {
throw new Exception("Problem reading data from ".$postURL.", ".$php_errormsg);
}
}
If you want to post several files, or add other multi-part parameters, it's easy to add these in other boundaries too.
I found some of this code on another post, and you can probably find similar code in the PHP wiki (http://www.php.net/manual/en/function.stream-context-create.php#90411). BUT ... That code was not properly handling the carriage return + line feeds and my server was summarily rejecting that post. In addition, that the older code was also using HTTP version 1.0 -- (which does not re-use sockets). When using HTTP 1.1 sockets are re-used when posting lots of files. (This works with HTTPS too.) I added my own user agent - If your are tricking some server into thinking this is a browser post, you might want to change the user agent to spoof a browser.
have you tried adding a redirect to end of your controller action that handles the upload? (if not you really should as its good practice to redirect after post) (make sure you redirect AFTER your logic has executed). In essence the 'page' that receives the post data should just work on the data, and any information you want to return to the user about that post action should be given to them on the page you redirect them to.
[form]--POST-->['post' controller action]--redirect (302)-->[page with success/failure info]