Following is the code I am using.
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
$app = new \Slim\App;
function handle_response($output, $response){
if($output['status'] === "failed"){
$response = $response->withStatus(400);
$response->getBody()->write(json_encode($output));
}
else{
$response->getBody()->write(json_encode($output));
}
return $response;
}
/* user profile */
$app->get('/user/profile', function (Request $request, Response $response) {
$headers = $request->getHeaders();
foreach ($headers as $name => $values) {
$name . ": " . implode(", ", $values);
}
if ($request->hasHeader('Authorization')) {
$output['token'] = 'yes';
}
else
$output['token'] = $name;
$output['status'] = "success";
return handle_response($output, $response);
});
I am using postman in google chrome to test this REST service.
I am passing a custom header "Authorization" along with the GET request.
however, this program doesn't recognize any custom headers.
The code block
$headers = $request->getHeaders();
foreach ($headers as $name => $values) {
$name . ": " . implode(", ", $values);
}
only returns the header "HTTP_ACCEPT_LANGUAGE".
Please help me to figure out, what went wrong here.
It is not Slim, it is considered a PHP feature. If you are sending something else than valid HTTP Basic Authorization header, PHP will not have access to it. You can work around this by adding the following rewrite rule to your .htaccess file.
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Another way is to use apache_request_headers() but it is Apache specific and not portable.
Related
I am trying to run a server locally using ngrok to use a Twilio phone number to receive calls, but when I run ngrok http 3000 and put the url it generated the error below appears.
What can it be? All the files are giving this problem.
Erro:
<?php
// Create a route that will handle Twilio webhook requests, sent as an
// HTTP POST to /voice in our application
require_once '../vendor/autoload.php';
require_once 'Curl.class.php';
require_once './utils/Utils.php';
include '/core/DigitalLockApi.class.php';
const baseUrl = 'https://digital-lock-api-node.paymobi.com.br/';
function logText($title, $content)
{
$logfile = fopen("./log.txt", "a");
fwrite($logfile, "\n" . $title);
fwrite($logfile, "\n" . date("Y-m-d H:i:s"));
fwrite($logfile, "\n" . print_r($content, true));
fwrite($logfile, "\n" . "-----------------------------------");
fclose($logfile);
}
function initErrorsLog()
{
$log_file = "errors.log";
ini_set("log_errors", true);
ini_set('error_log', $log_file);
}
use Twilio\TwiML\VoiceResponse;
// Use the Twilio PHP SDK to build an XML response
$response = new VoiceResponse();
initErrorsLog();
if (array_key_exists('Digits', $_POST)) {
$cpf = $_POST['Digits'];
$cpfString = (string) $cpf;
if(validateCPF($cpfString)) {
$response->redirect("./password.php?cpf=$cpf");
} else {
$response->redirect('./invalidCpf.php');
}
} else {
$gather = $response->gather(['numDigits' => '100', 'timeout' => '4']);
$gather->play("https://digital-lock-api.azurewebsites.net/ura/assets/audios/insertCpf.mp3");
// If the user doesn't enter input loop
$response->redirect('./cpfNull.php');
}
// Render the response as XML in reply to the webhook request
header('Content-Type: text/xml');
echo $response;
Debugging line by line I found out that what was breaking the code was the
include '/core/DigitalLockApi.class.php';
It was not finding this import
I have a situation where I have a loop, that is going to read chunk of data from a file, send those chunk to a rest api, and continue until the EOF, but I want this to be async inside the loop, so, I don't have to wait until the API respond to read the next chunk.
I have been looking at Amphp and ReactPHP for I can't find a solution to this, or maybe I don't understand how are those libraries supposed to be used.
here is a pseudo of what I am doing.
<?php
while($file.read()){
$chunk = getNextChunk();
sendChunkAsync($chunk);
}
function getNextChunk(){
echo "reading next chunk";
// read next chunk of data
}
sample with amphp
function sendChunkAsync($chunk){
Loop::run(function () {
$uri = "https://testapi.com/api";
$client = new DefaultClient;
try {
$promises = $client->request($uri);
$responses = yield $promises;
echo "chunk processed";
} catch (Amp\Artax\HttpException $error) {
// log error
// $error->getMessage() . PHP_EOL;
}
});
}
In this case I would expect (if reading chunk is faster than getting response from api) something like this, don't take this literary, I am trying to illustrate it for you.
Reading next chunk
Reading next chunk
chunk processed
Reading next chunk
chunk processed
chunk processed
I am going to use React as I know the library better but they work in similar ways.
EDIT: updated, see comments
This will read in a file and every time it recieves a chunk of data, it will create an api call and send the data off
<?php
require_once __DIR__ . '/vendor/autoload.php';
function async_send($config, $file, callable $proccessor)
{
$config['ssl'] = true === $config['ssl'] ? 's' : '';
$client = new \GuzzleHttp\Client([
'base_uri' => 'http' . $config['ssl'] . '://' . $config['domain'] . '/rest/all/V1/',
'verify' => false,
'http_errors' => false
]);
$loop = \React\EventLoop\Factory::create();
$filesystem = \React\Filesystem\Filesystem::create($loop);
$filesystem->getContents($file)->then(function($contents) use ($config, $proccessor, $client) {
$contents = $proccessor($contents);
$client->post($config['uri'], ['body' => $contents]);
});
}
$config = [
'domain' => 'example.com',
'ssl' => true
];
//somewhere later
$configp['uri'] = 'products';
async_send($configp, __DIR__ . 'my.csv', function ($contents) {
return json_encode($contents);
});
In case someone else is trying to solve a similar problem
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use React\HttpClient\Client as ReactClient;
function async_send($loop, $filePath, callable $proccessor)
{
echo "starting";
echo "\n\r";
try {
$filesystem = \React\Filesystem\Filesystem::create($loop);
$file = $filesystem->file($filePath);
$file->open('r')
->then(function ($stream) use ($loop, $proccessor){
$stream->on('data', function ($chunk) use ($loop, $proccessor) {
$proccessor($chunk);
});
});
} catch (\Exception $e) {
echo "failed";
echo "\n\r";
}
echo "ending reading";
echo "\n\r";
}
function callApiReal($loop, $fileChunk = null)
{
echo "ready to call api". PHP_EOL;
$uri = "https://testapi.com/";
try {
$client = new ReactClient($loop);
} catch (\Exception $e) {
echo "Error";
}
echo "ready to call api";
$request = $client->request('POST', $uri, $fileChunk);
$request->on('response', function ($response) use ($uri) {
$response->on('data', function ($data_chunk) {
echo 'data chunk from api received';
echo "\n\r";
});
// subscribe to listen to the end of the response
$response->on('end', function () use ($uri) {
echo "operation has completed";
echo "\n\r";
});
});
$request->on('error', function ($error) {
// something went bad in the request
echo "Damm!";
echo "\n\r";
});
$request->end();
}
// main loop
$loop = React\EventLoop\Factory::create();
//somewhere later
async_send($loop, __DIR__ . '/my.csv', function ($chunk) use ($loop) {
echo "calling api";
callApiReal($loop, $chunk);
echo "\n\r";
});
$loop->run();
How can I get headers sent by GuzzleHttp\Client()->get('URL')?
I can only get response headers, but not request. Help! thanks.
You can call the getHeaders() method of Request to get all the headers in a request, if you want to specifically check for a header you can use hasHeader()
use GuzzleHttp\Psr7;
$request = new Psr7\Request('GET', 'URL', ['Foo' => 'Bar']);
//Check for a header
if ($request->hasHeader('Foo')) {
echo 'Yes.';
}
//Get all the headers
foreach ($request->getHeaders() as $name => $values) {
echo $name .': ' . implode(', ', $values) . "\r\n";
}
https://coinbase.com/api/v1/transactions/send_money?api_key=xxx
I have that URL but after the api_key paramter what comes next (I blocked out my API Key so people can't access my BTC)?
Can someone give me an example of how to properly use coinbase's send_money API?
I don't have a PHP environment handy to test this with but I think it would go like this:
Get their PHP library: https://github.com/coinbase/coinbase-php
<?php
require_once(dirname(__FILE__) . '/../lib/Coinbase.php');
// Create an application at https://coinbase.com/oauth/applications and set these values accordingly
$_CLIENT_ID = "83a481f96bf28ea4bed1ee8bdc49ba4265609efa40d40477c2a57e913c479065";
$_CLIENT_SECRET = "a8dda20b94d09e84e8fefa5e7560133d9c5af9da93ec1d3e79ad0843d2920bbb";
// Note: your redirect URL should use HTTPS.
$_REDIRECT_URL = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
$coinbaseOauth = new Coinbase_OAuth($_CLIENT_ID, $_CLIENT_SECRET, $_REDIRECT_URL);
if(isset($_GET['code'])) {
// Request tokens
$tokens = $coinbaseOauth->getTokens($_GET['code']);
// The user is now authenticated! Access and refresh tokens are in $tokens
// Store these tokens safely, and use them to make Coinbase API requests in the future.
// For example:
$coinbase = new Coinbase($coinbaseOauth, $tokens);
try {
echo 'Balance: ' . $coinbase->sendMoney($to, $amount, $notes=null, $userFee=null, $amountCurrency=null) . '<br>';
echo $coinbase->createButton("Alpaca socks", "10.00", "CAD")->embedHtml;
} catch (Coinbase_TokensExpiredException $e) {
$newTokens = $coinbaseOauth->refreshTokens($tokens);
// Store $newTokens and retry request
}
} else {
// Redirect to Coinbase authorization page
// The provided parameters specify the access your application will have to the
// user's account; for a full list, see https://coinbase.com/docs/api/overview
// You can pass as many scopes as you would like
echo "Connect with Coinbase";
}
Here is the send money code
public function sendMoney($to, $amount, $notes=null, $userFee=null, $amountCurrency=null)
{
$params = array( "transaction[to]" => $to );
if($amountCurrency !== null) {
$params["transaction[amount_string]"] = $amount;
$params["transaction[amount_currency_iso]"] = $amountCurrency;
} else {
$params["transaction[amount]"] = $amount;
}
if($notes !== null) {
$params["transaction[notes]"] = $notes;
}
if($userFee !== null) {
$params["transaction[user_fee]"] = $userFee;
}
return $this->post("transactions/send_money", $params);
}
I have a function to translate the current text string using the Free Bing translator API. I just want to make sure if anything fails or something happens with the Application ID or I go over on requests, I don't want a big error to show.
The code I have right now is:
$translate_feed = file_get_contents('http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=' . BING_APPID . '&text=' . urlencode($text) . '&from=en&to=' . $to_lan . '');
$translate = simplexml_load_string($translate_feed);
return $translate[0];
What I want to happen is if anything fails, so if I add in another character to the URL to make it invalid then I want it to just return $text so at least something shows.
Thanks!
Have you tried failing it on purpose to see what happens?
If it's an exception, just catch it and handle it...
try{
//enter code to catch
}catch(Exception $ex){
//Process the exception
}
If there is an error outputted by the function, just # to hide the error and handle the incorrect output of $translate_feed or $translate manually.
You can try failing it on purpose by simply passing an invalid URI to file_get_contents and then forcefully feed non XML or invalid XML to simplexml_load_string to see what happens.
$translate_feed = file_get_contents('http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=' . BING_APPID . '&text=' . urlencode($text) . '&from=en&to=' . $to_lan . '');
if ( $translate_feed === false )
{
echo "failed";
}
You can do like this
if(#file_get_contents("yourFilePath.txt")){
echo "success";
}
/*
It's a modified file_get_contents()
get_contents(filename, use_include_path, context, offset, maxlen)
*/
function get_contents($url, $u = false, $c = null, $o = null) {
$headers = get_headers($url);
$status = substr($headers[0], 9, 3);
if ($status == '200') {
return file_get_contents($url, $u, $c, $o);
}
return false;
}
echo get_contents('https://example.com/');
there is $http_response_header variable is being created in local scope that we can use it to check headers returned from server. Here is my implementation:
public function getData($url)
{
try {
$response = #file_get_contents($url);
if (isset($http_response_header)) {
if (!in_array('HTTP/1.1 200 OK', $http_response_header) &&
!in_array('HTTP/1.0 200 OK', $http_response_header)) {
throw new \Exception('Server did not return success header!');
}
}
return $response;
} catch (\Exception $ex) {
throw new TransportException($ex->getMessage(), $ex->getCode(), $ex);
}
}
if( !$translate_feed) return "Failed";
$translate_feed = file_get_contents('http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=' . BING_APPID . '&text=' . urlencode($text) . '&from=en&to=' . $to_lan . '');
$result=$text;
if ($translate_feed) {
$translate = simplexml_load_string($translate_feed);
if (is_array($translate)) $result=$translate[0];
}
return $result;