O CakePHP inclui um cliente HTTP compatível com a PSR-18 que pode ser usado para fazer solicitações. É uma ótima maneira de se comunicar com serviços da web e APIs remotas.
Fazer solicitações é simples e direto. Fazer uma solicitação GET parece:
use Cake\Http\Client;
$http = new Client();
// GET simples
$response = $http->get('http://example.com/test.html');
// GET simples com querystring
$response = $http->get('http://example.com/search', ['q' => 'widget']);
// GET simples com querystring & cabeçalhos adicionais
$response = $http->get('http://example.com/search', ['q' => 'widget'], [
'headers' => ['X-Requested-With' => 'XMLHttpRequest']
]);
Fazer solicitações POST e PUT é igualmente simples:
// Envie uma solicitação POST com dados codificados em application/x-www-form-urlencoded
$http = new Client();
$response = $http->post('http://example.com/posts/add', [
'title' => 'testing',
'body' => 'content in the post'
]);
// Envie uma solicitação PUT com dados codificados application/x-www-form-urlencoded
$response = $http->put('http://example.com/posts/add', [
'title' => 'testing',
'body' => 'content in the post'
]);
// Outros métodos também.
$http->delete(/* ... */);
$http->head(/* ... */);
$http->patch(/* ... */);
Se você criou um objeto de solicitação PSR-7, pode enviá-lo usando
sendRequest()
:
use Cake\Http\Client;
use Cake\Http\Client\Request as ClientRequest;
$request = new ClientRequest(
'http://example.com/search',
ClientRequest::METHOD_GET
);
$client = new Client();
$response = $client->sendRequest($request);
Você pode incluir arquivos em corpos de solicitação:
$http = new Client();
$response = $http->post('http://example.com/api', [
'image' => fopen('/path/to/a/file', 'r'),
]);
O arquivo será lido até o fim; não será rebobinado antes de ser lido.
Pode haver momentos em que você precise criar um corpo de solicitação de
uma maneira muito específica. Nessas situações, você pode frequentemente usar
Cake\Http\Client\FormData
para criar a solicitação HTTP multipart que você deseja:
use Cake\Http\Client\FormData;
$data = new FormData();
// Crie uma parte XML
$xml = $data->newPart('xml', $xmlString);
// Defina o tipo de conteúdo.
$xml->type('application/xml');
$data->add($xml);
// Crie um upload de arquivo com addFile()
// Isso irá anexar o arquivo aos dados do formulário também.
$file = $data->addFile('upload', fopen('/some/file.txt', 'r'));
$file->contentId('abc123');
$file->disposition('attachment');
// Envie a solicitação.
$response = $http->post(
'http://example.com/api',
(string)$data,
['headers' => ['Content-Type' => $data->contentType()]]
);
Ao lidar com APIs REST, você geralmente precisa enviar corpos de solicitação que não são codificados por formulário. Http\Cliente expõe isso através da opção de tipo:
// Envie um corpo de solicitação JSON.
$http = new Client();
$response = $http->post(
'http://example.com/tasks',
json_encode($data),
['type' => 'json']
);
A chave type
pode ser “json”, “xml” ou um tipo MIME completo.
Ao usar a opção type
, você deve fornecer os dados como uma string.
Se você estiver fazendo uma solicitação GET que precisa de parâmetros de
string de consulta e um corpo de solicitação, você pode fazer o seguinte:
// Envie um corpo JSON em uma solicitação GET com parâmetros de string de consulta.
$http = new Client();
$response = $http->get(
'http://example.com/tasks',
['q' => 'test', '_content' => json_encode($data)],
['type' => 'json']
);
Cada método HTTP leva um parâmetro $options
que é usado para fornecer informações
adicionais de solicitação. As seguintes chaves podem ser usadas em $options
:
headers
- Matriz de cabeçalhos adicionais
cookie
- Matriz de cookies para usar.
proxy
- Matriz de informações do proxy.
auth
- Matriz de dados de autenticação, a chave type
é usada para delegar a uma estratégia
de autenticação. Por padrão, a autenticação básica é usada.
ssl_verify_peer
- o padrão é true
. Defina como false
para desativar a
verificação de certificação SSL (não recomendado).
ssl_verify_peer_name
- o padrão é true
. Defina como false
para desabilitar a verificação do nome
do host ao verificar os certificados SSL (não recomendado).
ssl_verify_depth
- o padrão é 5. Profundidade a ser percorrida na cadeia de CA.
ssl_verify_host
- o padrão é true
. Valide o certificado SSL em relação ao nome do host.
ssl_cafile
- o padrão é construído em cafile. Substitua para usar pacotes CA personalizados.
timeout
- Duração de espera antes de expirar em segundos.
type
- Envie um corpo de solicitação em um tipo de conteúdo personalizado. Requer que $data
seja uma string ou que a opção _content
seja definida ao fazer solicitações GET.
redirect
- Número de redirecionamentos a seguir. O padrão é false
.
O parâmetro options é sempre o terceiro parâmetro em cada um dos métodos HTTP.
Eles também podem ser usados ao construir Client
para criar scoped clients.
Cake\Http\Client
suporta alguns sistemas de autenticação. Diferentes
estratégias de autenticação podem ser adicionadas pelos desenvolvedores.
As estratégias de autenticação são chamadas antes do envio da solicitação
e permitem que cabeçalhos sejam adicionados ao contexto da solicitação.
Um exemplo de autenticação básica:
$http = new Client();
$response = $http->get('http://example.com/profile/1', [], [
'auth' => ['username' => 'mark', 'password' => 'secret']
]);
Por padrão, o Cake\Http\Client
usará a autenticação básica se não
houver uma chave 'type'
na opção auth.
Um exemplo de autenticação básica:
$http = new Client();
$response = $http->get('http://example.com/profile/1', [], [
'auth' => [
'type' => 'digest',
'username' => 'mark',
'password' => 'secret',
'realm' => 'myrealm',
'nonce' => 'onetimevalue',
'qop' => 1,
'opaque' => 'someval'
]
]);
Ao definir a chave “type” como “digest”, você informa ao subsistema de autenticação para usar a autenticação digest.
Muitos serviços da web moderna exigem autenticação OAuth para acessar suas APIs. A autenticação OAuth incluída pressupõe que você já tenha sua chave e segredo do consumidor:
$http = new Client();
$response = $http->get('http://example.com/profile/1', [], [
'auth' => [
'type' => 'oauth',
'consumerKey' => 'bigkey',
'consumerSecret' => 'secret',
'token' => '...',
'tokenSecret' => '...',
'realm' => 'tickets',
]
]);
Como OAuth2 geralmente é um único cabeçalho, não há um adaptador de autenticação especializado. Em vez disso, você pode criar um cliente com o token de acesso:
$http = new Client([
'headers' => ['Authorization' => 'Bearer ' . $accessToken]
]);
$response = $http->get('https://example.com/api/profile/1');
Alguns proxies requerem autenticação para serem usados. Geralmente, essa autenticação é Básica, mas pode ser implementada por qualquer adaptador de autenticação. Por padrão, o Http\Client assumirá a autenticação Básica, a menos que a chave de tipo seja definida:
$http = new Client();
$response = $http->get('http://example.com/test.php', [], [
'proxy' => [
'username' => 'mark',
'password' => 'testing',
'proxy' => '127.0.0.1:8080',
]
]);
O segundo parâmetro de proxy deve ser uma string com um IP ou um domínio sem protocolo. As informações de nome de usuário e senha serão passadas pelos cabeçalhos da solicitação, enquanto a string do proxy será passada por stream_context_create().
Ter que redigitar o nome de domínio, as configurações de autenticação e proxy pode se tornar tedioso e sujeito a erros. Para reduzir a chance de erro e aliviar um pouco do tédio, você pode criar clientes com escopo:
// Crie um cliente com escopo definido.
$http = new Client([
'host' => 'api.example.com',
'scheme' => 'https',
'auth' => ['username' => 'mark', 'password' => 'testing']
]);
// Faça uma solicitação para api.example.com
$response = $http->get('/test.php');
As seguintes informações podem ser usadas ao criar um cliente com escopo:
host
scheme
proxy
auth
port
cookies
timeout
ssl_verify_peer
ssl_verify_depth
ssl_verify_host
Qualquer uma dessas opções pode ser substituída, especificando-as ao fazer solicitações. host, scheme, proxy, port são substituídos no URL do pedido:
// Usando o cliente com escopo criado anteriormente.
$response = $http->get('http://foo.com/test.php');
O exemplo acima irá substituir o domínio, esquema e porta. No entanto, essa solicitação continuará usando todas as outras opções definidas quando o cliente com escopo foi criado. Veja Opções de Método para Solicitação para mais informações sobre as opções suportadas.
Os objetos de resposta têm vários métodos para inspecionar os dados recebidos.
Você lê todo o corpo da resposta como uma string:
// Leia toda a resposta como uma string.
$response->getStringBody();
Você também pode acessar o objeto stream para a resposta e usar seus métodos:
// Obtêm um Psr\Http\Message\StreamInterface contendo o corpo da resposta
$stream = $response->getBody();
// Leia um fluxo de 100 bytes por vez.
while (!$stream->eof()) {
echo $stream->read(100);
}
Como as respostas JSON e XML são comumente usadas, os objetos de resposta
fornecem acessores fáceis de usar para ler dados decodificados. Os dados
JSON são decodificados em uma matriz, enquanto os dados XML são decodificados
em uma árvore SimpleXMLElement
:
// Obtêm algum XML
$http = new Client();
$response = $http->get('http://example.com/test.xml');
$xml = $response->getXml();
// Obtêm algum JSON
$http = new Client();
$response = $http->get('http://example.com/test.json');
$json = $response->getJson();
Os dados de resposta decodificados são armazenados no objeto de resposta, portanto, acessá-lo várias vezes não tem custo adicional.
Você pode acessar os cabeçalhos por meio de alguns métodos diferentes. Os nomes dos cabeçalhos são sempre tratados como valores que não diferenciam maiúsculas de minúsculas ao acessá-los por meio de métodos:
// Obtenha todos os cabeçalhos como uma matriz associativa.
$response->getHeaders();
// Obtenha um único cabeçalho como uma matriz.
$response->getHeader('content-type');
// Obtenha um cabeçalho como uma string
$response->getHeaderLine('content-type');
// Obtenha a codificação da resposta
$response->getEncoding();
Os objetos de resposta fornecem alguns métodos para verificar os códigos de status:
// A resposta foi 20x
$response->isOk();
// A resposta foi 30x
$response->isRedirect();
// Obtenha o código de status
$response->getStatusCode();
Por padrão, o Http\Client
irá preferir usar um adaptador de transporte
baseado em curl
. Se a extensão curl não estiver disponível, um adaptador
baseado em fluxo será usado. Você pode forçar a seleção de um adaptador de
transporte usando uma opção de construtor:
use Cake\Http\Client\Adapter\Stream;
$client = new Client(['adapter' => Stream::class]);