Я пытаюсь протестировать мой REST API Laravel 4 с использованием Codeception, но когда я пытаюсь отправить через свой заголовок Authorization (используя функцию $ 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 в любом конкретном тесте. Это означало, что при выполнении последующих вызовов запрос (включая заголовки) от первого вызова сохранялся, и, таким образом, заголовок авторизации (который в тот момент был правильно передан с объектом запроса) не просматривался.
На самом деле я использовал модуль Laravel4 только для того, чтобы установить в своей среде «тестирование» и убедиться, что мои фильтры работали в этой среде, поэтому теперь мне нужно просто найти другой способ установки этого без необходимости изменять мой загрузчик / start.php каждый раз, когда я хочу запустить свои тесты.