Hola!, en esta oportunidad les mostraré como agregar excepciones de IP en modo mantenimiento de 2 tipos en Laravel 5.2, las cuales, son bastante necesarias previo a pasar a producción alguna nueva aplicación o bien para realizar modificaciones en el sistema, siempre había utilizado la excepciones por IP, pero hoy me tocó el caso en que un externo (Mailgun para la verificación de empresa) quería ver una sección de la aplicación (términos y condiciones, políticas de privacidad y checkbox en el registro de usuarios) por lo que no tenía por donde saber su IP y como la aplicación aun no está lista para producción, no podía quitar el modo mantenimiento asi que debía permitir el acceso a ciertas rutas independiente de la IP, así pues vamos a ello!

El modo de mantenimiento de Laravel ya trae un middleware por defecto si revisamos el archivo Kernel.php ubicado en “app/Http”

veremos lo sgte:

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];

Este middleware por defecto no nos brinda excepciones así que lo que haremos será crear un nuevo middleware que reemplazará al por defecto.

Crearemos un nuevo archivo llamado CheckForMaintenanceMode dentro de “app/Http/Middleware/" y dentro de este archivo pegaremos lo siguiente:

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Response;
 
class CheckForMaintenanceMode
{
 
    /**
    * The application implementation.
    *
    * @var \Illuminate\Contracts\Foundation\Application
    */
    protected $app;
 
    /**
    * Create a new middleware instance.
    *
    * @param \Illuminate\Contracts\Foundation\Application $app
    * @return void
    */
    public function __construct(Application $app)
    {
        $this->app = $app;
    }
 
 
    /**
    * Handle an incoming request.
    *
    * @param \Illuminate\Http\Request $request
    * @param \Closure $next
    * @return mixed
    */
    public function handle($request, Closure $next)
    {
 
        if ($this->app->isDownForMaintenance()))
        {
            //Reviso si esta en la exceltion
            foreach ($this->except as $except) {
                if ($except !== '/') {
                    $except = trim($except, '/');
                }
 
            }
            return response()->view(‘errors.503);
        }
 
        return $next($request);
    }
}

Como ven es muy parecido al originar el cual pueden encontrar en:

vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php

Ahora agregaremos primero que nada la excepción por ip única o múltiples

agregaremos a nuestra clase CheckForMaintenanceMode la variable

protected $ips =
[
    '255.255.255.255',
    '244.244.244.244'
];

y el condicional

if ($this->app->isDownForMaintenance()))

le agregaremos la condición

!in_array($request->getClientIp(), $this->ips)

quedando el condicional completo así:

if ($this->app->isDownForMaintenance() && !in_array($request->getClientIp(), $this->ips))

Ahora agregaremos la otra excepción por rutas, para ello agregamos otra variable a nuestra clase CheckForMaintenanceMode

protected $except =
[
    'info/politicas-de-privacidad',
    'info/terminos-y-condiciones'
];

y dentro del condicional agregaremos lo siguiente:

//Reviso si esta en la excepcion
foreach ($this->except as $except) {
    if ($except !== '/') {
        $except = trim($except, '/');
    }
 
    if ($request->is($except)) {
        return $next($request);
    }
 
}
return response()->view('errors.503');

Si se fijan, recorro el array $except (variable), si no es / , quito con trim los / y posteriormente consultamos si es la ruta en que estamos actualmente, si es la ruta, continuamos, de lo contrario lanzamos un 503 por que no es una excepción, finalmente en nuestro archivo Kernel.php ubicado en:

“app/Http”

reemplazamos el middleware a utilizar

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];

por el nuevo:

protected $middleware = [
     \App\Http\Middleware\CheckForMaintenanceMode::class,
];

eso es todo, les dejo el código completo de nuestro nuevo middleware CheckForMaintenanceMode, espero a más de alguien le sirva !

PD: Disculpen si fui muy lento y específico, la idea es que sirva tambien para aquellos que recién comiencen en Laravel

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Response;
 
class CheckForMaintenanceMode
{
 
    /**
    * The application implementation.
    *
    * @var \Illuminate\Contracts\Foundation\Application
    */
    protected $app;
 
    /**
    * Create a new middleware instance.
    *
    * @param \Illuminate\Contracts\Foundation\Application $app
    * @return void
    */
    public function __construct(Application $app)
    {
        $this->app = $app;
    }
 
    /**
    *
    * Routes for exception
    *
    */
    protected $except =
    [
        'info/politicas-de-privacidad',
        'info/terminos-y-condiciones'
    ];
 
    /**
    *
    * IPS for exception
    *
    */
    protected $ips =
    [
        '255.255.255.255',
        '244.244.244.244'
    ];
 
    /**
    * Handle an incoming request.
    *
    * @param \Illuminate\Http\Request $request
    * @param \Closure $next
    * @return mixed
    */
    public function handle($request, Closure $next)
    {
 
        if ($this->app->isDownForMaintenance() && !in_array($request->getClientIp(), $this->ips))
        {
            //Bucle for routes
            foreach ($this->except as $except) {
                if ($except !== '/') {
                    //Clean url
                    $except = trim($except, '/');
                }
                //If is exception route
                if ($request->is($except)) {
                    return $next($request);
                }
            }
            //Is not exception IP and not exception route launch 503
            return response()->view('errors.503');
        }
 
       return $next($request);
    }
}