2015-01-20 12 views
7

Sto tentando di testare l'API REST di Laravel 4 utilizzando Codeception, ma quando provo a inviare l'intestazione di autorizzazione (utilizzando la funzione $ I-> amBearerAuthenticated() del REST modulo) non sta arrivando fino all'eventuale richiesta.L'intestazione dell'autorizzazione non riesce a superare il test API Codeception

Da quello che posso vedere, il modulo Symfony2 BrowserKit modifica intestazioni aggiunte nel formato HTTP_XXX_XXX, in modo che il colpo di testa di essere inviato sembra essere HTTP_AUTHORIZATION - quando ho uscita le intestazioni ricevuti nella mia applicazione, tuttavia, né autorizzazione né HTTP_AUTHORIZATION sono presente.

Se aiuta, ecco la mia prova Codeception:

public function loginAndHitProtectedPage(ApiTester $I) 
{ 
    $I->wantTo('login and successfully get to a protected page'); 
    $I->sendPOST('/auth/login', ['username' => 'user1', 'password' => 'pass']); 
    $I->seeResponseIsJson(); 
    $token = $I->grabDataFromJsonResponse('token'); 
    $I->amBearerAuthenticated($token); 
    $I->sendGET('/runs'); 
    $I->seeResponseCodeIs(200); 
    $I->seeResponseIsJson(); 
    $I->dontSeeResponseContains('error'); 
} 

intestazioni inviate in base al BrowserKit (uscita $this->client->getInternalRequest()->getServer() nel modulo REST):

HTTP_HOST : localhost 
HTTP_USER_AGENT : Symfony2 BrowserKit 
HTTP_AUTHORIZATION : Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3RcL2F1dGhcL2xvZ2luIiwic3ViIjoxLCJpYXQiOjE0MjE3ODY0NDEsImV4cCI6MTQyMTg3Mjg0MX0.XxxxZMe8gwF9GS8CdKsh5coNQer1c6G6prK05QJEmDQ  
HTTP_REFERER : http://localhost/auth/login 
HTTPS : false 

intestazioni ricevuto secondo PHP:

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 
Referer:   http://localhost/auth/login 
User-Agent:  Symfony2 BrowserKit 

Il token è stato ricevuto correttamente, ma la mia API (correttamente) restituisce un 401 nella richiesta GET perché non riceve il token.

Qualsiasi aiuto sarebbe molto apprezzato!

+0

ho avuto PhpStorm debug a lavorare per i miei test e ho fatto qualche progresso al fine di identificare questo problema, anche se io sono ancora un po 'bloccato.Sembra che il modulo JWTAuth che sto usando per Autorizzazione sia parte del problema - perché sto facendo due chiamate REST nello stesso test, il modulo JWTAuth sembra essere inizializzato solo per il primo e come parte dell'inizializzazione la richiesta è archiviata. Quindi, quando viene effettuata la seconda chiamata, vengono utilizzate le intestazioni della prima richiesta e quindi l'intestazione Autorizzazione non è presente. Se ho hardcode il token e faccio solo il secondo GET, funziona. Continuando ... –

risposta

2

Dopo aver scavato nelle viscere di Laravel e Codeception, ho scoperto che il problema era che stavo usando il modulo Laravel4 nello stesso momento del modulo REST. Non mi ero reso conto che l'utilizzo di Laravel4 per le richieste HTTP in realtà simula semplicemente la richiesta alla route all'interno della stessa sessione, e quindi il mio oggetto JWTAuth è stato risolto solo dal contenitore IOC alla prima chiamata REST in un particolare test. Ciò significava che quando si effettuavano chiamate successive, la richiesta (comprese le intestazioni) della prima chiamata veniva mantenuta e quindi l'intestazione di autorizzazione (che a quel punto veniva trasmessa correttamente con l'oggetto Richiesta) non veniva visualizzata.

Stavo solo usando il modulo Laravel4 per impostare il mio ambiente su 'testing' e per assicurarmi che i miei filtri funzionassero in quell'ambiente, quindi ora dovrò solo capire un modo diverso di impostarlo senza doverlo modifica il mio bootstrap/start.php ogni volta che voglio eseguire i miei test.

4

Utilizzo i moduli Laravel 5 (non diff diff da L4) e REST. Questo è il modo in cui lo sto facendo in questo momento:

protected $token; 
public function _before(ApiTester $I) 
{ 
    $user = TestDummy(...); 
    $I->sendPOST('/v1/auth/login', [ 
     'email' => $user->email, 
     'password' => $user->password 
    ]); 
    $this->token = $I->grabDataFromResponseByJsonPath('$.token'); 
} 

Poi, nel mio test:

// Do stuff ... 
$I->amBearerAuthenticated($this->token[0]); 
// Do more stuff ... 

Sono sicuro che ci sono modi migliori per fare questo, ma fino a quando ho trovato uno migliore questo sta funzionando.

+0

quindi stai chiamando '$ I-> amBearerAuthenticated ($ this-> token [0]);' in tutte le funzioni? C'è comunque che possiamo farlo una volta in classe e utilizzarlo? –

+0

Puoi estrarlo su un trair o creare una classe base, quindi un'altra estensione che è –

4

C'è una soluzione alternativa. L'utilizzo di $I->amHttpAuthenticated("test", "test") rende permanente l'intestazione Authorization:. Non sono sicuro se questo è un bug o una funzionalità. Costruire invece l'intestazione Authorization: Basic manualmente in modo da poterla eliminare prima di impostare l'intestazione Authorization: Bearer.

$I = new ApiTester($scenario); 
$I->wantTo("fetch token and use it as bearer"); 

/* This does not work. */ 
/* $I->amHttpAuthenticated("test", "test"); */ 

/* Instead use this. */ 
$I->setHeader("Authorization", "Basic dGVzdDp0ZXN0"); 

$I->haveHttpHeader("Content-Type", "application/json");  
$I->sendPOST("token", ["read", "write"]); 
$I->seeResponseCodeIs(201); 
$I->seeResponseIsJson(); 
$I->seeResponseContainsJson(["status" => "ok"]); 

$token = $I->grabDataFromJsonResponse("token"); 

/* Delete the basic auth header before adding bearer. */ 
$I->deleteHeader("Authorization"); 
$I->amBearerAuthenticated($token); 
+0

Non penso che ci sia il metodo 'deleteHeader'. –

+0

ma questo funziona anche, invece di usare 'amHttpAuthenticated' basta usare' haveHttpHeader' due volte. –

+0

Accesso tramite '$ I-> haveHttpHeader (" Autorizzazione "," Token $ di base ");' sembra funzionare, l'intestazione viene realmente inviata. – Surt