Введение

Недавно я сделал pull request, который был объединен с фреймворком Laravel и выпущен в версии v8.55. Он добавил новый метод assertRedirectToSignedRoute(), который вы можете использовать в своих тестах.

Я уже давно использую этот метод в нескольких своих проектах, добавляя его с помощью макросов, но я решил сделать запрос на включение в фреймворк, чтобы попытаться помочь другим разработчикам, которые, вероятно, тоже могли бы его использовать.

Кстати, если вам интересно узнать о макросах, ознакомьтесь с моей статьей Как поменять местами элементы в массиве с помощью макросов Laravel.

Что такое подписанные маршруты?

Прежде чем мы рассмотрим тестирование подписанных URL-адресов, давайте кратко рассмотрим, что они из себя представляют и для чего их можно использовать.

Подписанные URL-адреса — это просто URL-адреса именованных маршрутов в вашем приложении, которые содержат подпись в строке запроса.

Вот пример подписанного URL:

https://my-website.co.uk/protected?signature=41cacd19b33b5d29d46876762e6b0091e236a8c2ab59a656df88a31b500471e1

Как видите, URL-адрес содержит параметр signature.

Теперь, если бы мы попытались пойти по этому пути, мы могли бы использовать промежуточное ПО signed, чтобы убедиться, что URL-адрес не был изменен с момента его создания. Это может быть очень полезно, когда мы хотим создать маршрут, который должен быть общедоступным, но нуждается в некоторой защите. Если URL-адрес каким-либо образом изменился, когда кто-то перейдет к нему, он получит ответ об ошибке 403.

Вы можете сгенерировать подписанные URL-адреса, используя такой код:

use Illuminate\Support\Facades\URL;

return URL::signedRoute('protected-route', ['user' => 1]);

Если вы подписаны на мою рассылку и у вас орлиный взгляд, вы могли заметить, что я использую подписанные маршруты в электронном письме «Подтвердить подписку». Подписанный маршрут выглядит так:

https://ashallendesign.co.uk/subscribe/confirm?email=example%40example.com&signature=f6def8b181b2ff43629994bda724f6ada19b3677bbaf09bc656ecde7ba1144c3

Когда кто-то переходит по этому маршруту, это подтверждает, что он хочет подписаться на информационный бюллетень. Подписывая этот URL-адрес, я могу быть уверен, что он не был подделан и что кто-то не пытается залить мою рассылку и подписать множество случайных адресов электронной почты.

Что такое временные подписанные URL-адреса?

Обсужденные выше подписанные URL-адреса не имеют срока действия и, как правило, должны быть доступны в течение неопределенного времени. Однако могут быть случаи, когда вы хотите создать подписанный URL-адрес, к которому можно получить доступ в течение определенного периода времени. Они работают так же, как общие подписанные URL-адреса, но у них также есть время истечения срока действия в строке запроса.

Вот пример временного подписанного URL:

https://my-website.co.uk/protected?expires=1628978674&signature=ec582ea358f0d357edd91fd456a01b0e0b0a3bc62fb460a2853a82c921cd6f54

Как видите, URL содержит параметры signature и expires.

Как и в случае с общими подписанными URL-адресами, если URL-адрес подделан или кто-то пытается перейти к нему после истечения срока действия, будет возвращен ответ об ошибке 403.

Тестирование перенаправлений на подписанные маршруты

Теперь, когда мы кратко рассмотрели подписанные маршруты в Laravel, мы можем посмотреть, как написать тест, подтверждающий, что контроллер перенаправляет на подписанный URL-адрес. Обратите внимание, что приведенные ниже тесты будут очень простыми, и мы будем тестировать только перенаправление; но, надеюсь, они должны помочь объяснить общую концепцию.

Давайте представим, что у нас есть следующий одноразовый контроллер с маршрутом /my-route:

class RandomController extends Controller
{
    public function __invoke(): RedirectResponse
    {
        // Do something...
        
        return redirect()->signedRoute(
            'example.route', ['param' => 'hello']
        );
    }
}

Если бы мы хотели проверить, что контроллер возвращает перенаправление на подписанный маршрут, но не особенно заботился о том, какой URL-адрес, мы могли бы написать такой тест:

/** @test */
public function user_is_redirected_to_signed_route(): void
{
    $this->get('/my-route')
        ->assertRedirectToSignedRoute();
}

В качестве альтернативы, если мы хотим быть более строгими и проверять, что перенаправление было на определенный маршрут, мы могли бы написать следующий тест:

/** @test */
public function user_is_redirected_to_signed_route(): void
{
    $this->get('/my-route')
        ->assertRedirectToSignedRoute(
            route('example.route', ['param' => 'hello']
        )
    );
}

Метод assertRedirectToSignedRoute() также работает с временными подписанными маршрутами. Таким образом, если бы наш контроллер возвращал redirect()->temporarySignedRoute(), а не redirect()->signedRoute(), приведенные выше тесты все равно работали бы.

Вывод

Хотя этот пост немного короче обычного, надеюсь, он должен был дать вам краткий обзор подписанных URL-адресов в Laravel и того, как правильно писать тесты, которые ваши контроллеры перенаправляют на них.

Если этот пост помог вам, я хотел бы услышать об этом. Точно так же, если у вас есть какие-либо отзывы, чтобы улучшить этот пост, я тоже хотел бы их услышать.

Если вы хотите получать обновления каждый раз, когда я публикую новый пост, не стесняйтесь подписаться на мою рассылку.

Продолжайте создавать потрясающие вещи! 🚀

Первоначально опубликовано на https://ashallendesign.co.uk.