PreventRequestsDuringMaintenance.php
TLDR
The PreventRequestsDuringMaintenance.php file is a middleware class that handles incoming requests during maintenance mode. It checks if the application is in maintenance mode and if so, it handles the request accordingly. It also provides methods for determining if a request has a maintenance mode bypass cookie, redirecting the user with a maintenance mode bypass cookie, and getting the excluded paths that should be accessible even during maintenance mode.
Methods
handle
Handles an incoming request. If the request is in the excluded paths, it allows the request to proceed. If the application is in maintenance mode, it checks for a maintenance mode bypass cookie or a secret path. If the bypass cookie or secret path is present, it allows the request to proceed. Otherwise, it handles the request based on the maintenance mode data, such as redirecting to a specified path or returning a maintenance mode template.
hasValidBypassCookie
Determines if the incoming request has a maintenance mode bypass cookie. It checks if the cookie exists and if it is valid based on the provided secret.
inExceptArray
Determines if the request has a URI that should be accessible in maintenance mode. It checks if the request URL or path matches any of the excluded paths.
bypassResponse
Redirects the user back to the root of the application with a maintenance mode bypass cookie. It creates a bypass cookie with the provided secret and attaches it to the redirect response.
getHeaders
Gets the headers that should be sent with the response. It includes the Retry-After header if specified, and the Refresh header if specified.
getExcludedPaths
Gets the URIs that should be accessible even when maintenance mode is enabled. It returns the array of excluded paths.
<?php
namespace Illuminate\Foundation\Http\Middleware;
use Closure;
use ErrorException;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Http\MaintenanceModeBypassCookie;
use Symfony\Component\HttpKernel\Exception\HttpException;
class PreventRequestsDuringMaintenance
{
/**
* The application implementation.
*
* @var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
/**
* The URIs that should be accessible while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [];
/**
* 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
*
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
* @throws \ErrorException
*/
public function handle($request, Closure $next)
{
if ($this->inExceptArray($request)) {
return $next($request);
}
if ($this->app->maintenanceMode()->active()) {
try {
$data = $this->app->maintenanceMode()->data();
} catch (ErrorException $exception) {
if (! $this->app->maintenanceMode()->active()) {
return $next($request);
}
throw $exception;
}
if (isset($data['secret']) && $request->path() === $data['secret']) {
return $this->bypassResponse($data['secret']);
}
if ($this->hasValidBypassCookie($request, $data)) {
return $next($request);
}
if (isset($data['redirect'])) {
$path = $data['redirect'] === '/'
? $data['redirect']
: trim($data['redirect'], '/');
if ($request->path() !== $path) {
return redirect($path);
}
}
if (isset($data['template'])) {
return response(
$data['template'],
$data['status'] ?? 503,
$this->getHeaders($data)
);
}
throw new HttpException(
$data['status'] ?? 503,
'Service Unavailable',
null,
$this->getHeaders($data)
);
}
return $next($request);
}
/**
* Determine if the incoming request has a maintenance mode bypass cookie.
*
* @param \Illuminate\Http\Request $request
* @param array $data
* @return bool
*/
protected function hasValidBypassCookie($request, array $data)
{
return isset($data['secret']) &&
$request->cookie('laravel_maintenance') &&
MaintenanceModeBypassCookie::isValid(
$request->cookie('laravel_maintenance'),
$data['secret']
);
}
/**
* Determine if the request has a URI that should be accessible in maintenance mode.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function inExceptArray($request)
{
foreach ($this->getExcludedPaths() as $except) {
if ($except !== '/') {
$except = trim($except, '/');
}
if ($request->fullUrlIs($except) || $request->is($except)) {
return true;
}
}
return false;
}
/**
* Redirect the user back to the root of the application with a maintenance mode bypass cookie.
*
* @param string $secret
* @return \Illuminate\Http\RedirectResponse
*/
protected function bypassResponse(string $secret)
{
return redirect('/')->withCookie(
MaintenanceModeBypassCookie::create($secret)
);
}
/**
* Get the headers that should be sent with the response.
*
* @param array $data
* @return array
*/
protected function getHeaders($data)
{
$headers = isset($data['retry']) ? ['Retry-After' => $data['retry']] : [];
if (isset($data['refresh'])) {
$headers['Refresh'] = $data['refresh'];
}
return $headers;
}
/**
* Get the URIs that should be accessible even when maintenance mode is enabled.
*
* @return array
*/
public function getExcludedPaths()
{
return $this->except;
}
}