Laravel Session is created / generated on every request, Redis takes a lot of space on RAM

127 views Asked by At

So I have a Laravel 10 project which is using Sanctum's SPA authentication, which stores sessions to Redis and came to this problem where RAM was suddenly on 100% of usage on server.

When I look in Network tab of Chrome's devtools, I see that session value changes after every request.

I don't call session()->regenerate() anywhere nor manipulating session with any manner.

In this case, I tried locally fixing the file/directory permissions inside storage folder of my app. This showed up like a good idea, because I've seen in Devtools that session value is not changing anymore, it stays the same.

Well, I wanted to be sure so I looked into Redis using redis-cli. I executed FLUSHDB, made few request to laravel app and then executed

KEYS *

which ended up logging out a lot of entries - each per request.

My middleware variable inside app\Http\Kernel.php looks like this:

protected $middleware = [
        StartSession::class,
        TrustProxies::class,
        PreventRequestsDuringMaintenance::class,
        ValidatePostSize::class,
        TrimStrings::class,
        ConvertEmptyStringsToNull::class,
];

TLDR; Laravel generates new session every request even though Devtools show same session cookie value.

1

There are 1 answers

0
jacob_frankovic On

I assumed this could be because of Cross-origin XHR requests. Before they execute normally as we would await, before every one there is preflight (OPTIONS) request happenning.

This request essentialy must not include cookies, and since we are not including session value, the Laravel's StartSession middleware, which is executing on every request, generates new session value and saves it to Redis.

This is the place where all the unknown sessions are generated. So I removed StartSession middleware from $middleware variable and created new one:

<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Session\Middleware\StartSession;
use Symfony\Component\HttpFoundation\Response;

class StartSessionExtended
{
    /**
     * Handle an incoming request.
     *
     * @param  Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->isMethod('OPTIONS')) {
            return $next($request);
        }

        return app(StartSession::class)->handle($request, $next);
    }
}

What this does is it skips executing StartSession middleware when request is of type OPTIONS.