Middleware allows you to run code before a request is completed. Then, based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly.
Middleware를 활용해서 어떤 문제를 해결하고 있을까?
메인페이지를 모바일에서 접속시 무려 61.6MB의 리소스를 다운로드
/
)로 요청이 오면, 미들웨어 실행, 요청 헤더에서 userAgent를 파싱_viewport
이름으로 하위 폴더를 만들고, _viewport/desktop.tsx
, _viewport/mobile.tsx
파일을 만듦 import { NextResponse, userAgent } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname === '/') {
const { device } = userAgent(request)
const viewport = device.type === 'mobile' ? 'mobile' : 'desktop'
request.nextUrl.pathname = `_viewport/${viewport}`
return NextResponse.rewrite(request.nextUrl)
}
return NextResponse.next();
}
// matcher에 해당하는 경로일 경우만 위 middleware가 실행된다. (과부하 방지)
export const config = {
matcher: ['/'],
}```
결과
import type { NextRequest } from 'next/server'
import { Ratelimit } from '@upstash/ratelimit'
import { kv } from '@vercel/kv'
const ratelimit = new Ratelimit({
redis: kv,
// 5 requests from the same IP in 10 seconds
limiter: Ratelimit.slidingWindow(5, '10 s'),
})
export const config = {
runtime: 'edge',
}
export default async function handler(request: NextRequest) {
// You could alternatively limit based on user ID or similar
const ip = request.ip ?? '127.0.0.1'
const { limit, reset, remaining } = await ratelimit.limit(ip)
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: {
'X-RateLimit-Limit': limit.toString(),
'X-RateLimit-Remaining': remaining.toString(),
'X-RateLimit-Reset': reset.toString(),
},
})
}
import { NextRequest, NextResponse } from 'next/server'
import {
BOTD_DEFAULT_PATH,
BOTD_DEFAULT_URL,
BOTD_PROXY_API,
BOTD_PROXY_JS,
} from './constants'
type NextURL = Parameters<typeof NextResponse['rewrite']>[0]
type Proxies = {
[key: string]: (req: NextRequest) => NextURL
}
export const PROXIES: Proxies = {
[BOTD_PROXY_JS]: () =>
'https://cdn.jsdelivr.net/npm/@fpjs-incubator/botd-agent@0/dist/botd.min.js',
[BOTD_PROXY_API + 'detect']: (req) =>
`${BOTD_DEFAULT_URL}${BOTD_DEFAULT_PATH}detect${req.nextUrl.search ?? ''}`,
}
/**
* Proxy Botd scripts and browser calls
* Note: We can't change headers when proxying, so for botd we're going to
* their domain directly instead of using this proxy because we can't send
* the `botd-client-ip` header
*/
export default function botdProxy(req: NextRequest) {
const proxy = PROXIES[req.nextUrl.pathname]
if (proxy) {
return NextResponse.rewrite(proxy(req))
}
}
https://irondeveloper.tistory.com/10
https://vercel.com/blog/introducing-the-edge-runtime
훌륭한 글 감사드립니다.