0Pricing
Next.js 15 Fullstack Web Apps · 课时

速率限制与 API 错误处理

使用速率限制保护 Next.js 路由处理器,并通过正确的 HTTP 状态码返回一致且结构良好的错误响应。

速率限制与 API 错误处理 是 CoddyKit 上的免费 Next.js 15 Fullstack Web Apps 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Next.js 15 Fullstack Web Apps 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Next.js 15 Fullstack Web Apps 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Why Rate Limit

Public API routes are exposed to abuse: brute-force logins, scraping, and accidental floods. Rate limiting caps how many requests a client may make in a time window, protecting your backend and external service quotas.

Identifying the Client

You need a key to count requests per client. Common choices are the IP address, an API key, or the authenticated user ID. In route handlers, read the IP from headers set by your platform.

export async function GET(req) {
  const ip = req.headers.get('x-forwarded-for') ?? 'unknown';
  return Response.json({ ip });
}

A Fixed-Window Counter

The simplest algorithm counts requests in a fixed time window per key. When the count exceeds the limit, reject further requests until the window resets.

function fixedWindow(store, key, limit, windowMs) {
  const now = Date.now();
  const entry = store[key] || { count: 0, reset: now + windowMs };
  if (now > entry.reset) { entry.count = 0; entry.reset = now + windowMs; }
  entry.count++;
  store[key] = entry;
  return entry.count <= limit;
}

Trying the Limiter

Run the fixed-window logic locally to see it allow then block.

function fixedWindow(store, key, limit, windowMs) {
  const now = Date.now();
  const entry = store[key] || { count: 0, reset: now + windowMs };
  if (now > entry.reset) { entry.count = 0; entry.reset = now + windowMs; }
  entry.count++;
  store[key] = entry;
  return entry.count <= limit;
}
const store = {};
for (let i = 0; i < 4; i++) {
  console.log(i, fixedWindow(store, 'ip1', 3, 1000));
}

In-Memory vs Distributed

An in-memory store resets on every cold start and is not shared across serverless instances. For real deployments use a shared store like Redis (e.g. Upstash) so limits are consistent everywhere.

Returning 429

When a client is over the limit, respond with HTTP 429 Too Many Requests and a Retry-After header telling them when to try again.

export async function POST(req) {
  if (!allowed) {
    return new Response('Rate limit exceeded', {
      status: 429,
      headers: { 'Retry-After': '60' },
    });
  }
  return Response.json({ ok: true });
}

A Consistent Error Shape

Clients parse errors more easily when every failure has the same JSON shape. Standardize on a small envelope.

function apiError(message, status, code) {
  return Response.json(
    { error: { message, code } },
    { status }
  );
}

Mapping Errors to Status Codes

Choose the status that matches the cause:

  • 400 bad input
  • 401 not authenticated
  • 403 not authorized
  • 404 not found
  • 429 rate limited
  • 500 server fault

Catching Unexpected Errors

Wrap handler logic in try/catch so an unhandled exception becomes a controlled 500 rather than a leaked stack trace.

export async function GET() {
  try {
    const data = await loadData();
    return Response.json(data);
  } catch (e) {
    console.error(e);
    return Response.json({ error: { message: 'Internal error' } }, { status: 500 });
  }
}

Reusable Wrapper

Factor the boilerplate into a higher-order function that applies rate limiting and error catching to any handler.

function withGuards(handler) {
  return async (req) => {
    if (!checkLimit(req)) return apiError('Too many requests', 429);
    try { return await handler(req); }
    catch { return apiError('Internal error', 500); }
  };
}

Never Leak Internals

In production, never send raw error messages, stack traces, or SQL details to the client. Log them server-side and return a generic message with a stable error code.

Quick Check

Which HTTP status code and header best signal that a client has exceeded the rate limit?

Recap

You hardened your API routes:

  • Identified clients and counted requests with a fixed-window limiter.
  • Returned 429 with Retry-After, preferring Redis for distributed limits.
  • Standardized a JSON error envelope and mapped causes to status codes.
  • Caught exceptions and avoided leaking internals.

常见问题解答

「速率限制与 API 错误处理」课时是免费的吗?

是的 — 「速率限制与 API 错误处理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Next.js 15 Fullstack Web Apps 课程的其余内容,请升级到 CoddyKit PRO。 Next.js 15 Fullstack Web Apps 课程共包含 4 节课。

「速率限制与 API 错误处理」这节课中我会学到什么?

使用速率限制保护 Next.js 路由处理器,并通过正确的 HTTP 状态码返回一致且结构良好的错误响应。 你通过在浏览器中直接运行的动手代码来练习 Next.js 15 Fullstack Web Apps,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Next.js 15 Fullstack Web Apps 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Next.js 15 Fullstack Web Apps 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「速率限制与 API 错误处理」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Next.js 15 Fullstack Web Apps 课中编写并运行代码吗?

能。每节 Next.js 15 Fullstack Web Apps 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 构建 API 路由处理程序
  2. 请求验证与安全
  3. 集成外部服务
  4. 速率限制与 API 错误处理
← 返回 Next.js 15 Fullstack Web Apps