Assume that you have an application that will consume an API with Basic Auth authentication. To do such thing, you can implement example below.


Composer.json


Install "guzzlehttp/guzzle": "4.2.3" with composer. If you're using a MAC OS then do not use .local tld which is reserved for Bonjour service otherwise response will be really slow. Use something like .dev instead.


Controllers.yml


services:
application_backend.controller.api:
class: Application\BackendBundle\Controller\ApiController
arguments:
- @application_backend.service.api

Services.yml


services:
application_backend.service.api:
class: Application\BackendBundle\Service\ApiService
arguments:
- @application_backend.util.api_helper

Utils.yml


services:
application_backend.util.api_helper:
class: Application\BackendBundle\Util\ApiHelper

ApiController


namespace Application\BackendBundle\Controller;

use Application\BackendBundle\Service\ApiServiceInterface;
use Exception;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

/**
* @Route("api", service="application_backend.controller.api")
*/
class ApiController extends AbstractController
{
private $apiService;

public function __construct(ApiServiceInterface $apiService)
{
$this->apiService = $apiService;
}

/**
* @param Request $request
*
* @Route("/student")
* @Route("/lecturer")
* @Route("/admin")
*
* @return Response
*/
public function proxyAction(Request $request)
{
try {
$response = $this->apiService->call(
'student', // student|lecturer|admin
$request->getMethod(),
$request->getPathInfo(),
$request->query->all(),
$request->getContent()
);

return new Response(json_encode($response));
} catch (Exception $e) {
throw new BadRequestHttpException($e->getMessage(), null, $e->getCode());
}
}
}

ApiServiceInterface


namespace Application\BackendBundle\Service;

use Application\BackendBundle\Model\Response;

interface ApiServiceInterface
{
/**
* @param string $user
* @param string $method
* @param string $uri
* @param array $getParams
* @param string|null $postData
*
* @return Response
*/
public function call($user, $method, $uri, array $getParams = [], $postData = null);
}

ApiService


namespace Application\BackendBundle\Service;

use Application\BackendBundle\Model\Response;
use Application\BackendBundle\Util\ApiHelper;

class ApiService implements ApiServiceInterface
{
private $apiHelper;

public function __construct(ApiHelper $apiHelper)
{
$this->apiHelper = $apiHelper;
}

/**
* @param string $user
* @param string $method
* @param string $uri
* @param array $getParams
* @param string|null $postData
*
* @return Response
*/
public function call($user, $method, $uri, array $getParams = [], $postData = null)
{
return $this->apiHelper->call($user, $method, $uri, $getParams, $postData);
}
}

ApiHelper


namespace Application\BackendBundle\Util;

use Application\BackendBundle\Model\Response;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\BadResponseException;
use GuzzleHttp\Stream\Stream;

class ApiHelper
{
const API_ENDPOINT = 'http://webservice.local/app_dev.php';

// These users are defined in API application
private $authorisation = [
'student' => 'Basic c3R1ZGVudDpzdHVkZW50',
'lecturer' => 'Basic bGVjdHVyZXI6bGVjdHVyZXI=',
'admin' => 'Basic YWRtaW46YWRtaW4=',
];

/**
* @param string $user
* @param string $method
* @param string $uri
* @param array $getParams
* @param string|null $postData
*
* @return Response
*/
public function call($user, $method, $uri, array $getParams = [], $postData = null)
{
return $this->consume(
$method,
$this->createUri($uri, $getParams),
$this->authorisation[$user],
$postData
);
}

/**
* @param string $uri
* @param array $getParams
*
* @return string
*/
private function createUri($uri, array $getParams = [])
{
return sprintf(
'%s%s?%s',
self::API_ENDPOINT,
$uri,
http_build_query($getParams)
);
}

/**
* @param string $method
* @param string $uri
* @param string $auth
* @param string|null $postData
*
* @return Response
*/
private function consume($method, $uri, $auth, $postData = null)
{
$response = new Response();

try {
$client = new Client();
$request = $client->createRequest($method, $uri);
$request->addHeader('Authorization', $auth);
$request->addHeader('Content-Type', 'application/json');
$request->setBody(Stream::factory($postData));
$result = $client->send($request);

$response->code = $result->getStatusCode();
$response->message = json_decode($result->getBody(), true);
} catch (BadResponseException $e) {
$response->code = $e->getCode();
$response->message = $e->getMessage();
}

return $response;
}
}

If you use Guzzle 6.1.1 version, you can use example code below.


use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Stream;

$client = new Client();
/** @var Response $response */
$response = $client->request(
'POST',
'http://www.whatever.com/api/student',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Basic 23erfgh678iED6tyuh'
],
'body' => $postData
]
);

Test


Your application http://football.local/ consumes http://webservice.local/ API. As you can see above, there are three different types of users which are student | lecturer | admin and all have restricted access rights to endpoints.


GET http://football.local/app_dev.php/api/student?name=inanzzz


User student is being used.


# Response
{"code":"200","message":"Hello inanzzz"}

API endpoint side.


/**
* @param Request $request
*
* @Method({"GET"})
* @Route("/student")
* @Security("has_role('ROLE_STUDENT')")
*
* @return Response
*/
public function studentAction(Request $request)
...

POST http://football.local/app_dev.php/api/student


User admin is being used.


# Request
{
"name": "inanzzz"
}

# Response
{"code":"200","message":"{\n \"name\": \"inanzzz\"\n}"}

API endpoint side.


/**
* @param Request $request
*
* @Method({"POST"})
* @Route("/student")
* @Security("has_role('ROLE_ADMIN')")
*
* @return Response
*/
public function createAction(Request $request)
...