Como posso usar o Guzzle para enviar uma solicitação POST em JSON?

180

Alguém sabe a maneira correta de postusar o JSON Guzzle?

$request = $this->client->post(self::URL_REGISTER,array(
                'content-type' => 'application/json'
        ),array(json_encode($_POST)));

Eu recebo uma internal server errorresposta do servidor. Funciona usando o Chrome Postman.

user3379466
fonte
A solicitação parece ok ... você verificou o conteúdo de $ _POST para ter certeza de que realmente obtém os valores antes de codificá-los? : var_dump ($ _ POST)
ylerjen
De acordo com docs agora, você pode simplesmente usar o que @davykiash disse 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

Respostas:

262

Para o Guzzle 5 e 6, você faz assim:

use GuzzleHttp\Client;

$client = new Client();

$response = $client->post('url', [
    GuzzleHttp\RequestOptions::JSON => ['foo' => 'bar'] // or 'json' => [...]
]);

Documentos

Michal Gallovic
fonte
13
Este é o caminho certo para fazer ( exemplo oficial aqui )
Pierre de LESPINAY
5
É recomendável usar RequestOptionsconstantes para as chaves do array de opções ( GuzzleHttp\RequestOptions::JSONneste caso) - isso facilita a detecção de erros de digitação, pois de repente eles se tornam avisos em vez de apenas bugs silenciosos esperando para causar problemas.
ksadowski
7
@MichalGallovic É o mesmo. O objetivo de usar a constante é evitar erros de digitação. O uso de uma constante que não existe gera um erro, mas o envio de uma opção inútil (como jssonpor exemplo) não gera nenhum erro, e você pode levar algum tempo para encontrar seu erro de digitação.
Zessx
1
Eu estava procurando por uma hora por esta resposta. Por que isso não está na documentação (especialmente no guia de configuração rápida)? Louco!?!
Sevenearths 13/03/19
1
@giovannipds GuzzleHttp \ RequestOptions :: JSON é um alias para 'json', também é bom.
Michal Gallovic
44

Para Guzzle <= 4 :

É uma solicitação de postagem bruta, portanto, colocar o JSON no corpo resolveu o problema

$request = $this->client->post($url,array(
                'content-type' => 'application/json'
        ),array());
$request->setBody($data); #set body!
$response = $request->send();

return $response;
user3379466
fonte
8
Isso não funciona mais com o GuzzleHttp. @Charlie tem a resposta certa
hbt
Acho que precisamos apenas especificar a versão do Guzzle na pergunta.
precisa saber é o seguinte
1
Se você quiser definir o cabeçalho tipo de conteúdo em Guzzle 6, você pode fazê-lo como este:$client->post($url, ['body' => $string, 'headers' => ['Content-type' => 'application/json']]);
marcovtwout
Eu tentei isso com o Guzzle3 não está funcionando, mesmo que seja da maneira mencionada no documento: guzzle3.readthedocs.io/http-client/… , faz dois dias que estou tentando resolver esse pb, mas em vão
Hanane
De acordo com docs agora, você pode simplesmente usar o que @davykiash disse 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds
42

A maneira simples e básica (guzzle6):

$client = new Client([
    'headers' => [ 'Content-Type' => 'application/json' ]
]);

$response = $client->post('http://api.com/CheckItOutNow',
    ['body' => json_encode(
        [
            'hello' => 'World'
        ]
    )]
);

Para obter o código de status da resposta e o conteúdo do corpo, fiz isso:

echo '<pre>' . var_export($response->getStatusCode(), true) . '</pre>';
echo '<pre>' . var_export($response->getBody()->getContents(), true) . '</pre>';
Frank Roth
fonte
2
Esta é realmente uma maneira simples e fácil. Resolvi meu problema sobre como definir corpo e cabeçalhos. Muito obrigado
Faisal Sarfraz
Esta resposta funciona para mim quando a resposta aceita não.
vietnguyen09
32

Isso funcionou para mim (usando o Guzzle 6)

$client = new Client(); 
$result = $client->post('http://api.example.com', [
            'json' => [
                'value_1' => 'number1',
                'Value_group' =>  
                             array("value_2" => "number2",
                                    "value_3" => "number3")
                    ]
                ]);

echo($result->getBody()->getContents());
davykiash
fonte
25
$client = new \GuzzleHttp\Client();

$body['grant_type'] = "client_credentials";
$body['client_id'] = $this->client_id;
$body['client_secret'] = $this->client_secret;

$res = $client->post($url, [ 'body' => json_encode($body) ]);

$code = $res->getStatusCode();
$result = $res->json();
CharlieJade
fonte
2
Isso também define o cabeçalho correto? Eu acho que ['json' => $body]é o melhor caminho aqui, como mencionado pela resposta de Michael.
Ja͢ck 16/06
1
$res->json();só funciona no Guzzle 5.3. Foi removido na v6.
David
1
Davi está correto. Isso ocorre devido à implementação do PSR-7. Use em json_decode()vez disso.
Andreas
10
$client = new \GuzzleHttp\Client(['base_uri' => 'http://example.com/api']);

$response = $client->post('/save', [
    'json' => [
        'name' => 'John Doe'
    ]
]);

return $response->getBody();
Yamen Ashraf
fonte
8

Isso funciona para mim com o Guzzle 6.2:

$gClient =  new \GuzzleHttp\Client(['base_uri' => 'www.foo.bar']);
$res = $gClient->post('ws/endpoint',
                            array(
                                'headers'=>array('Content-Type'=>'application/json'),
                                'json'=>array('someData'=>'xxxxx','moreData'=>'zzzzzzz')
                                )
                    );

De acordo com a documentação, guzzle faça o json_encode

arcos.lwm
fonte
7
use GuzzleHttp\Client;

$client = new Client();

$response = $client->post('url', [
    'json' => ['foo' => 'bar']
]);

Veja Documentos .

Nurul Huda
fonte
2

Versão Php: 5.6

Versão Symfony: 2.3

Guzzle: 5.0

Recentemente, tive uma experiência sobre o envio de json com o Guzzle. Eu uso o Symfony 2.3 para que minha versão do guzzle possa ser um pouco mais antiga.

Também mostrarei como usar o modo de depuração e você poderá ver a solicitação antes de enviá-la,

Quando fiz o pedido, como mostrado abaixo, obtive a resposta bem-sucedida;

use GuzzleHttp\Client;

$headers = [
        'Authorization' => 'Bearer ' . $token,        
        'Accept'        => 'application/json',
        "Content-Type"  => "application/json"
    ];        

    $body = json_encode($requestBody);

    $client = new Client();    

    $client->setDefaultOption('headers', $headers);
    $client->setDefaultOption('verify', false);
    $client->setDefaultOption('debug', true);

    $response = $client->post($endPoint, array('body'=> $body));

    dump($response->getBody()->getContents());
Tuncay Elvanağaç
fonte
0

A resposta de @ user3379466 pode ser configurada da $dataseguinte maneira:

$data = "{'some_key' : 'some_value'}";

O que nosso projeto precisava era inserir uma variável em uma matriz dentro da string json, que fiz da seguinte maneira (caso isso ajude alguém):

$data = "{\"collection\" : [$existing_variable]}";

Assim $existing_variablesendo, digamos, 90210, você obtém:

echo $data;
//{"collection" : [90210]}

Também digno de nota é que você também pode definir o 'Accept' => 'application/json'caso, caso o terminal que você está atingindo se importe com esse tipo de coisa.

j boschiero
fonte
Apenas um heads-up ... você pode simplificar o seu $datausando json_encode:$data = json_encode(array('collection' => $existing_variable));
phpisuber01 30/10
0

@ user3379466 está correto, mas aqui reescrevo na íntegra:

-package that you need:

 "require": {
    "php"  : ">=5.3.9",
    "guzzlehttp/guzzle": "^3.8"
},

-php code (Digest is a type so pick different type if you need to, i have to include api server for authentication in this paragraph, some does not need to authenticate. If you use json you will need to replace any text 'xml' with 'json' and the data below should be a json string too):

$client = new Client('https://api.yourbaseapiserver.com/incidents.xml', array('version' => 'v1.3', 'request.options' => array('headers' => array('Accept' => 'application/vnd.yourbaseapiserver.v1.1+xml', 'Content-Type' => 'text/xml'), 'auth' => array('[email protected]', 'password', 'Digest'),)));

$url          = "https://api.yourbaseapiserver.com/incidents.xml";
        
$data = '<incident>
<name>Incident Title2a</name>
<priority>Medium</priority>
<requester><email>[email protected]</email></requester>
<description>description2a</description>
</incident>';

    $request = $client->post($url, array('content-type' => 'application/xml',));

    $request->setBody($data); #set body! this is body of request object and not a body field in the header section so don't be confused.

    $response = $request->send(); #you must do send() method!
    echo $response->getBody(); #you should see the response body from the server on success
    die;

--- Solução para o * Guzzle 6 * --- -package que você precisa:

 "require": {
    "php"  : ">=5.5.0",
    "guzzlehttp/guzzle": "~6.0"
},

$client = new Client([
                             // Base URI is used with relative requests
                             'base_uri' => 'https://api.compay.com/',
                             // You can set any number of default request options.
                             'timeout'  => 3.0,
                             'auth'     => array('[email protected]', 'dsfddfdfpassword', 'Digest'),
                             'headers' => array('Accept'        => 'application/vnd.comay.v1.1+xml',
                                                'Content-Type'  => 'text/xml'),
                         ]);

$url = "https://api.compay.com/cases.xml";
    $data string variable is defined same as above.


    // Provide the body as a string.
    $r = $client->request('POST', $url, [
        'body' => $data
    ]);

    echo $r->getBody();
    die;
Estrume
fonte
Obrigado. Não foi possível encontrar nenhuma solução guzzle3 em nenhum outro lugar para projetos herdados do php5.3, gostaria de vê-la com quebra de linha, como o seu guzzle6 também, pois isso me pouparia muito tempo.
taur 10/07
0

As respostas acima não funcionaram para mim de alguma forma. Mas isso funciona bem para mim.

 $client = new Client('' . $appUrl['scheme'] . '://' . $appUrl['host'] . '' . $appUrl['path']);

 $request = $client->post($base_url, array('content-type' => 'application/json'), json_encode($appUrl['query']));
Suraj
fonte
0

Basta usar isso funcionará

   $auth = base64_encode('user:'.config('mailchimp.api_key'));
    //API URL
    $urll = "https://".config('mailchimp.data_center').".api.mailchimp.com/3.0/batches";
    //API authentication Header
    $headers = array(
        'Accept'     => 'application/json',
        'Authorization' => 'Basic '.$auth
    );
    $client = new Client();
    $req_Memeber = new Request('POST', $urll, $headers, $userlist);
    // promise
    $promise = $client->sendAsync($req_Memeber)->then(function ($res){
            echo "Synched";
        });
      $promise->wait();

fonte