mcpField
E
edgeone-makers-middleware

edgeone-makers-middleware

github.com/tencentedgeoneDevelopment1.8k248 installsUpdated 3w ago
Repository

About edgeone-makers-middleware

A skill for implementing request interception in EdgeOne's V8 edge runtime in non-framework or static projects. It covers routing and request handling patterns through a JavaScript middleware API.

Key features

  1. 01Request interception at the edge
  2. 02Redirects and path rewrites
  3. 03Route matching with matchers
  4. 04Auth guards and JSON responses
  5. 05Geo-based routing and A/B tests
  6. 06Request header injection

Use cases

  1. 01Redirecting legacy URLs
  2. 02Restricting API or admin routes
  3. 03Routing by client location
  4. 04Testing alternate landing pages

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/tencentedgeone/edgeone-makers-tools --skill edgeone-makers-middleware

After installing, type/edgeone-makers-middlewarein Claude Code to confirm it loaded.

Details

From the project README

Middleware

Lightweight request interception running at the edge (V8 runtime). Use for redirects, rewrites, auth guards, A/B testing, and header injection.

⚠️ Framework projects (Next.js, Nuxt, etc.): Do NOT use this platform middleware format. Use the framework's built-in middleware instead (e.g. Next.js middleware.ts with NextRequest/NextResponse). The patterns below are for non-framework or pure static projects only.

Basic middleware

File: middleware.js (project root)

export function middleware(context) {
  const { request, next, redirect, rewrite } = context;

  // Pass through — no modification
  return next();
}

Context API

PropertyTypeDescription
requestRequestCurrent request object
next(options?)FunctionContinue to origin; optionally modify headers
redirect(url, status?)FunctionRedirect (default 307)
rewrite(url)FunctionRewrite request path (transparent to client)
geoGeoPropertiesClient geolocation
clientIpstringClient IP address

Route matching

By default middleware runs on ALL routes. Use config.matcher to limit scope:

// Only run on /api/* routes
export const config = {
  matcher: ['/api/:path*'],
};

export function middleware(context) {
  // Auth check for API routes only
  const token = context.request.headers.get('Authorization');
  if (!token) {
    return new Response('Unauthorized', { status: 401 });
  }
  return context.next();
}

Matcher patterns:

// Single path
export const config = { matcher: '/about' };

// Multiple paths
export const config = { matcher: ['/api/:path*', '/admin/:path*'] };

// Regex
export const config = { matcher: ['/api/.*', '^/user/\\d+$'] };

Common patterns

URL Redirect
export function middleware(context) {
  const url = new URL(context.request.url);

  if (url.pathname === '/old-page') {
    return context.redirect('/new-page', 301);
  }
  return context.next();
}
URL Rewrite (transparent proxy)
export function middleware(context) {
  const url = new URL(context.request.url);

  if (url.pathname.startsWith('/blog')) {
    return context.rewrite('/content' + url.pathname);
  }
  return context.next();
}
Add request headers
export function middleware(context) {
  return context.next({
    headers: {
      'x-request-id': crypto.randomUUID(),
      'x-client-ip': context.clientIp,
      'x-country': context.geo.countryCodeAlpha2,
    },
  });
}
Auth guard
export const config = {
  matcher: ['/api/:path*', '/admin/:path*'],
};

export function middleware(context) {
  const token = context.request.headers.get('Authorization');
  if (!token || !token.startsWith('Bearer ')) {
    return new Response(JSON.stringify({ error: 'Unauthorized' }), {
      status: 401,
      headers: { 'Content-Type': 'application/json' },
    });
  }
  return context.next();
}
Geo-based routing
export function middleware(context) {
  const country = context.geo.countryCodeAlpha2;

  if (country === 'CN') {
    return context.rewrite('/zh' + new URL(context.request.url).pathname);
  }
  return context.next();
}
A/B Testing
export function middleware(context) {
  const url = new URL(context.request.url);

  if (url.pathname === '/landing') {
    const variant = Math.random() < 0.5 ? '/landing-a' : '/landing-b';
    return context.rewrite(variant);
  }
  return context.next();
}
Direct JSON response
export function middleware(context) {
  const url = new URL(context.request.url);

  if (url.pathname === '/api/health') {
    return new Response(JSON.stringify({ status: 'ok', timestamp: Date.now() }), {
      headers: { 'Content-Type': 'application/json' },
    });
  }
  return context.next();
}

GeoProperties

Available on context.geo:

PropertyTypeExample
countryNamestringSingapore
countryCodeAlpha2stringSG
countryCodeAlpha3stringSGP
regionNamestring—
cityNamestringSingapore
latitudenumber1.29027
longitudenumber103.851959
asnnumber132203

Comments

Markdown supported