Laravel get_file_contents() replaces & with & - php

How can I avoid Laravel replacing & with & when calling get_file_contents()? I always get a "Bad Request" response because of this,
which is not a problem when not using Laravel.

use file_get_contents(htmlspecialchars_decode($URL));

I solve my problem just use the " instead ' when building string URL path like follow:
public function __construct($url, $username, $password)
{
$this->url = $url;
$this->params = 'send?username='.$username.'&password='.$password.'&dlr=no';
}
to:
public function __construct($url, $username, $password)
{
$this->url = $url;
$this->params = "send?username=".$username."&password=".$password."&dlr=no";
}
Instead of use file_get_contents() you can use guzzlehttp/guzzle you can use this link for installation, and following example to send request and get response:
$client = new Client([
'base_uri' => $this->url,
'timeout' => 1.0,
]);
$request = $client->request('POST', $params);
$response = $request->getBody()->getContents();
You can access the content's of body by getContents() method, hop this help you.

Related

Why GuzzleHttp client throws ClientException when using it to make network request on Laravel/Lumen?

I am currently building a Financial micro service application using Laravel/Lumen micro framework.Everything have been working perfectly as expected. My problem now is that i am trying to make a network request to my internal services via Api call from ApiGateway using GuzzleHttp client. The problem is that when i make request to the internal service, it always throws an exception of ClientException.
ClientException.
Client error: GET http://127.0.0.1:8081/v1/admin resulted in a 401
Unauthorized response: {"error":"Unauthorized.","code":401}
I have tried to make network request to the same internal services using postman; and it works fine. However, for some reason still fail to work with GuzzleHttp. I don't know what i am doing wrong. Please your assist will be appreciated.
Here is the httpClient.php in ApiGateway.
//Constructor method
public function __construct() {
$this->baseUri = config('services.auth_admin.base_uri');
}
public function httpRequest($method, $requestUrl, $formParams = [], $headers = []) {
//Instantiate the GazzleHttp Client
$client = new Client([
'base_uri' => $this->baseUri,
]);
//Send the request
$response = $client->request($method, $requestUrl, ['form_params' => $formParams, 'headers' => $headers]);
//Return a response
return $response->getBody();
}
//Internal Service Communication in ApiGateway**
public function getAdmin($header) {
return $this->httpRequest('GET', 'admin', $header);
}
InternalServiceController.php
public function getAdmin(Request $request) {
return $this->successResponse($this->authAdminService->getAdmin($request->header()));
}
I am using Lumen version: 5.8 and GuzzleHttp Version: 6.3
You pass your headers as formParams (third index instead of fourth).
Try below:
return $this->httpRequest('GET', 'admin', [], $header);
I am making some assumptions here which I hope should be helpful to you.
PHP does not support skipping optional parameters and thus you should pass an empty array [] when calling httpRequest().
public function httpRequest($method, $requestUrl, $formParams = [], $headers = [], $type='json', $verify = false) {
//Instantiate the GazzleHttp Client
$client = new Client([
'base_uri' => $this->baseUri,
]);
//the request payload to be sent
$payload = [];
if (!$verify) {
$payload['verify'] = $verify; //basically for SSL and TLS
}
//add the body to the specified payload type
$payload[$type] = $formParams;
//check if any headers have been passed and add it as well
if(count($headers) > 0) {
$payload['headers'] = $headers;
}
//Send the request
$response = $client->request($method, $requestUrl, $payload);
//Return a response
return $response->getBody();
}
Now you need to call it in this manner when you are not passing in any form_params or body
//Internal Service Communication in ApiGateway**
public function getAdmin($header) {
return $this->httpRequest('GET', 'admin', [], $header);
}

PHP - Guzzle Middleware

I'm using the Pole Emploi's API,but I encounter 401 error 25 minutes later, when my token expires.
I looked for a way to get a new token and retry the request, but no way for me to understand how Middlewares work, and if I should use a middleware for my needings.
On Guzzle's docs this is written :
Middleware functions return a function that accepts the next handler to invoke. This returned function then returns another function that acts as a composed handler-- it accepts a request and options, and returns a promise that is fulfilled with a response. Your composed middleware can modify the request, add custom request options, and modify the promise returned by the downstream handler.
And this is an example code from the docs :
use Psr\Http\Message\RequestInterface;
function my_middleware()
{
return function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
return $handler($request, $options);
};
};
}
So I think I need to manage the "promise" to see if its HTTP code is 401, and then get a new token and retry the request ?
I'm lost, so I would appreciate if someone can explain me the logic of this with different words maybe :)
Thank you in advance.
It doesn't need to be that difficult, add a handler that takes care of the job, in combination with cache that expires.
If you don't use cache then I guess you could probably save it to a file along with a timestamp for expiration that you check against when fetching it.
class AuthenticationHandler
{
private $username;
private $password;
private $token_name = 'access_token';
public function __construct($username, $password)
{
$this->username = $username;
$this->password = $password;
}
public function __invoke(callable $handler)
{
return function (RequestInterface $request, array $options) use ($handler) {
if (is_null($token = Cache::get($this->token_name))) {
$response = $this->getJWT();
Cache::put($this->token_name, $token = $response->access_token, floor($response->expires_in));
}
return $handler(
$request->withAddedHeader('Authorization', 'Bearer '.$token)
->withAddedHeader('Api-Key', $this->api_key), $options
);
};
}
private function getJWT()
{
$response = (new Client)->request('POST', 'new/token/url', [
'form_params' => [
'grant_type' => 'client_credentials',
'username' => $this->username,
'password' => $this->password,
],
]);
return json_decode($response->getBody());
}
}
Then use it:
$stack = HandlerStack::create(new CurlHandler());
$stack->push(new AuthenticationHandler('username', 'password'));
$client = new GuzzleHttp\Client([
'base_uri' => 'https://api.com',
'handler' => $stack,
]);
Now you will always have a valid token, and you will never have to worry about it ever again.
I wouldn't recommend doing this as it can become hell to debug your application and as far as I am aware Guzzle doesn't really allow access to the client from middleware. Regardless you can use Promises to get around. If I were you I would refresh token before other requests, or refresh periodically. It might be fine if you are firing requests one by one, but in a Pool it will become a nightmare because you can end up having script fetch token too often and then some request ends up with out-dated token.
Anyway here is a rough example:
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
function my_middleware()
{
return function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
/**
* #var $promise \GuzzleHttp\Promise\Promise
*/
$promise = $handler($request, $options);
return $promise->then(
function (ResponseInterface $response) use ($request, $options) {
if ($response->getStatusCode() === 404) {
var_dump($response->getStatusCode());
var_dump(strlen($response->getBody()));
// Pretend we are getting new token key here
$client = new Client();
$key = $client->get('https://www.iana.org/domains/reserved');
// Then we modify the failed request. For your case you use ->withHeader() to change the
// Authorization header with your token.
$uri = $request->getUri();
$uri = $uri->withHost('google.com')->withPath('/');
// New instance of Request
$request = $request->withUri($uri);
// Send the request again with our new header/URL/whatever
return $client->sendAsync($request, $options);
}
return $response;
}
);
};
};
}
$handlerStack = HandlerStack::create();
$handlerStack->push(my_middleware());
$client = new Client([
'base_uri' => 'https://example.org',
'http_errors' => false,
'handler' => $handlerStack
]);
$options = [];
$response = $client->request('GET', '/test', $options);
var_dump($response->getStatusCode());
var_dump(strlen($response->getBody()));
echo $response->getBody();

Use Yii2 REST client to consume Yii2 REST API

I have created a REST API using the Yii2 documentation. It seems to be working fine as I can use curl like this:
curl -i "https://example.com/api/v3/user" \
-H "Accept:application/json" \
-H "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
I would now like to be able to consume this data from another Yii2 site. I am trying to use the Yii2 REST API client. I won't post the whole code as it's basically a copy of the Facebook client in yiisoft/yii2-authclient.
Does anyone know of a guide to help me amend this to comsume my API? In the first instance, I'm struggling with what to put for $authUrl and $tokenUrl.
I am not sure if you need to extend outh2 class as I believe you don't have the authentication logic completed in the first Yii2 webapp, like authenticating using first webapp url then redirect to the second webapp to extract the token from url.
It could be simpler just create a component that have those methods
class YourRestClient {
const BASE_URL = 'https://example.com/api/v3';
private $_token = null;
public function authenticate($username,$password){
$client = new Client();
$response = $client->createRequest()
->setMethod('POST')
->setUrl(BASE_URL.'/user/login')
->setData(['username' => $username, 'password' => $password])
->send();
if ($response->isOk) {
$this->_token = $response->data['token'];
}
}
public function logout(){
//your logut logic
}
public function refreshToken(){
//your refresh logic
}
public function userList(){
$client = new Client();
$response = $client->createRequest()
->setMethod('GET')
->setUrl(BASE_URL.'/user/users')
->addHeaders([
'content-type' => 'application/json',
'Authorization' => 'Bearer '.$_token,
])
->send();
if ($response->isOk) {
return $response->getData();
}
}
}
for more info httpclient
If I am not wrong what you will need for this, is to use yiisoft/yii2-httpclient
Ref: https://github.com/yiisoft/yii2-httpclient
Add it: php composer.phar require --prefer-dist yiisoft/yii2-httpclient
Then make the call «I would probably build a model to handle this»
use yii\httpclient\Client;
$client = new Client();
$response = $client->createRequest()
->setMethod('GET')
->setUrl('https://example.com/api/v3/user')
->addHeaders(['Authorization' => 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'])
->send();
if ($response->isOk) {
// use your data
}

Figuring out function arguments of a webservice function

For reasons beyond my control, I'm forced to use NuSoap instead of SOAP to make a request to a webservice.
After some searching, I found SOAP's __getFunctions() equivalent in NuSoap. The part where I'm stuck now is to figure out in what format are the parameters expected by the webservice's function.
require_once(APPPATH.'libraries/nusoap.php');
$baseurl = 'http://www.webservicex.net/geoipservice.asmx?WSDL';
$client = new nusoap_client($baseurl, true);
$err = $client->getError();
if ($err) {
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
die();
}
$proxy = $client->getProxyClassCode();
print_r($proxy);
The above is giving me an output of
class nusoap_proxy_1027585735 extends nusoap_client
{
// http://www.webservicex.net/:GetGeoIP^
$parameters function GetGeoIP($parameters)
{
$params = array('parameters' => $parameters);
return $this->call('GetGeoIP', $params, 'http://testuri.com', 'http://www.webservicex.net/GetGeoIP');
}
// http://www.webservicex.net/:GetGeoIPContext^
$parameters function GetGeoIPContext($parameters)
{
$params = array('parameters' => $parameters);
return $this->call('GetGeoIPContext', $params, 'http://testuri.com', 'http://www.webservicex.net/GetGeoIPContext');
}
}
So now that I know the function names (GetGeoIP and GetGeoIPContext), I'm struggling to find out what parameters do I need to pass to those functions.
I'm guessing $params = array('parameters' => $parameters); is the part I should be interested in, but that isn't giving the complete picture.
So in short, is there SOAP's __getTypes() equivalent in NuSoap?
You can use SoapUI to get an example of the request.
If you create a new project with your url endPoint (WSDL) you can get all the soapCalls. With it is more easy to understand the types define in the WSDL.
Follow this link http://www.soapui.org/SOAP-and-WSDL/working-with-wsdls.html
$parameters is an array (key -> value) for each param in the request
$parameters = array('IPAddress' => 'xxx.xxx.xxx.xxx')
$opdata = $proxy->getOperationData('GetGeoIP'); The method getOperationData is inherited from nusoap_client. See http://www.contao-docs.org/docs/nusoap/html/classnusoap__client.html.

How to retrieve full Zend_Http_Client GET URI?

I have something like that:
$client = new Zend_Http_Client('http://www.site.com');
$client->setParameterGet(array(
'platform' => $platform,
'clientId' => $clientId,
'deploymentId' => $deploymentId,
));
try {
$response = $client->request();
...
This would generate a request similar to 'http://www.site.com/?plataform=..?clientid?..'.
Is there a way I could retrieve this full URL generated by this GET request?
Kind regards,
Surprisingly enough there is no direct method for getting full request string.
BUT
After the request is done you could check $client->getLastRequest
().
If you need to know what the ?plataform=..?clientid? part of the
request is there is a trick.
function getClientUrl (Zend_Http_Client $client)
{
try
{
$c = clone $client;
/*
* Assume there is nothing on 80 port.
*/
$c->setUri ('http://127.0.0.1');
$c->getAdapter ()
->setConfig (array (
'timeout' => 0
));
$c->request ();
}
catch (Exception $e)
{
$string = $c->getLastRequest ();
$string = substr ($string, 4, strpos ($string, "HTTP/1.1\r\n") - 5);
}
return $client->getUri (true) . $string;
}
$client = new Zend_Http_Client ('http://yahoo.com');
$client->setParameterGet ('q', 'search string');
echo getClientUrl ($client);

Categories