/
/
Mastering NextJS 13 Middleware
Posted 6 months ago • 341 Dibaca

Mastering NextJS 13 Middleware

Apa itu Middleware

Middleware memungkinkan Anda menjalankan kode sebelum permintaan diselesaikan. Kemudian, berdasarkan permintaan yang masuk, Anda dapat mengubah respons dengan menulis ulang, mengalihkan, mengubah header permintaan atau respons, atau merespons secara langsung.

Di NextJs Middleware, step pertama adalah whitelist path yang ingin di lakukan pengecekan di middleware, jika tidak ada di whitelist maka akan skip middleware dan lanjut ke handler masing-masing.

Use Case

Untuk sample project disini kami menggunakan, NextJS 13, project ada di link berikut: mastering-nextjs-middleware/__free-practice at main · maucoding-collections/mastering-nextjs-middleware (github.com)

Di project tersebut, kami ada 3 halaman yang sudah tersedia

  • /login
  • /dashboard/users
  • /dashboard/

3 Halaman tersebut memiliki tampilan sebagai berikut

Tampilan halaman /

Screenshot 2023-10-22 at 11.04.22.png

Tampilan halaman /dashboard/user

Tampilan halaman /dashboard/news

Goalnya adalah sebagai berikut, untuk bisa akses semua path /dashboard/* , wajib login terlebih dahulu di halaman login. jika belum login maka redirect ke halaman login. Nah tugas yang mengecek apakah sudah login dan lanjut redirect ke login atau melanjutkan ke halaman target adalah “middleware”.

Start Code

Membuat Dummy Login

Untuk step login ini ada 2 tugas, memastikan username dan password match, jika match simpan session di cookies. Dari cookies inilah middleware bisa mengecek apakah user sudah login atau belum.

Location: __free-practice/src/app/api/login/route.js

import { cookies } from 'next/headers';import { NextResponse } from 'next/server';const DUMMY_USER = { username: 'user', password: '123qwe', role: 'admin',};export async function POST(request) { const { username, password } = await request.json(); // dummy checking if ( username.trim().toLowerCase() === DUMMY_USER.username && password === DUMMY_USER.password ) { const RES_DUMMY_USER = { ...DUMMY_USER }; delete RES_DUMMY_USER.password; // save session cookies().set('userdata', JSON.stringify(RES_DUMMY_USER)); return NextResponse.json({ message: 'Login Success', data: RES_DUMMY_USER, }); } return NextResponse.json({ error: 'User & password not match' });}

Menggunakan dummy user untuk mempermudah login, set cookies dari sisi server sehingga by auto httpOnly:true, sehingga cookies hanya bisa di baca dari sisi xhr request.

Create Middleware

Sebelum ke sisi FE kita bereskan dulu untuk pengerjaan dari sisi BE/server sidenya. Step berikutnya membuat middleware, menambah whitelist pengecekan hanya untuk “/dashboard/*” , dan handling redirect jika session di cookies kosong.

Location: __free-practice/src/middleware.js

import { NextResponse } from 'next/server';import { cookies } from 'next/headers';// This function can be marked `async` if using `await` insideexport function middleware(request) { const userdata = cookies().get('userdata'); if (!userdata) { return NextResponse.redirect(new URL('/', request.url)); } return NextResponse.next();}// See 'Matching Paths' below to learn moreexport const config = { matcher: ['/dashboard/:path*'],};

Tidak ada sedikit perbedaan dengan NextJs versi sebelumnya untuk peletakan middleware. Perbedaan hanya di temukan di module yang digunakan dan hanya sedikit, seperti adanya modul untuk get cookies dan modul untuk redirect.

Implement di FE

Step terakhir tinggal implement endpint login di sisi FE . Next JS 12 menggunakan app route untuk structur directorinya, membuatnya sangat berbeda dengan Next JS versi sebelumnya.

Location: __free-practice/src/app/page.tsx

'use client';import type { NextPage } from 'next';import Box from '@mui/material/Box';import CardContent from '@mui/material/CardContent';import Button from '@mui/material/Button';import Typography from '@mui/material/Typography';import FormControl from '@mui/material/FormControl';import InputLabel from '@mui/material/InputLabel';import Input from '@mui/material/Input';import FormHelperText from '@mui/material/FormHelperText';import { useCallback, useState } from 'react';const Home: NextPage = () => { // initial state const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); // intial functions // handling submit form const submitHandler = useCallback(async () => { const request = await fetch('/api/login', { method: 'post', body: JSON.stringify({ username, password }), }); const response = await request.json(); if (response.error) { alert(response.error); } else { location.href = '/dashboard/user'; } }, [username, password]); return ( <Box width='100vw' height='100vh' display='flex' alignItems='center' justifyContent='center' > <CardContent sx={{ width: '350px', border: '1px solid #e8e8e8', borderRadius: '10px', padding: '40px 30px', }} > <form onSubmit={submitHandler} action='#' method='post'> <Typography variant='h5' color='text.secondary' textAlign='center' gutterBottom > <strong>Login</strong> </Typography> <br /> <FormControl sx={{ textAlign: 'left', width: '100%' }}> <InputLabel htmlFor='my-input-email'>Username</InputLabel> <Input id='my-input-email' name='my-input-email' aria-describedby='my-helper-text' onChange={(e) => setUsername(e.target.value)} value={username} /> <FormHelperText id='my-helper-text'> We'll never share your email. </FormHelperText> </FormControl> <br /> <FormControl sx={{ textAlign: 'left', width: '100%' }}> <InputLabel htmlFor='my-input-password'>Password</InputLabel> <Input id='my-input-password' name='my-input-password' type='password' aria-describedby='my-helper-text' onChange={(e) => setPassword(e.target.value)} value={password} /> </FormControl> <br /> <br /> <br /> <Box textAlign='center'> <Button type='submit' variant='contained' size='large'> Login </Button> </Box> </form> </CardContent> </Box> );};export default Home;

Agar simple dan lebih minimal modul yang digunakan disini kami menggunakan fetch bawaan dari JS.

Hit endpoint “/api/login”, dan jika success maka web bertugas redirect ke “/dashboard/user”.

Kesimpulan

Yups dan sesimple itulah untuk membuat middleware di Next JS 13 untuk sample use case yang kami jelaskan diatas.

Selengkapnya bisa dibaca di dokumentasi resmi NextJS di https://nextjs.org/docs/app/building-your-application/routing/middleware

MauCoding © 2024 powered by YMG Team