Skip to content

Instantly share code, notes, and snippets.

@zachshallbetter
Created September 29, 2023 21:33
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save zachshallbetter/ee164b1f2842a3aee5caabaf4e375ae3 to your computer and use it in GitHub Desktop.
Save zachshallbetter/ee164b1f2842a3aee5caabaf4e375ae3 to your computer and use it in GitHub Desktop.
Middleware Examples

Next.js Middleware Examples

This Gist contains a collection of Next.js Middleware examples that demonstrate various use cases and scenarios for enhancing your Next.js applications. Middleware in Next.js allows you to intercept, modify, and control the flow of requests and responses, making it a powerful tool for building robust web applications.

Middleware Examples

  1. Authentication Middleware (authenticationMiddleware.ts):

    • Checks if the user is authenticated based on a session cookie.
    • Redirects unauthenticated users to the login page.
    • Ensures users have the necessary role to access protected routes.
  2. Custom Response Middleware (customResponseMiddleware.ts):

    • Produces custom responses based on a condition.
    • Demonstrates how Middleware can return custom error responses with status codes.
  3. Request Logging Middleware (loggingMiddleware.ts):

    • Logs incoming requests, including method, URL, and timestamp.
    • Useful for debugging and monitoring purposes.
  4. Custom Header Middleware (customHeadersMiddleware.ts):

    • Sets a custom response header in the HTTP response.
    • Shows how Middleware can customize response headers.
  5. Request Body Parsing Middleware (requestBodyParsingMiddleware.ts):

    • Parses the request body, enabling working with data submitted via POST or PUT requests.
    • Handles JSON, form data, and other request body formats.
  6. CSRF Protection Middleware (csrfProtectionMiddleware.ts):

    • Helps protect against Cross-Site Request Forgery (CSRF) attacks.
    • Generates and validates CSRF tokens in form submissions.

Usage Instructions

Each Middleware example is provided in a separate TypeScript file. You can include these files in your Next.js project and use them as Middleware functions in your application.

To use a Middleware function:

  1. Copy the content of the desired Middleware file (e.g., authenticationMiddleware.ts).
  2. Create a new file in your Next.js project with a .ts or .js extension.
  3. Paste the copied Middleware function into the new file.
  4. Import the Middleware function in your Next.js routes or other Middleware files.
  5. Apply the Middleware function to specific routes or route groups using Next.js configuration options or directly in your route handlers.

Make sure to customize the Middleware functions according to your application's requirements.

License

This collection of Next.js Middleware examples is provided under the MIT License. Feel free to use, modify, and distribute these examples in your projects.

// Authentication Middleware
// This Middleware checks if the user is authenticated based on the presence of an "authenticated" cookie in the request headers.
// If the user is not authenticated, it redirects them to the login page. It also checks the user's role and ensures they have the necessary role to access protected routes. Otherwise, it redirects them to a permission-denied page.
export function authenticationMiddleware(request: NextRequest) {
// Check if the user is authenticated based on a session cookie or token.
if (!request.headers.cookie?.includes('authenticated=true')) {
// If not authenticated, redirect the user to the login page.
return NextResponse.redirect('/login');
}
// Read the user role from the session cookie (assuming you set it during login).
const userRole = request.cookies.get('userRole');
// Check if the user has the necessary role to access the route (e.g., Admin role).
if (userRole !== UserRoles.Admin) {
// If the user doesn't have the required role, deny access and redirect to a permission-denied page.
return NextResponse.redirect('/permission-denied');
}
// If authenticated and has the necessary role, allow the request to proceed to the next Middleware or route handler.
return NextResponse.next();
}
// CSRF Protection Middleware
// This Middleware helps protect your application against Cross-Site Request Forgery (CSRF) attacks.
// It can generate and validate CSRF tokens in forms submitted to your application.
export function csrfProtectionMiddleware(request: NextRequest) {
// Check if the request is a POST request.
if (request.method === 'POST') {
// Validate the CSRF token from the request body or headers.
const csrfToken = request.headers.get('X-CSRF-Token') || request.body?.csrfToken;
// Compare the token with the one stored in the user's session or another secure location.
const storedCsrfToken = /* Retrieve the stored CSRF token */;
if (csrfToken !== storedCsrfToken) {
// CSRF token validation failed; reject the request.
return new Response('CSRF token validation failed.', { status: 403 });
}
}
// Continue to the next Middleware or route handler.
return NextResponse.next();
}
// Custom Response Middleware
// This Middleware checks some condition and produces a custom response if needed.
// For example, it may return a custom error response with a status code of 400 if the condition is met.
// If the condition is not met, it allows the request to continue to the next Middleware or route handler.
export function customResponseMiddleware(request: NextRequest) {
// Check some condition and produce a custom response if needed.
if (/* Some condition */) {
// For example, return a custom error response with a status code of 400.
return new Response('Custom error message', { status: 400 });
}
// If the condition is not met, continue to the next Middleware or route handler.
return NextResponse.next();
}
// Error Handling Middleware
// This Middleware handles errors that occur during request processing.
// It can catch exceptions, log them, and return a user-friendly error response.
export function errorHandlingMiddleware(request: NextRequest) {
try {
// Attempt to process the request. If an error occurs, it will be caught.
// For example, you can handle validation errors, database errors, or other exceptions here.
// If no error occurs, the request will continue to the next Middleware or route handler.
// Example: Simulate an error for demonstration purposes.
if (Math.random() < 0.5) {
throw new Error('An unexpected error occurred.');
}
// If no error occurred, continue to the next Middleware or route handler.
return NextResponse.next();
} catch (error) {
// Handle the error gracefully.
console.error('Error:', error.message);
// Return a user-friendly error response with a status code of 500 (Internal Server Error).
return new Response('An error occurred. Please try again later.', { status: 500 });
}
}
// Request Logging Middleware
// This Middleware logs information about the incoming request, including the request method, URL, and timestamp.
// It can be valuable for debugging and monitoring purposes.
// After logging, it allows the request to continue to the next Middleware or route handler.
export function loggingMiddleware(request: NextRequest) {
// Log information about the incoming request, including the request method, URL, and timestamp.
console.log(`Received ${request.method} request to ${request.url} at ${new Date()}`);
// Continue to the next Middleware or route handler.
return NextResponse.next();
}
// Rate Limiting Middleware
// This Middleware enforces rate limits on incoming requests to prevent abuse or excessive usage of your API.
// It can track and limit requests based on IP address or user session.
export function rateLimitingMiddleware(request: NextRequest) {
// Implement rate limiting logic here.
// Check the rate limit for the requesting IP or user session.
// If the limit is exceeded, return an appropriate response (e.g., 429 Too Many Requests).
// Otherwise, allow the request to continue to the next Middleware or route handler.
// For simplicity, we'll just allow all requests in this example.
return NextResponse.next();
}
// Request Body Parsing Middleware
// This Middleware parses the request body, allowing you to work with data submitted via POST or PUT requests.
// It can handle JSON, form data, and other request body formats.
export async function requestBodyParsingMiddleware(request: NextRequest) {
// Check if the request has a body (e.g., for POST or PUT requests).
if (request.method === 'POST' || request.method === 'PUT') {
try {
// Parse the request body as JSON.
const requestBody = await request.json();
// You can now work with the parsed data.
console.log('Parsed Request Body:', requestBody);
// Attach the parsed data to the request object for later Middleware or route handlers.
request.locals.parsedBody = requestBody;
} catch (error) {
// Handle parsing errors (e.g., invalid JSON).
console.error('Request Body Parsing Error:', error.message);
return new Response('Invalid request body.', { status: 400 });
}
}
// Continue to the next Middleware or route handler.
return NextResponse.next();
}
// Response Header Middleware
// This Middleware adds custom response headers to the outgoing response.
// For example, it can set security-related headers like Content Security Policy (CSP) or CORS headers.
export function responseHeaderMiddleware(request: NextRequest) {
// Create a response object.
const response = NextResponse.next();
// Set custom headers in the response.
response.headers.set('Content-Security-Policy', "default-src 'self'");
response.headers.set('Access-Control-Allow-Origin', '*');
// Continue to the next Middleware or route handler.
return response;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment