Laravel y el ciclo de vida de las solicitudes


Lección 8 / 8

Laravel y el ciclo de vida de las solicitudes

Laravel Guía Laravel

El routing es uno de los aspectos esenciales de una aplicación web y es, obviamente, la base de un proyecto Laravel. Routing significa el mecanismo mediante el cual las solicitudes HTTP se enrutan (route) a la parte del código que las administrará y es la base del ciclo de vida de una solicitud HTTP administrada por una aplicación Laravel.

En Laravel, el routing se configura y gestiona mediante el registro de rutas en los archivos route/web.php y route/api.php, que gestionan respectivamente las solicitudes relacionadas con la interfaz web de la aplicación y las solicitudes de tipo API RESTful.

Conocer los mecanismos de trabajo del routing en Laravel es importante para comprender mejor el propósito, el comportamiento esperado y las interacciones entre los diversos componentes que componen una aplicación web Laravel, logrando así superar la sensación inicial de "sucede como por arte de magia". 

Veamos entonces, en detalle, el ciclo de vida de solicitud HTTP en una aplicación Laravel. Es decir, que sucede "en el server" cuando llega una solicitud HTTP de un client.

Server web y aplicación web Laravel

En el mundo del web es importante distinguir entre server web y aplicación web.

El servidor web es una aplicación por derecho propio que básicamente se encarga de recibir solicitudes HTTP de los clientes y decidir qué archivo está asociado con el recurso solicitado.

Hagamos un pequeño ejemplo: tenemos una directory de nombre /opt/website/ que tiene dentro los archivos index.html y style.css. Si iniciamos el server web configurado de la siguiente manera:

root: /opt/website/

req: / -> index.html
req: /* -> * 

Estamos diciendo que:

  • si el client manda una solicitud HTTP para el recurso /, entonces el server sustituye el archivo /opt/website/index.html
  • para cualquier otra solicitud el server devuelve el archivo solicitado si está presente en /opt/website/website/

Si el archivo solicitado no existe, el web server ofrecerá una respuesta HTTP con status code 404 Not Found.

Un server web opera a nivel de solicitud y respuesta HTTP, limitándose a clasificar las solicitudes hacia los archivos incluidos en un directory determinado.

Un sitio web estático, es decir, compuesto solo de páginas HTML que no cambian en función de la solicitud realizada o que no requieren la presencia de formularios para enviar datos, puede estar disponible en la web cargando los archivos en una máquina que ejecuta solo un servidor web, gestionando adecuadamente los enlaces y directorios en disco.

Una aplicación Laravel necesita un servidor web para recibir solicitudes HTTP y devolver respuestas, pero el servidor web básicamente está configurado de la siguiente manera:

root: /opt/app-laravel/public/

req: /* -> run(php index.php)

Es decir: por cada solicitud HTTP recibida ejecuta el script public/index.php del proyecto Laravel.

El archivo index.php en Laravel

El archivo public/index.php de un proyecto Laravel es, por lo tanto, el script PHP que se invoca cada vez que llega una solicitud a nuestro servidor.

No hay mucho código en este archivo, solo lo que se necesita para cargar el resto del framework de Laravel. De hecho, aparte del necesario requerimiento del autoload, encontramos solo

$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Kernel::class);

$response = $kernel->handle(
    $request = Request::capture()
)->send();

$kernel->terminate($request, $response);

Que podemos interpretar de la siguiente manera:

  • recupera una instancia de la aplicación Laravel $app
  • carga el $kernel oportuno (en base al tipo de solicitud que llega será un kernel de tipo HTTP o consol)
  • gestiona la $request que llega al kernel y envía una $response

Este mini ciclo se repite con cada solicitud que llega al servidor, pasando la solicitud de una capa a otra hasta llegar al código real que manejará y devolverá el contenido de la respuesta.

La selección del middleware

Las solicitudes de tipo HTTP continúan su viaje siguiendo un camino aparentemente tortuoso, nuevamente ligado al tipo de solicitud recibida.

Las versiones más recientes de Laravel (en esta guía estamos usando la versión 9.x actualmente disponible) ofrecen, de hecho, la posibilidad de distinguir dos "grupos" diferentes de rutas, definidas como middleware.

Cuando se inicializa la aplicación Laravel, se carga un servicio interno para el manejo de rutas. Este servicio corresponde al contenido del archivo app/Providers/RouteServiceProvider.php, es decir, la clase App\Providers\RouteServiceProvider. La versión predeterminada de este servicio incluye lo siguiente:

$this->routes(function () {
    Route::middleware('api')
        ->prefix('api')
        ->group(base_path('routes/api.php'))
    Route::middleware('web')
        ->group(base_path('routes/web.php'));
});

es decir, todas las solicitudes de recursos cuya ruta comienza con api pertenecen al middleware api y se clasificarán en el archivo route/api.php para su clasificación posterior. Cualquier otra solicitud se reenvía al middleware web y se reenviará mediante el archivo route/web.php.
 

Solicitud

Middleware

GET /api/orders/

api

POST /page/form

web

GET /docs/api/

web

GET /blog/2022/12/23/post.html

web

DELETE /api/orders/23455

api

DELETE /order/23455

web

NOTA: lo que se ha descrito hasta ahora es la configuración presente en una aplicación Laravel recién creada a partir del template de default. Puedes cambiar estas configuraciones según tus necesidades, por ejemplo, eliminar completamente el middleware API en caso de que no necesitse las API RESTful, pero quieras usar Laravel para compilar solo en el sitio web.

La selección de las rutas registradas

Una vez que se ha identificado el middleware, nuestra solicitud HTTP continúa su viaje hasta su destino final.

La responsabilidad ahora recae en los archivos route/web.php y route/api.php que, aunque de forma ligeramente diferente dada la diferente naturaleza del tipo de solicitud que manejan, contienen las rutas reales registradas.

// routes/web.php

Route::get('/', function () {
    return view('welcome');
});

Route::get('/hello', function () {     
    return "Hello Laravel"; 
});

// routes/api.php

Route::middleware('auth:sanctum')->get('/orders', function (Request $request) {
    return $request->orders();
});

Por lo tanto, si hay una ruta registrada para la ruta de la solicitud que se está manejando, entonces se ejecutará la función correspondiente y se devolverá el retorno de la función misma.

Por ejemplo, limitándonos solo a solicitudes en el middleware web:

  • en caso de que llegase una solicitud GET /hello, entonces será devuelto el texto “Hello Laravel” que se convertirá en el body de la respuesta HTTP con status 200 OK
  • para la solicitud GET / se invocará una función dedicada que hace el rendering de una view, es decir busca el archivo template asociato, lo elabora y devuelve el resultado como texto (muy probablemente HTML) que, también aquí, se convertirá en el body de una respuesta HTTP con status 200 OK
  • cualquier otra solicitud, tanto por método como por recurso solicitado, al no tener registrada una ruta correspondiente, no se puede satisfacer y Laravel se encargará de preparar y devolver la respuesta con status 404 Not Found

El archivo routes/web.php es, por tanto, el archivo a consultar para saber qué rutas están actualmente registradas y el punto de partida a la hora de definir una nueva ruta.

NOTA: Además de lo descrito hasta ahora, Laravel también permite otra forma de definir una ruta, a través de un controller. Por ahora, considéralo como una forma de agrupar rutas que forman parte del mismo agregado en una sola clase.

Artisan y las rutas en Laravel

Para obtener una lista completa de las rutas registradas de la aplicación Laravel, también es posible usar el oportuno comando Artisan:

php artisan route:list

La opción -v muestra también los middleware asociados, mientras la opción --path permite mostrar solo las rutas que contienen una determinada cadena en el URI:

$ php artisan route:list --path=user -v

GET|HEAD       api/user
                ⇂ api
                ⇂ App\Http\Middleware\Authenticate:sanctum
GET|HEAD       user
                ⇂ web

Si habéis agregado una ruta y no aparece cuando se ejecuta este comando, probablemente no se agregó correctamente. Laravel, por lo tanto, no podrá manejar solicitudes para esa ruta.

Conclusiones

  • el routing es la manera con la que una solicitud HTTP de una determinada URI se envía a un archivo o a una porción de código que se encarga de crear el contenido de la respuesta
  • en Laravel es suficiente con registrar una ruta para gestionar las solicitudes
  • una ruta registrada se identifica por el método HTTP y por el path del recurso 
  • una ruta registrada indica también que hacer para construir la respuesta para mandar al cliente
  • todas las rutas registradas están presentes en el archivo routes/web.php
  • Laravel esconde al desarrollador web gran parte de la gestión de bajo nivel de los mecanismos de routing, pero se puede siempre personalizar la propia app yendo a modificar el contenido de archivos específicos y clases

Siguiente

9
Guía Laravel en español 1 ¿Qué es HTTP? 2 ¿Qué son las solicitudes HTTP? 3 ¿Qué son las respuestas HTTP? 4 Administrador de dependencias Composer 5 Laravel, el framework para los artesanos de la web 6 El ecosistema Laravel 7 Estructura de un proyecto Laravel 8 Laravel y el ciclo de vida de las solicitudes

© 2022 Aulab. Todos los derechos reservados • P.IVA: IT07647440721 • Política de privacidad