2016-01-03 18 views
7

Nie jest wysyłany lub nie jest odbierany poprawnie. Używanie curl bezpośrednio z wiersza poleceń (przy użyciu opcji -d) lub z PHP (przy użyciu CURLOPT_POSTFIELDS) działa.Guzzle nieprzesyłania ciała POST PSR-7 poprawnie

zacznę z PSR-7 życzenie:

$request = GuzzleHttp\Psr7\Request('POST', $url); 

dodać nagłówek uwierzytelniania, który uwierzytelnia przeciwko API poprawnie:

$request = $request->withHeader('Authorization', 'Bearer ' . $accessToken); 

Potem dodać ciało żądanie:

// The parameter for the API function 
$body = \GuzzleHttp\Psr7\stream_for('args=dot'); 
$request = $request->withBody($body); 

Mogę wysłać wiadomość do interfejsu API:

$client = new \GuzzleHttp\Client(); 
$response = $client->send($request, ['timeout' => 2]); 

Odpowiedź, którą otrzymuję, oznacza, że ​​parametr "args" po prostu nie był widziany przez API. Próbowałem przeniesienie tokenu uwierzytelniania do args:

'args=dot&access_token=123456789' 

to powinno działać, a robi pracę z dyni z linii poleceń (-d access_token=123456789), ale API nie widzi tego parametru również podczas wysyłania CIA zwijania (6.x) jak wyżej.

widzę komunikat ma zawierać ciała:

var_dump((string)$request->getBody()); 
// string(8) "args=dot" 
// The "=" is NOT URL-encoded in any way. 

Więc co może być nie tak tutaj? Czy parametry nie są wysyłane, czy są wysyłane w niewłaściwym formacie (może "=" jest kodowane?), Czy może użyty jest niewłaściwy typ zawartości? Trudno zobaczyć, co jest wysyłane "na drucie" podczas używania Guzzle, ponieważ wiadomość HTTP jest sformatowana i wysłana na wiele warstw.

Edit: Wywoływanie local test script zamiast zdalnego API, otrzymuję ten surowy szczegół wiadomość:

POST 
CONNECTION: close 
CONTENT-LENGTH: 62 
HOST: acadweb.co.uk 
USER-AGENT: GuzzleHttp/6.1.1 curl/7.19.7 PHP/5.5.9 

args=dot&access_token=5e09d638965288937dfa0ca36366c9f8a44d4f3e 

więc wygląda jak ciało jest wysyłane, więc myślę, że coś jeszcze brakuje do powiedz zdalnemu API, jak interpretować ten obiekt.

Edit: curl wiersza polecenia, które zadziała, wysłanego do tego samego skryptu testowego, daje mi dwa dodatkowe pola w zgłoszeniu:

CONTENT-TYPE: application/x-www-form-urlencoded 
ACCEPT: */* 

Idę do odgadnięcia to na treści typ nagłówka, którego brakuje w żądaniu Guzzle, które jest źródłem problemu. Czy to jest błąd Guzzle? Czy nie powinien zawsze wysyłać treści typu, na podstawie przyjętych założeń, które są listed in the documentation?

Odpowiedz

6

Urządzenie GuzzleHttp\Client zapewnia niezbędne owijanie.

$response = $client->post(
    $uri, 
    [ 
     'auth' => [null, 'Bearer ' . $token], 
     'form_params' => $parameters, 
]); 

Dokumentacja dostępna Guzzle Request Options

Edit: Jednak, jeśli wnioski są wykorzystywane w GuzzleHttp \ Pool Następnie można po prostu wszystko do następującego:

$request = new GuzzleHttp\Psr7\Request(
    'POST', 
    $uri, 
    [ 
     'Authorization' => 'Bearer ' . $token, 
     'Content-Type' => 'application/x-www-form-urlencoded' 

    ], 
    http_build_query($form_params, null, '&') 
); 
+0

więc klient chlać * wstawi poprawne nagłówki 'Content-Type', pod warunkiem, że podasz mu surowe dane we właściwy sposób (domyślam się, że" trigger_params "jest tutaj wyzwalaczem). Guzzle * nie * doda żadnych nagłówków bez podania ich bezpośrednio podczas konstruowania wiadomości żądania PSR-7. Moim celem było skonstruowanie wiadomości PSR-7, która mogłaby zostać przesłana za pośrednictwem dowolnego klienta HTTP obsługującego wiadomości PSR-7, zarówno pod względem czystości, jak i po prostu zauważenia, że ​​można to zrobić w możliwie jak przenośny sposób, więc używając tylko PSR -7 metody na pakiecie pomocnika Guzzle/PSR-7. – Jason

+0

Prawdopodobnie w cytatach powinien znajdować się spacja po wyrazie "Nośnik". – Jason

+0

Prawidłowo, klient automatycznie wstawi odpowiedni nagłówek typu treści i nagłówek uwierzytelniania, gdy używane będą opcje żądania "auth" i "form_params". Jest to coś, o czym należy pamiętać podczas ręcznego budowania żądań użycia z innymi pakietami zgodnymi z PSR7. –

9

Nagłówek Content-Type. Zwykle Guzzle będzie trzymał twoją dłoń i wstawi nagłówki, które uzna za konieczne, i zgadywa na Content-Type na podstawie tego, co mu dałeś, i podałeś, jak to zrobiłeś.

Z wiadomościami PSR-7 Guzzle'a, żadne z tych trzymań się nie skończyły. Ściśle pozostawia wszystkie nagłówki, którymi możesz się posługiwać.Więc podczas dodawania parametrów posta PSR-7 Request, należy jawnie ustawić Content-Type:

$params = ['Foo' => 'Bar']; 
$body = new \GuzzleHttp\Psr7\stream_for(http_build_query($params)); 
$request = $request->withBody($body); 
$request = $request->withHeader('Content-Type', 'application/x-www-form-urlencoded'); 

zdolność przechodzenia w params jako tablicę i zostawić chlać wypracować resztę, nie zastosuj do implementacji Guzzle PSR-7. Jest trochę niezgrabny, ponieważ musisz serializować parametry POST w łańcuchu zapytań HTTP, a następnie wstawić go do strumienia, ale już go masz. Może istnieć łatwiejszy sposób na obsłużenie tego (np. Klasa opakowania, której nie znam), a poczekam i zobaczę, czy pojawią się przed zaakceptowaniem tej odpowiedzi.

Należy pamiętać również, że jeśli konstruowania wiadomość multipart/form-data żądania, trzeba dodać łańcuch ograniczający do Content-Type:

$request = $request->withHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary); 

Gdzie $boundary może być coś podobnego uniq() i jest stosowany w budownictwie wieloczęściowy ciała .