Edge Middleware APIs
Learn about the Edge Middleware APIs.Edge Middleware use the Edge Runtime, a runtime that is built on top of V8. The Edge Runtime exposes a subset of Web Standard APIs such as FetchEvent, Response, and Request.
These native Web API objects are extended to give you more control over how you manipulate and configure a response, based on the incoming requests.
The Edge Runtime can execute V8 code, but you don't have access to regular Node.js APIs such as process, path, or fs. This is because they are Node.js specific, and not available in a browser context.
Instead you have access to APIs related to networking, like fetch, request, and response, APIs that are available on the browser:
For a full list of available APIs see the Edge Runtime API documentation.
All Middleware should be created in a single middleware.ts or middleware.js file at the root of your project. You can then export a middleware function from the file.
The following example assumes you have a route called /about in your project, and that you want to rewrite to a new route /about-2 whenever someone visits /about:
export default function middleware(request) {
return Response.redirect(new URL('/about-2', request.url));
}
// config with custom matcher
export const config = {
matcher: '/about/:path*',
};
Middleware will be invoked for every route in your project. There are two ways to define which paths the middleware should be run on: with a custom matcher config or with conditional statements.
While the config option is the preferred method, as it does not get invoked on every request, you can also use conditional statements to only run the Middleware when it matches specific paths.
To decide which route the Middleware should be run on, you can use a custom matcher config to filter on specific paths. The matcher property can be used to define either a single path, or using an array syntax, multiple paths.
export const config = {
matcher: '/about/:path*',
};
export const config = {
matcher: ['/about/:path*', '/dashboard/:path*'],
};
import { rewrite } from '@vercel/edge';
export function middleware(request: Request) {
const url = new URL(request.url);
if (url.pathname.startsWith('/about')) {
return rewrite(new URL('/about-2', request.url));
}
if (url.pathname.startsWith('/dashboard')) {
return rewrite(new URL('/dashboard/user', request.url));
}
}
In addition to these APIs, Next.js Middleware comes with built in helpers that are based upon the native FetchEvent, Response, and Request objects.
See the next/server documentation for more information.
While Next.js comes with built in helpers, if you are using Edge Middleware outside of Next.js, you can use the @vercel/edge package, which exports the following helpers:
rewrite: Returns a response that rewrites the request to a different URLgeolocation: Returns the location information for the incoming requestipAddress: Returns the IP address of the request from the headersnext
Add the @vercel/edge package to your project with:
npm i @vercel/edge
Installing @vercel/edge using the npm command.
The rewrite helper returns a response that rewrites the request to a different URL. The following example shows how to rewrite a request to a different URL:
import { rewrite } from '@vercel/edge';
export function middleware(request: Request) {
return rewrite(new URL('/about-2', request.url));
}
The geolocation helper returns the location information for the incoming request. The function receives a request object and returns the following properties:
city: The city that the request originated fromcountry: The country that the request originated fromlatitude: The latitude of the clientlongitude: The longitude of the clientregion: The Vercel Edge Network region that received the request
Each property returns a string, or undefined.
The following example assumes a bare project with index.html, and blocked.html files at the root.
import { geolocation } from '@vercel/edge';
const BLOCKED_COUNTRY = 'SE';
export const config = {
// Only run the middleware on the home route
matcher: '/',
};
export default function middleware(request: Request) {
const url = new URL(request.url);
const { country } = geolocation(request);
// You can also get the country using dot notation on the function
// const country = geolocation(request).country;
if (country === BLOCKED_COUNTRY) {
url.pathname = '/blocked.html';
} else {
url.pathname = '/index.html';
}
// Return a new redirect response
return Response.redirect(url);
}
The ipAddress helper returns the IP address of the request from the headers. The function receives a request object, and the returned value is a string with the IP address, or undefined.
The following example adds a custom header based on the IP address of the request:
import { ipAddress, next } from '@vercel/edge';
export function middleware(request: Request) {
const ip = ipAddress(request);
return next({
headers: { 'x-your-ip-address': ip || 'unknown' },
});
}
The next helper returns a Response that instructs the function to continue processing the request. The function receives a request object and returns a Response object.
The following example adds a custom header:
import { next } from '@vercel/edge';
export default function middleware() {
return next({
headers: { 'x-from-middleware': 'true' },
});
}
A no-op example. This will return a 200 OK response with no further action:
import { next } from '@vercel/edge';
export default function middleware() {
return next();
}
The Edge Runtime has some restrictions including:
- Native Node.js APIs are not supported. For example, you can't read or write to the filesystem
- Node Modules can be used, as long as they implement ES Modules and do not use any native Node.js APIs. For example, you could use the
path-to-regexppackage to do path matches - You can use ES Modules and split your code into reusable files that will then be bundled together when the application is built
- Calling
requiredirectly is not allowed. If you do use it, it might work when the import path can be statically resolved, but it is not recommended. Use ES Modules instead
The following JavaScript language features are disabled, and will not work:
eval: Evaluates JavaScript code represented as a stringnew Function(evalString): Creates a new function with the code provided as an argument
See Edge Middleware Limitations for more information on these limitations.