Kostumisasi File Route Laravel - CRUDPRO

Kostumisasi File Route Laravel

Suatu pagi saya terbangun dengan pemberitahuan Slack. Itu sama sekali bukan pertanda baik. Semalam, instance Redis saya benar-benar penuh. Redis digunakan untuk dua tujuan:

  1. Penyimpanan session
  2. Cache beberapa bit data, tetapi tidak ada yang praktis

Kami menggunakan TablePlus untuk melihat apa yang dapat dilakukan Redis. Laravel menggunakan hash acak sebagai bagian dari kunci cache, dan muatannya dikodekan/dienkripsi, jadi agak sulit untuk mengetahui apa yang terjadi.

Namun, saya menemukan bahwa saya memiliki dua database Redis (db0 dan db1). Saya memeriksa file config/databases.php dan menemukan bahwa dua database yang sesuai sebenarnya ditentukan untuk Redis.

# File config/databases.php

return [
    // Things ommitted here...
    /*
    |--------------------------------------------------------------------------
    | Redis Databases
    |--------------------------------------------------------------------------
    |
    | Redis is an open source, fast, and advanced key-value store that also
    | provides a richer body of commands than a typical key-value system
    | such as APC or Memcached. Laravel makes it easy to dig right in.
    |
    */
    'redis' => [
        'client' => env('REDIS_CLIENT', 'phpredis'),
        'options' => [
            'cluster' => env('REDIS_CLUSTER', 'redis'),
            'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
        ],

        'default' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => env('REDIS_DB', '0'),

        ],

        'cache' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => env('REDIS_CACHE_DB', '1'),
        ],
    ],
];

Koneksi default menggunakan db0 dan koneksi cache menggunakan db1. Sesi disimpan di db0, tetapi apa pun yang di-cache dalam kode menggunakan db1. Basis data default db0 memiliki lebih banyak kunci daripada basis data cache.

Aplikasi membuat terlalu banyak session.

Bagaimana membuat session?

Semua permintaan web (untuk routes yang ditentukan dalam routes/web.php) membuat session (atau menggunakan session yang ada). Aplikasi web mengembalikan cookie saat session dibuat. Browser web Anda menyimpan cookie ini dan mengirimkannya kembali saat Anda membuat permintaan web tambahan. Ini memungkinkan aplikasi web Anda mengetahui session mana yang valid untuk pengguna tertentu.

Jika browser tidak mengembalikan cookie pada setiap permintaan, pengguna tidak akan dapat tetap login.

Session berbasis API tidak bekerja dengan cara ini. Setiap sesi dibuat dan dihancurkan di setiap permintaan web. Cookie tidak relevan. Sebagai gantinya, klien harus mengirim kredensial (biasanya beberapa token) pada setiap permintaan web.

Apa yang meledakkan Redis?

Jadi apa yang menyebabkan instance Redis meledak di session?

Aset yang dihasilkan secara dinamis yang disematkan orang lain di situs web Anda. Ada dua kasus ini.

  1. Aplikasi kami menghasilkan file .js yang disematkan orang lain di situs web mereka
  2. Aplikasi kami juga menghasilkan gambar .svg untuk tujuan yang sama
routes ini didefinisikan dalam file routes/web.php:.
Route::get('/embed.js');
Route::get('/{project}/share.js');

Apakah kamu punya masalah? Pelanggan menempatkan ini di situs web mereka. Setiap kali seseorang mengunjungi situs web saya, permintaan HTTP dibuat ke aplikasi tertanam atau SVG, yang membuat session. Ini berarti bahwa lalu lintas web Anda juga membuat sesi di aplikasi web Anda.

Cara mengurangi pembuatan session

Cara mengatasinya adalah tidak membuat session untuk routes tertentu. Mudah untuk mengatakannya, tetapi bagaimana Anda bisa mencapainya?

Ternyata pembuatan dan session cookie dilakukan di middleware Laravel. Ini bagus karena mengontrol middleware mana yang diterapkan ke setiap routes.

Saya suka membuat file routes lain dengan tumpukan middleware berbeda untuk mencegah beberapa routes membuat session/mengembalikan cookie. Cara mengatasinya adalah tidak membuat session untuk routes tertentu. Mudah untuk mengatakannya, tetapi bagaimana Anda bisa mencapainya?

ernyata pembuatan dan sesi cookie dilakukan di middleware Laravel. Ini bagus karena mengontrol middleware mana yang diterapkan ke setiap routes.

Saya suka membuat file root lain dengan tumpukan middleware berbeda untuk mencegah beberapa routes membuat session/mengembalikan cookie.

Untuk melakukan itu, Anda perlu melakukan beberapa hal:
  1. Buat file routes/static.php baru (namanya sembarang)
  2. Tambahkan tumpukan middleware ke app/Http/Kernel.php
  3. Perbarui app/Providers/RouteServiceProvider.php untuk memuat file routes baru dan menerapkan tumpukan middleware baru
File routes baru sederhana. Buat file baru dan pindahkan definisi routes ke sana:
# File routes/static.php`
# Move these from routes/web.php
Route::get('/embed.js');
Route::get('/{project}/share.js');

Anda kemudian dapat memperbarui file Kernel.php untuk membuat tumpukan middleware baru. Anda dapat menyalin tumpukan middleware web untuk menghapus middleware yang menangani cookie dan session.

# File app/Http/Kernel.php
# Items omitted here

    /**
     * The application's route middleware groups.
     *
     * @var array
     */

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'static' => [
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ], 
    ];
# Items omitted here

Saya telah membuat grup middleware baru bernama static. Mirip dengan middleware API, tetapi tanpa throttle.

Terakhir, Anda perlu mendaftarkan file root baru dan menerapkan grup middleware statis baru. Untuk melakukannya, perbarui RouteServiceProvider.php

.
# File app/Providers/RouteServiceProvider.php
# Items omitted here

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */

    public function boot()
    {
        $this->configureRateLimiting();
        $this->routes(function () {
            Route::prefix('api')
                ->middleware('api')
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));

            Route::middleware('static')
                ->namespace($this->namespace)
                ->group(base_path('routes/static.php'));
        }); 
    }

# Items omitted here

RouteServiveProvider mendaftarkan setiap file routes dan menentukan middleware mereka. Ini adalah bagaimana semua routes/web.php mendapatkan grup middleware web yang ditugaskan padanya.

Ini juga alasan untuk membuat file routes Anda sendiri. Kami ingin menghindari grup middleware web dan dapat menambahkan routes ke file routes baru kapan pun kami membutuhkannya.

The Result

Akibatnya, dua routes "statis" (yang mengembalikan aset yang dihasilkan secara dinamis (file JS dan SVG)) tidak membuat session dan tidak mengembalikan cookie.

Ini memungkinkan Anda memulihkan instans Redis Anda. Session telah kedaluwarsa dan telah dihapus dari Redis. Instance Redis Anda tidak akan terisi lagi karena lalu lintas Anda telah menghentikan session yang dibuat di penyimpanan session.