Acessando APIs com Guzzle PHP

Cada vez mais necessitamos consumir APIs de terceiros em nossos sistemas, embora o PHP tenha maneiras nativas de fazer requisições HTTP, nem sempre elas são as maneira mais ageis e simples dependendo do contexto. Então é comum utilizarmos clientes HTTP como o Guzzle, que é uma das mais populares bibliotecas para realizar requisições HTTP, ela permite realizar requisições GET, POST, PUT, DELETE e lidar com a resposta de forma fácil e com uma sintaxe agradável.
Vamos então ver alguns exemplos de como acessar uma API simples utilizando o Guzzle, para isso vamos fazer algumas requisições a uma API fake criada com uma ferramenta que estou desenvolvendo (ainda está bastante crua mas para o básico dos exemplos vai funcionar, eu acho 🙂 ). Basta baixar o projeto que roda no servidor build-in do PHP e descompactar e rodar.
cd api/
php -S localhost:8000
Uma vez com o projeto da API rodando temos os seguintes endpoints que podemos acessar:
Url | Http Method | Descrição |
/posts | GET | Retorna todos os posts . |
/posts/1 | GET | Retorna o post cujo o id foi passado na requisição. |
/posts | POST | Espera no corpo da requisição um json com os campos “title”, “author” e “content”. Cria um novo post. |
/posts/1 | PUT | Espera no corpo da requisição um json com os campos “id”, “title”, “author” e “content”. Altera o post cujo o id foi passado na url. |
/posts/1 | DELETE | Deleta o post cujo id foi passado na url. |
/headers-return | GET | Retorna todos os headers passados na requisição como corpo da resposta. |
Você pode ver os dados no arquivo db.json
da pasta api
. Ao testar verifique o arquivo para ver as alterações ou acesse a rota /posts novamente.
Agora que temos uma API para acessar, criamos um projeto PHP e instalamos o guzzle através do composer.
composer require guzzlehttp/guzzle:^7.0
Para realizar uma requisição instanciamos um objeto Client
use GuzzleHttp\Client;
$client = new Client();
Realizando uma requisição GET com Guzzle
Para realizar uma requisição utilizamos o método request
, passando como argumento o método http desejado, no momento GET, e a URL que desejamos acessar.
use GuzzleHttp\Client;
$client = new Client();
$response = $client->request('GET', 'http://localhost:8000/posts');
echo "Status: " . $response->getStatusCode() . PHP_EOL;
$data = json_decode( (string) $response->getBody(), true );
echo "========= DADOS ===========\n";
print_r($data);
echo "===========================\n";
O método request
irá retornar um objeto Psr\Http\Message\ResponseInterface
, que é uma interface da Psr-7, nos fornecendo diversos métodos para obter informações da resposta. Na linha 7 pegamos o código de retorno HTTP através do método getStatusCode()
. Na linha 9 pegamos o corpo da resposta da requisição(ou seja, o conteúdo propriamente dito) através do método getBody()
. O método getBody()
retorna um objeto StreamInterface
que é um stream, podemos chamar o método getContents()
dele para pegar o conteúdo como uma string ou simplesmente fazer um cast para string que irá chamar o __toString().
O corpo da nossa resposta é um JSON então convertemos ele para um array. Depois somente exibimos na tela seu conteúdo.
Requisição POST
Para realizar uma requisição POST é muito parecido, apenas temos que mudar o argumento do método para POST e passar como terceiro argumento o body como um dos valores do array de options da requisição. No nosso caso, um JSON.
$client = new Client();
$response = $client->request('POST', 'http://localhost:8000/posts', [
'body' => json_encode([
'title' => 'Titulo do post',
'author' => 'Eu',
'content' => 'Um texto bobo..'
])
]);
echo "Status: " . $response->getStatusCode() . PHP_EOL;
$data = (string) $response->getBody();
echo "========= Body ===========\n";
echo $data;
echo "\n===========================\n";
No caso acima passamos os dados de forma crua, convertendo nós mesmos um array para JSON, mas podemos utilizar a opção json
em vez de body
para ele fazer a conversão automaticamente.
$response = $client->request('POST', 'http://localhost:8000/posts', [
'json' => [
'title' => 'Titulo do post',
'author' => 'Eu',
'content' => 'Um texto bobo..'
]
]);
Outra possibilidade é carregar o conteúdo do body de um arquivo e passar um stream para a opção body, podemos fazer isso com o método tryFopen
da classe Utils
.
$body = GuzzleHttp\Psr7\Utils::tryFopen('entity-post-data.json', 'r');
$response = $client->request('POST', 'http://localhost:8000/posts', [
'body' => $body
]);
Requisição PUT
A requisição PUT é basicamente a mesma ideia da post, apenas trocamos o parâmetro do método de POST para PUT.
$client = new Client();
$response = $client->request('PUT', 'http://localhost:8000/posts/2', [
'json' => [
'id' => 2,
'title' => 'Alterando titulo',
'author' => 'Eu, mas mais bonito',
'content' => 'Um texto ainda mais bobo..'
]
]);
echo "Status: " . $response->getStatusCode() . PHP_EOL;
$data = (string) $response->getBody();
echo "========= Body ===========\n";
echo $data;
echo "\n===========================\n";
Requisição DELETE
Requisições DELETE também são bastante simples apenas mudando o método.
$client = new Client();
$response = $client->request('DELETE', 'http://localhost:8000/posts/2');
echo "Status: " . $response->getStatusCode() . PHP_EOL;
Enviando e Recebendo Headers
Para enviar headers em uma requisição passamos eles como um array associativo no array de opções da requisição com a chave headers
.
No exemplo abaixo fazemos uma requisição a rota /headers-return que irá retornar todos os headers enviados na requisição como um json no body da resposta.
use GuzzleHttp\Client;
$client = new Client();
$response = $client->request('GET', 'http://localhost:8000/headers-return', [
'headers' => [
'x-my-header' => 'valor-do-header'
]
]);
echo "Status: " . $response->getStatusCode() . PHP_EOL;
$data = (string) $response->getBody();
echo "========= Response com os Headers Request ===========\n";
echo $data . PHP_EOL;
echo "=====================================\n";
$headersResponse = $response->getHeaders(); // pegando os headers da resposta
echo "========= Headers Response ===========\n";
print_r($headersResponse);
echo "=====================================\n";
No bloco de código acima pegamos os headers da resposta através do método getHeaders
do objeto $response
, lembrando que o response é um objeto ResponseInterface
da Psr7 fornecendo todos os métodos do padrão.
Autenticação HTTP Basic
O Guzzle permite enviar as credenciais da autenticação http basic de forma muito fácil, bastando passar um array com o usuário e senha para o array de opções com a chave auth
. Ele irá automáticamente criar o token e enviar no header.
$client = new Client();
try{
$response = $client->request('GET', 'http://localhost:8000/protegido', [
'auth' => ['rodrigo','123456']
]);
echo "Status: " . $response->getStatusCode() . PHP_EOL;
}catch(BadResponseException $e){
echo $e->getResponse()->getStatusCode() . PHP_EOL;
echo (string) $e->getResponse()->getBody();
}
Caso passarmos um usuário ou senha errados e ele retornar uma resposta 401, isso irá lançar uma exceção que pode ser capturada com o objeto response através do método getResponse
da exceção. Altere a senha e teste.
Bom era isso uma pequena introdução ao Guzzle, esse cliente Http bastante simples e poderoso, para mais detalhes veja a documentação. T++