Я пытаюсь проверить свой REST API Laravel 4 с помощью Codeception, но когда я пытаюсь отправить через свой заголовок авторизации (используя функцию $ I-> amBearerAuthenticated () модуля REST), он не доводит до конечного запроса.
Из того, что я вижу, модуль Symfony2 BrowserKit модифицирует любые заголовки, добавленные в формат HTTP_XXX_XXX, поэтому отправляемый заголовок кажется HTTP_AUTHORIZATION – при выводе полученных заголовков в моем приложении, однако, не присутствуют ни авторизация, ни HTTP_AUTHORIZATION.
Если это помогает, вот мой тест 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'); }
Заголовки, отправленные в соответствии с BrowserKit (вывод $this->client->getInternalRequest()->getServer()
в модуле REST):
HTTP_HOST : localhost HTTP_USER_AGENT : Symfony2 BrowserKit HTTP_AUTHORIZATION : Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3RcL2F1dGhcL2xvZ2luIiwic3ViIjoxLCJpYXQiOjE0MjE3ODY0NDEsImV4cCI6MTQyMTg3Mjg0MX0.XxxxZMe8gwF9GS8CdKsh5coNQer1c6G6prK05QJEmDQ HTTP_REFERER : http://localhost/auth/login HTTPS : false
Заголовки, полученные в соответствии с 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
Токен получен правильно, но мой API (правильно) возвращает 401 в запросе GET, потому что он не получает токен.
Любая помощь будет принята с благодарностью!
Я использую Laravel 5 (без больших различий от L4) и модулей REST. Я так делаю это сейчас:
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'); }
Затем в моих тестах:
// Do stuff ... $I->amBearerAuthenticated($this->token[0]); // Do more stuff ...
Я уверен, что есть лучшие способы сделать это, но пока я не найду лучшего, это работает.
Существует обходное решение. Использование $I->amHttpAuthenticated("test", "test")
делает заголовок Authorization:
постоянным. Не уверен, что это ошибка или функция. Вместо этого создайте заголовок Authorization: Basic
вручную, чтобы удалить его перед настройкой заголовка 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);
После некоторого углубления в кишки Laravel и Codeception я обнаружил, что проблема заключалась в том, что я использовал модуль Laravel4 одновременно с модулем REST. Я не понял, что использование Laravel4 для HTTP-запросов фактически просто имитирует запрос маршрута в пределах того же сеанса, и поэтому мой объект JWTAuth был только разрешен из контейнера IOC при первом вызове REST в любом конкретном тесте. Это означало, что при выполнении последующих вызовов запрос (включая заголовки) от первого вызова сохранялся и, следовательно, заголовок авторизации (который в этот момент прошел через объект Request правильно) не просматривался.
Я действительно использовал только модуль Laravel4, чтобы настроить мою среду на «тестирование» и убедиться, что мои фильтры запущены в этой среде, поэтому теперь мне просто нужно выяснить другой способ установить это, не изменяя мою загрузку / start.php каждый раз, когда я хочу запускать свои тесты.