Create A Middleware In NextJS 13
Tags: nextjs, javascript, webdev, react
Published: 2023-09-26 03:41:48

Now I will implement an important function in **Next.js**. That is we need to handle **Middleware**, so what is **middleware** for? We can understand as follows:

**Middleware** is used to handle problems. When a request needs to run into our software, it needs to go through this Middleware first. What's the point of going through it first? Let's go through it to check if the user information is valid or not, check such as: _origin ,  cookie , pathname , hostname ,  header_ , ..... that we allow access to the routers in the application . Depending on the application we install, please check

If you have worked on Middleware **in Laravel, or React**, then you can imagine, it's the same.

**Example**:
**Laravel**: then we need to create Middleware to check the user's Authentication or check _Role , Group , Permissions_ ,...

**React**: we often use middleware in the libraries _Redux , Redux-Toolkit , Redux-Saga _,...

**NextJS** : I create a Middleware file at the same level as app, pages , or inside src . It will check every route passing through the application

Okay, first I will create a **middleware.ts** file at the same level as the app folder

```javascript
import { NextRequest, NextResponse } from "next/server";
const allow_origin_lists :string[]   = process.env.NODE_ENV==='production'?['https://hoanguyenit.com','https://100daysofcode.hoanguyenit.com']:
['https://www.google.com','http://localhost:3000']
export default function middleware(request: NextRequest){
    console.log("env",process.env.NODE_ENV);
    console.log("Host",request.headers.get('host'))
    console.log("Origin",request.headers.get('origin'));
    console.log("Url",request.url)
    console.log("Mehod:",request.method);

    //Chúng ta kiểm tra các request tại đây
    const origin: string | null  = request.headers.get('origin')
    const res = NextResponse.next()
    const res_404 = new NextResponse(null,
        {
            status: 404,
            statusText:"Bad request",
            headers:{
                'Content-Type':'text/plain'
            }
        })
    
    console.log(allow_origin_lists);
    if(origin && !allow_origin_lists.includes(origin)){
        return res_404;
    }

    // add the CORS headers to the response
    res.headers.append('Access-Control-Allow-Credentials', "true")
    res.headers.append('Access-Control-Allow-Origin', origin) 
    res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT')
    res.headers.append(
        'Access-Control-Allow-Headers',
        'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
    )

    return res;
}
export const config = {
    matcher:[ '/api/:path*']
  }
```
If you look at the code above, I use it to check the origins that allow access to the application

```javascript
const allow_origin_lists :string[]   = process.env.NODE_ENV==='production'?['https://100daysofcode.hoanguyenit.com']:
['https://www.google.com','http://localhost:3000']
```
Besides, in function middleware we can check parameter values ​​such as **method **, **origin **, **url **, **host **. These values ​​are essential when we authenticate where user requests come from, what website, and what methods are allowed

```javascript
console.log("env",process.env.NODE_ENV);
   console.log("Host",request.headers.get('host'))
   console.log("Origin",request.headers.get('origin'));
   console.log("Url",request.url)
   console.log("Mehod:",request.method);
```
Next we can check whether origin is in the origin array we allow or not. If not, the response will be 404

```javascript
 const res_404 = new NextResponse(null,
        {
            status: 404,
            statusText:"Bad request",
            headers:{
                'Content-Type':'text/plain'
            }
        })
    
if(origin && !allow_origin_lists.includes(origin)){
        return res_404;
    }
```
The following paragraph is also easy to use: 
**Access-Control-Allow-Credentials** : allows the browser to send CORS requests with authentication information (like a cookie or another credential)

**Access-Control-Allow-Origin** : defines the origin to which the browser is allowed to send CORS requests

**Access-Control-Allow-Methods** : defines the HTTP methods that the server accepts from browsers sending CORS requests

**Access-Control-Allow-Headers** : defines optional HTTP headers that the browser can include in **CORS **requests. This is important if you want to allow the browser to send other custom headers. In this case, a list of headers is listed, including **_X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X- API-Version_**

```javascript
res.headers.append('Access-Control-Allow-Credentials', "true")
    res.headers.append('Access-Control-Allow-Origin', origin) 
    res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT')
    res.headers.append(
        'Access-Control-Allow-Headers',
        'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
    )
```
Next we can provide some routes to let the Middleware know how to check our important routes, we can customize it, as desired.

```javascript
export const config = {
    matcher:[ '/api/:path*']
  }
```
The matcher config above, if you do not also provide Middleware, it will by default scan the entire application route, you can see the image here.

![Create A Middleware In NextJS 13 - hoanguyenit.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oxvs7nhuec72yfnp0md6.jpeg)
If you tell the Middleware which routes to check, it will only check those routes.

For example, I only provide middleware checks in the** /api/:path* **route . Then it only checks at that link

![Create A Middleware In NextJS 13 - hoanguyenit.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tayqm3jeb77ga7eg6u19.jpeg)
Okay, now let's check it out

![Create A Middleware In NextJS 13 - hoanguyenit.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kyw4jw7o5qpoob2vvkz4.jpeg)
We see that there is no cors warning, so it's ok

Let's try another site

![Create A Middleware In NextJS 13 - hoanguyenit.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qpm8qsb477f463o8qvgs.jpeg)
Getting a Cors error because our application is in **development** state , not yet available ( **production** )

There are many things you can check, such as checking whether you are using the phone or not

```javascript
import { NextResponse, userAgent } from 'next/server'
......
 const { device } = userAgent(request)
if (host=== 'hoanguyenit.com' && device.type === 'mobile') {
    const url = request.nextUrl.clone()
   //cập nhật lại host name
    url.hostname = 'm.hoanguyenit.com'
  // chuyển hướng nó
    return NextResponse.redirect(url)
  }
```
Or for example, check the pathname**_ "/api/post/12"_** changes to **_/api/post/99_**

```javascript
if (request.nextUrl.pathname === 'api/post/12')
    const url = request.nextUrl.clone()
    url.pathname = '/api/post/99'
    return NextResponse.redirect(url)
  }
```
The Article : [Create A Middleware In NextJS 13](https://hoanguyenit.com/create-a-middleware-in-nextjs-13.html)