fix(chat): handle inactive botid gracefully (#1437)

This commit is contained in:
dancer 2026-03-02 15:06:22 +00:00 committed by GitHub
parent ad47aa0ee0
commit 314f8ced57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 30 additions and 9 deletions

View file

@ -1,6 +1,7 @@
import type { NextAuthConfig } from "next-auth"; import type { NextAuthConfig } from "next-auth";
export const authConfig = { export const authConfig = {
basePath: "/api/auth",
pages: { pages: {
signIn: "/login", signIn: "/login",
newUser: "/", newUser: "/",

View file

@ -1,4 +1,3 @@
import { checkBotId } from "botid/server";
import { geolocation, ipAddress } from "@vercel/functions"; import { geolocation, ipAddress } from "@vercel/functions";
import { import {
convertToModelMessages, convertToModelMessages,
@ -8,6 +7,7 @@ import {
stepCountIs, stepCountIs,
streamText, streamText,
} from "ai"; } from "ai";
import { checkBotId } from "botid/server";
import { after } from "next/server"; import { after } from "next/server";
import { createResumableStreamContext } from "resumable-stream"; import { createResumableStreamContext } from "resumable-stream";
import { auth, type UserType } from "@/app/(auth)/auth"; import { auth, type UserType } from "@/app/(auth)/auth";
@ -64,9 +64,12 @@ export async function POST(request: Request) {
const { id, message, messages, selectedChatModel, selectedVisibilityType } = const { id, message, messages, selectedChatModel, selectedVisibilityType } =
requestBody; requestBody;
const [botResult, session] = await Promise.all([checkBotId(), auth()]); const [botResult, session] = await Promise.all([
checkBotId().catch(() => null),
auth(),
]);
if (botResult.isBot) { if (botResult?.isBot) {
return new ChatbotError("unauthorized:chat").toResponse(); return new ChatbotError("unauthorized:chat").toResponse();
} }

View file

@ -3,7 +3,7 @@ import { initBotId } from "botid/client/core";
initBotId({ initBotId({
protect: [ protect: [
{ {
path: "/api/chat", path: `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/chat`,
method: "POST", method: "POST",
}, },
], ],

View file

@ -11,7 +11,7 @@ let client: ReturnType<typeof createClient> | null = null;
function getClient() { function getClient() {
if (!client && process.env.REDIS_URL) { if (!client && process.env.REDIS_URL) {
client = createClient({ url: process.env.REDIS_URL }); client = createClient({ url: process.env.REDIS_URL });
client.on("error", () => {}); client.on("error", () => undefined);
client.connect().catch(() => { client.connect().catch(() => {
client = null; client = null;
}); });
@ -20,10 +20,14 @@ function getClient() {
} }
export async function checkIpRateLimit(ip: string | undefined) { export async function checkIpRateLimit(ip: string | undefined) {
if (!isProductionEnvironment || !ip) return; if (!isProductionEnvironment || !ip) {
return;
}
const redis = getClient(); const redis = getClient();
if (!redis?.isReady) return; if (!redis?.isReady) {
return;
}
try { try {
const key = `ip-rate-limit:${ip}`; const key = `ip-rate-limit:${ip}`;
@ -37,6 +41,8 @@ export async function checkIpRateLimit(ip: string | undefined) {
throw new ChatbotError("rate_limit:chat"); throw new ChatbotError("rate_limit:chat");
} }
} catch (error) { } catch (error) {
if (error instanceof ChatbotError) throw error; if (error instanceof ChatbotError) {
throw error;
}
} }
} }

View file

@ -1,5 +1,5 @@
import type { NextConfig } from "next";
import { withBotId } from "botid/next/config"; import { withBotId } from "botid/next/config";
import type { NextConfig } from "next";
const basePath = "/demo"; const basePath = "/demo";
@ -8,6 +8,7 @@ const nextConfig: NextConfig = {
assetPrefix: "/demo-assets", assetPrefix: "/demo-assets",
env: { env: {
NEXT_PUBLIC_BASE_PATH: basePath, NEXT_PUBLIC_BASE_PATH: basePath,
NEXTAUTH_URL: `http://localhost${basePath}/api/auth`,
}, },
cacheComponents: true, cacheComponents: true,
images: { images: {

View file

@ -1,5 +1,15 @@
{ {
"framework": "nextjs", "framework": "nextjs",
"rewrites": [
{
"source": "/149e9513-01fa-4fb0-aad4-566afd725d1b/2d206a39-8ed7-437e-a3be-862e0f06eea3/a-4-a/c.js",
"destination": "https://api.vercel.com/bot-protection/v1/challenge"
},
{
"source": "/149e9513-01fa-4fb0-aad4-566afd725d1b/2d206a39-8ed7-437e-a3be-862e0f06eea3/:path*",
"destination": "https://api.vercel.com/bot-protection/v1/proxy/:path*"
}
],
"redirects": [ "redirects": [
{ {
"source": "/", "source": "/",