web-dev-qa-db-fra.com

Comment obtenir le contenu du corps de la requête HTTP dans Laravel?

Je crée une API avec Laravel 5 Et je la teste avec PHPUnit. Je dois tester la compatibilité de la fonctionnalité existante, qui est un POST XML. Pour l'instant, mon premier test ressemble à ceci:

public function testPostMessages()
{
    $response = $this->call('POST', 'xml');

    $this->assertEquals(200, $response->getStatusCode());
}

Ceci passe très bien. Suivant sur ma liste envoie réellement les données XML avec le POST. Donc pour mon deuxième test, j'ai:

public function testPostMessagesContent()
{
    $response = $this->call('POST', 'xml');

    $this->assertTrue(is_valid_xml($response->getContent()));
}

Ce test échoue. Cependant, je n'envoie pas mes données XML. Comment puis-je envoyer mon XML?
Après cela, je dois ajouter la fonctionnalité pour obtenir le contenu de la demande. Je sais qu'il y a un objet Request avec lequel je peux interagir, mais je ne sais pas exactement quelle méthode utiliser. Comment puis-je obtenir mon code XML à partir de mon contrôleur?


Mise à jour # 1

J'ai pu obtenir des résultats entre-temps. Mon test actuel ressemble à ceci:

public function testPostMessagesContent()
{
    $response = $this->call('POST', 'xml', array('key' => 'value'), array(), array(), array('content' => 'content'));
    $this->assertContains('~', $response->getContent());
}

J'ai seulement le tilde ici parce que je sais qu'il ne correspondra pas pour que je puisse voir toute la réponse. Dans XmlController.php J'ai:

class XmlController extends Controller {
public function index(Request $request)
{
    return $request;
    }
}

Ma sortie de PHPUnit est la suivante:

1) XmlTest::testPostMessagesContent
Failed asserting that 'POST xml HTTP/1.1
Accept:          text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Language: en-us,en;q=0.5
Content-Type:    application/x-www-form-urlencoded
Host:            localhost
User-Agent:      Symfony/2.X
' contains "~".

Où sont mes paramètres et mon contenu? J'ai l'impression de n'utiliser que call() de manière incorrecte.


Mise à jour # 2

J'ai mis à jour mon contrôleur pour qu'il utilise Request:all() comme suit:

class XmlController extends Controller
{
    public function index()
   {
        $content = Request::all();
        return $content;
    }
}

Cela a renvoyé ma paire clé-valeur, mais pas le contenu.

1) XmlTest::testPostMessagesContent
Failed asserting that '{"key":"value"}' contains "~".

Les paires clé-valeur sont bonnes; c'est un progrès. Cependant, ce dont j'ai vraiment besoin, c'est du contenu puisque je recevrai ces données dans la partie contenu de la demande. Si j'utilise Request::getContent(), je récupère une chaîne vide. Voici mon appel dans le test:

$response = $this->call('POST', 'xml', array('key' => 'value'), array(), array(), array('content' => 'content'));

Voici mes résultats de test:

1) XmlTest::testPostMessagesContent
Failed asserting that '' contains "~".

Mise à jour # 3

Je ne parviens pas à obtenir le contenu du corps d'une requête HTTP. Comme XML ne fonctionnait pas, j'ai avancé avec la partie REST de mon API, qui utilise JSON. Voici un de mes tests:

public function testPostMessagesContent()
{
    $response = $this->call('POST', 'messages', ['content' => 'content']);

    $this->assertEquals('saved!', $response->getContent());
}

Ce test est réussi. Si j'utilise curl, je reçois également un appel réussi:

curl -X POST -d "content=my_new_content" "http://localhost:8000/messages"

Cela retourne 'saved!' C'est génial, mais si j'essaie d'utiliser curl dans un script autonome PHP (pour simuler un client), voici ce qui est retourné:

Array ( [url] => http://localhost:8000/messages [content_type] => text/html; charset=UTF-8 [http_code] => 302 [header_size] => 603 [request_size] => 118 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.063977 [namelookup_time] => 0.000738 [connect_time] => 0.000866 [pretransfer_time] => 0.000943 [size_upload] => 12 [size_download] => 328 [speed_download] => 5126 [speed_upload] => 187 [download_content_length] => -1 [upload_content_length] => 12 [starttransfer_time] => 0.057606 [redirect_time] => 0 [certinfo] => Array ( ) [primary_ip] => ::1 [primary_port] => 8000 [local_ip] => ::1 [local_port] => 63248 [redirect_url] => http://localhost:8000 [request_header] => POST /messages HTTP/1.1 Host: localhost:8000 Accept: */* Content-type: text/xml Content-length: 12 ) Redirecting to http://localhost:8000. 

Voici ma commande curl ajoutant les champs POST:

curl_setopt($ch, CURLOPT_POSTFIELDS, 'content=test');

Il me semble que POSTFIELDS est ajouté au corps de la demande. Dans ce cas, j'ai toujours le même problème. Je ne parviens pas à obtenir le contenu du corps de mes en-têtes HTTP. Après avoir commenté ma validation, je reçois:

Array ( [url] => http://localhost:8000/messages [content_type] => text/html; charset=UTF-8 [http_code] => 200 [header_size] => 565 [request_size] => 118 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.070225 [namelookup_time] => 0.000867 [connect_time] => 0.00099 [pretransfer_time] => 0.001141 [size_upload] => 12 [size_download] => 6 [speed_download] => 85 [speed_upload] => 170 [download_content_length] => -1 [upload_content_length] => 12 [starttransfer_time] => 0.065204 [redirect_time] => 0 [certinfo] => Array ( ) [primary_ip] => ::1 [primary_port] => 8000 [local_ip] => ::1 [local_port] => 63257 [redirect_url] => [request_header] => POST /messages HTTP/1.1 Host: localhost:8000 Accept: */* Content-type: text/xml Content-length: 12 ) saved!

J'ai donc mon message 'saved!'. Génial! Mais, dans ma base de données, j'ai maintenant une ligne vide. Pas génial. Il ne voit toujours pas le contenu du corps, juste les en-têtes.


Critères de réponse

Je cherche les réponses à ces questions:

  1. Pourquoi ne puis-je pas obtenir le contenu de corps de ma demande?
  2. Comment puis-je obtenir le contenu de corps de ma demande?
41
beznez

Le contrôleur interne injecte un objet Request. Par conséquent, si vous souhaitez accéder au corps de la demande dans la méthode du contrôleur 'foo', procédez comme suit:

public function foo(Request $request){
    $bodyContent = $request->getContent();
}
87
gandra404

Vous pouvez passer data comme troisième argument de call(). Ou, en fonction de votre API, il est possible que vous souhaitiez utiliser le sixième paramètre.

De la docs :

$this->call($method, $uri, $parameters, $files, $server, $content);
3
Jason McCreary

Je ne pense pas que vous souhaitiez obtenir les données de votre demande , je pense que vous souhaitez obtenir les données de votre réponse . Les deux sont différents. Aussi, vous devriez construire votre réponse correctement dans votre contrôleur.

En regardant la classe dans la deuxième édition, je lui donnerais l'aspect suivant:

class XmlController extends Controller
{
    public function index()
    {
        $content = Request::all();
        return Response::json($content);
    }
}

Une fois que vous en êtes arrivé là, vous devriez vérifier le contenu de votre réponse dans votre scénario de test (utilisez print_r si nécessaire), vous devriez voir les données à l'intérieur.

Plus d'informations sur les réponses Laravel ici:

http://laravel.com/docs/5.0/responses

1
delatbabel

Pour ceux qui obtiennent encore une réponse vide avec $request->getContent(), vous pouvez utiliser:

$request->all()

par exemple:

public function foo(Request $request){
   $bodyContent = $request->all();
}
0
user3785966