How to make http request to another server through Laravel?
I'll be pleased to provide whatever information you need
any help is much appreciated
Depends how complex the request needs to be. You can use curl or even, file_get_contents for simple get requests, or install a package like Guzzle for more complex things.
https://github.com/guzzle/guzzle
With 'normal' PHP, you can use Curl to work with the http protocol (POST/GET). If you are using Laravel, you can either build your own curl methods or you can use a 3rd party curl library compatible with composer/Laravel:
https://packagist.org/packages/unikent/curl
You can use Guzzle
add the dependency package in the composer.json file
{
"require": {
"guzzlehttp/guzzle": "~4.0" //you can change the version
}
}
make composer install or update
To create your very first request with guzzle, a code snippet as simple as below will work:
use GuzzleHttp\Client;
use GuzzleHttp\Message\Request;
use GuzzleHttp\Message\Response;
$client = new Client();
$response = $client->get("https://api.github.com/");
retrun $response;
If for some reason you are running an old Laravel version or don't want to bother with guzzle, you can always use php-curl:
sudo apt-get install php-curl
Then create a function for your needs eg POST:
function httpPost($url, $data){
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
or GET
public function httpGet($url){
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
Simply call your function in controller:
$response = $this->httpPost($url, $data);
$response = $this->httpget($url);
Where $url is your endpoint where you need to send request and $data - parameters required.
First of all run this command
composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
$client = new Client();
$response = $client->get("http://www.somewebsite.com/getSmth");
$response = (string) $response->getBody();
return $response;
getBody() function will return object.
You can use via converting to string and after that if you want you can change it to integer also
$response = (int) (string) $response->getBody();
Related
I am posting data(including a media file (.wav)) from my app to an API with curl. When submitting my data, i check for the data including the mediafile submitted in my API. From the response i get from my API, see below
Response
{"status":"success","media":false,"data":{"message":"Media Campaign","recipient":["34505140704"],
"file":{"name":"\/Users\/path\/to\/folder\/public\/Voice\/aaaah.wav","mime":null,"postname":null}}}true
In the response, the file is being retrieved as well but when i check for the file using $request->hasFile('file') or $request->file('file'), I get false and null respectively.
Can someone let me know why this is happening in my code please ?
Controller
public function test()
{
$file_name_with_full_path = '/Users/path/to/folder/public/Voice/aaaah.wav';
if(function_exists('curl_file_create'))
{
$cFile = curl_file_create($file_name_with_full_path);
}
else
{
$cFile = '#' . realpath($file_name_with_full_path);
}
$post = array('message' => 'Media Campaign', 'recipient' => ['34505140704'],'file' => $cFile);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$result=curl_exec ($ch);
curl_close ($ch);
}
APIController
public function campaign(Request $request)
{
if (($request->get('message')) {
return response()->json([
'status' => 'success',
'data' => $request->all()
]);
}
}
To be honest, I'd use Guzzle to hide the details of cURL requests in PHP. The way PHP's cURL extension handles file transfers changed a couple of years ago, which broke a lot of legacy code at the company I was working for. By using a third-party wrapper like Guzzle, you can let the Guzzle developers worry about changes in the underlying extension - all you need to do is keep your Guzzle package up to date.
PHP - Why Use Guzzle Instead of cURL?
I'm trying to use laravel-wp-api to get the posts from a blog. When I use Postman with http://idareyou.ee/blog//wp-json/wp/v2/posts I get a 200 OK HTTP response and Postman shows the JSON result.
The following Laravel BlogController getPosts() method prints in the browser this Curl error:
{"error":{"message":"cURL error 6: Couldn't resolve host '\u003Cwp_location\u003E' (see http:\/\/curl.haxx.se\/libcurl\/c\/libcurl-errors.html)"},"results":[],"total":0,"pages":0}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use WpApi;
class BlogController extends Controller
{
public function getPosts()
{
$posts = WpApi::posts('http://idareyou.ee/blog//wp-json/wp/v2/posts');
echo json_encode($posts,true);
//return view('pages.blog', ['active'=>'navBlog'])->with('posts', $posts );
}
}
Elsewhere in my app I am fetching successfully some pictures from Instagram API using the following. Do I need a similar 'fetchData' function in my BlogController?
function fetchData($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
$result = fetchData("https://api.instagram.com/v1/users/.......");
$result = json_decode($result, true);
$lastFive = array_slice($result['data'], 0, 5); // returns last 5 instagram pics
Can anybody give me any tips on what I'm doing wrong?
I would check the config file for this service - my guess is you need to set-up the endpoint (blog domain) for your calls. So once you run php artisan vendor:publish you should have a specific config file under app/config - see if there's a setting there you need to change.
Hope this helps!
I need to make a route in a Symfony 3 app (server 1), which has to send a (filtered) request on a server 2, then send back the exact response given by the server 2 (same HTTP status code, headers and body).
With the native curl Php library, you can get the raw response (including headers), by setting the CURLOPT_HEADER option to True.
But the Response object from Symfony HttpFoundation seems to be only configurable by setting separately headers (inside the constructor, or with $response->headers->set()) and body (with $response->setContent(). I didn't find a way to set a raw response (with headers) into the Response object.
Is it possible, or how could it be done otherwise?
Here's my try:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class MyController extends Controller
{
/**
* #Route("/get", name="get")
*/
public function getAction(Request $request)
{
// Filter/modify the query string, but keep it quite similar:
$request->query->remove('some_private_attr');
$my_query_string = http_build_query($request->query->all());
// Setup the curl request:
$curl = curl_init('http://localhost?'.$my_query_string);
curl_setopt($curl, CURLOPT_HEADER, 1); // Include headers
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // Return data as a string
curl_setopt($curl, CURLOPT_PORT, 8200);
// Perform the request, returning the raw response
// (headers included) as a string:
$result = curl_exec($curl);
// Get the response status code:
$status_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
// Here, how can I pass the raw external response ($result)
// to a new Response object, without parsing the header
// and body parts unnecessarily?
// Of course, the following doesn't send the right headers:
$response = new Response($result, $status_code);
return $response;
}
}
You should be able to use (for example):
$response->headers->set('Content-Type', 'text/plain');
which is described here:
http://symfony.com/doc/current/components/http_foundation.html#response
The Response API also describes each of the methods. I'm not certain what type of header you need to send.
I had the exact same issue. I basically wanted to forward the CurlResponse as a Response by the controller.
I implemented this as follows, using the standard Symfony HttpClient:
public function myAction()
{
/** #var Request $request */
$request = $this->container->get('request_stack')->getCurrentRequest();
$my_query_string = http_build_query($request->query->all());
$client = HttpClient::create();
$url = 'http://localhost?'.$my_query_string;
$response = $client->request('GET', $url);
$statusCode = $response->getStatusCode();
$headers = $response->getHeaders();
$content = $response->getContent();
return new JsonResponse($content, $statusCode, $headers);
}
If your content is already Json, add the optional parameter true to JsonResponse.
I've got an app which works with Digits as authentication.
Client-side works perfectly, but I'm not able to make the server user authentication through oAuth.
My server is developed with Laravel, so it's PHP.
My endpoint is under https, so everything should be ready to make the call.
I solved by myself!
Here's the code that makes correctly the authentication through Digits O-Auth.
The function that makes authentication is inside an AuthManager class and I call in this way:
$obj = AuthManager::verifyUser($request->header('X-Auth-Service-Provider'),$request->header("X-Verify-Credentials-Authorization"));
And here's the function that makes the magic:
public static function verifyUser ($xAuthServiceProvider, $xVerifyCredentialsAuthorization)
{
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL, $xAuthServiceProvider);
curl_setopt($curl,CURLOPT_HTTPHEADER, array(
'Content-length: 0',
'Content-type: application/json',
'Authorization: '.$xVerifyCredentialsAuthorization,
));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
$obj = json_decode($content, true);
return $obj;
}
If you have any problem, don't hesitate to write here!
EDIT WITH EXAMPLE FUNCTION ABOUT HOW TO GET DATA FROM O-AUTH
public function authenticate (Request $request)
{
$obj = AuthManager::verifyUser($request->header('X-Auth-Service-Provider'),$request->header("X-Verify-Credentials-Authorization"));
if(isset($obj["errors"]))
{
return "error!";
}
$digits_token = $obj["access_token"]["token"];
$digitsId = $obj["id"];
/*
the variables above are returned by O-auth server-server authentication
*/
}
Using Symfony2, I need to access an external API based on HTTPS.
How can I call an external URI and manage the response to "play" with it. For example, to render a success or a failure message?
I am thinking in something like (note that performRequest is a completely invented method):
$response = $this -> performRequest("www.someapi.com?param1=A¶m2=B");
if ($response -> getError() == 0){
// Do something good
}else{
// Do something too bad
}
I have been reading about Buzz and other clients. But I guess that Symfony2 should be able to do it by its own.
I'd suggest using CURL:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'www.someapi.com?param1=A¶m2=B');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); // Assuming you're requesting JSON
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
// If using JSON...
$data = json_decode($response);
Note: The php on your web server must have the php5-curl library installed.
Assuming the API request is returning JSON data, this page may be useful.
This doesn't use any code that is specific to Symfony2. There may well be a bundle that can simplify this process for you, but if there is I don't know about it.
Symfony doesn't have a built-in service for this, but this is a perfect opportunity to create your own, using the dependency injection framework. What you can do here is write a service to manage the external call. Let's call the service "http".
First, write a class with a performRequest() method:
namespace MyBundle\Service;
class Http
{
public function performRequest($siteUrl)
{
// Code to make the external request goes here
// ...probably using cUrl
}
}
Register it as a service in app/config/config.yml:
services:
http:
class: MyBundle\Service\Http
Now your controller has access to a service called "http". Symfony manages a single instance of this class in the "container", and you can access it via $this->get("http"):
class MyController
{
$response = $this->get("http")->performRequest("www.something.com");
...
}
Best client that I know is: http://docs.guzzlephp.org/en/latest/
There is already bundle that integrates it into Symfony2 project:
https://github.com/8p/GuzzleBundle
$client = $this->get('guzzle.client');
// send an asynchronous request.
$request = $client->createRequest('GET', 'http://httpbin.org', ['future' => true]);
// callback
$client->send($request)->then(function ($response) {
echo 'I completed! ' . $response;
});
// optional parameters
$response = $client->get('http://httpbin.org/get', [
'headers' => ['X-Foo-Header' => 'value'],
'query' => ['foo' => 'bar']
]);
$code = $response->getStatusCode();
$body = $response->getBody();
// json response
$response = $client->get('http://httpbin.org/get');
$json = $response->json();
// extra methods
$response = $client->delete('http://httpbin.org/delete');
$response = $client->head('http://httpbin.org/get');
$response = $client->options('http://httpbin.org/get');
$response = $client->patch('http://httpbin.org/patch');
$response = $client->post('http://httpbin.org/post');
$response = $client->put('http://httpbin.org/put');
More info can be found on: http://docs.guzzlephp.org/en/latest/index.html
https://github.com/sensio/SensioBuzzBundle seems to be what you are looking for.
It implements the Kris Wallsmith buzz library to perform HTTP requests.
I'll let you read the doc on the github page, usage is pretty basic:
$buzz = $this->container->get('buzz');
$response = $buzz->get('http://google.com');
echo $response->getContent();
Symfony does not have its own rest client, but as you already mentioned there are a couple of bundles. This one is my prefered one:
https://github.com/CircleOfNice/CiRestClientBundle
$restClient = $this->container->get('ci.restclient');
$restClient->get('http://www.someUrl.com');
$restClient->post('http://www.someUrl.com', 'somePayload');
$restClient->put('http://www.someUrl.com', 'somePayload');
$restClient->delete('http://www.someUrl.com');
$restClient->patch('http://www.someUrl.com', 'somePayload');
$restClient->head('http://www.someUrl.com');
$restClient->options('http://www.someUrl.com', 'somePayload');
$restClient->trace('http://www.someUrl.com');
$restClient->connect('http://www.someUrl.com');
You send the request via
$response = $restclient->get($url);
and get a Symfony response object.
Then you can get the status code via
$httpCode = $response-> getStatusCode();
Your code would look like:
$restClient = $this->container->get('ci.restclient');
if ($restClient->get('http://www.yourUrl.com')->getStatusCode !== 200) {
// no error
} else {
// error
}
Use the HttpClient class to create the low-level HTTP client that makes requests, like the following GET request:
use Symfony\Component\HttpClient\HttpClient;
$client = HttpClient::create();
$response = $client->request('GET', 'https://api.github.com/repos/symfony/symfony-docs');
$statusCode = $response->getStatusCode();
// $statusCode = 200
$contentType = $response->getHeaders()['content-type'][0];
// $contentType = 'application/json'
$content = $response->getContent();
// $content = '{"id":521583, "name":"symfony-docs", ...}'
$content = $response->toArray();
// $content = ['id' => 521583, 'name' => 'symfony-docs', ...]
This is compatible with Symfony 5. Symfony Manual on this topic: The HttpClient Component