我正在构建一个 NextJs 14 Web 应用程序。我正在使用服务器操作从客户端组件中的数据库获取数据。检查网络请求时。我看到 prisma 正在发出 POST 请求而不是 GET。我如何确保它应该发出 GET 请求?
我要解决的问题是对客户端组件的 POST 请求数量进行速率限制。为了解决这个问题,我使用 @upstash/ratelimit 和 @vercel/kv
来使用 NextJs 中间件当我打开页面时,它发送 4 个 POST 请求(还没弄清楚为什么它发送 4 个而不是 2 个),中间件将其视为 POST 请求,并在一段时间内减少了 POST 请求计数。
中间件文件:
import { NextRequest, NextResponse } from 'next/server';
import { Ratelimit } from '@upstash/ratelimit';
import { kv } from '@vercel/kv';
const ratelimit = new Ratelimit({
redis: kv,
//allow 5 requests from the same IP in 10 seconds
limiter: Ratelimit.slidingWindow(5, '10 s'),
});
// Define which routes you want to rate limit
export const config = {
matcher: "/((?!api|_next|fonts|examples|dashboard|not-found|[\\w-]+\\.\\w+).*)/",
}
export default async function middleware(request: NextRequest) {
// You could alternatively limit based on user ID or similar
const ip = request.ip ?? '127.0.0.1';
console.log("IP: ", ip);
if(request.method === 'POST') {
// console.log("Request: ", request);
const { success, pending, limit, reset, remaining } = await ratelimit.limit(
ip
)
console.log("success: ", success);
console.log("remaining: ", remaining);
return success
? NextResponse.next()
: NextResponse.redirect("/");
}
return NextResponse.next();
}
这是组件:
"use client";
import React, { useEffect, useState } from "react";
import { useRouter, useParams } from "next/navigation";
import {
getAnsweredQuestionsByUsername,
getCreatorPageDetails,
} from "../actions/actions";
import { UserProps, Username } from "./types";
import Image from "next/image";
import UserForm from "@/components/UserForm";
import { Question } from "../dashboard/types";
const UserPage = () => {
const params = useParams();
const router = useRouter();
const username: Username = params.username;
const [loading, setLoading] = useState(true);
const [recipient, setRecipient] = useState<UserProps>({});
const [answeredQuestions, setAnsweredQuestions] = useState<Question[]>([]);
useEffect(() => {
async function getUserData() {
const recipentDetails = await getCreatorPageDetails(username as string);
const answeredQuestions = await getAnsweredQuestionsByUsername(
username as string
);
if (!recipentDetails) {
router.replace("/not-found");
} else {
setRecipient(recipentDetails);
setAnsweredQuestions(answeredQuestions as Question[]);
setLoading(false);
}
}
getUserData();
}, []);
以下是行动:
export async function getCreatorPageDetails(username : string) {
try {
const user = await prisma.user.findFirst({
where: {
username: username as string,
},
});
return user;
} catch (error) {
console.log("Couldn't find user", error);
}
}
export async function getAnsweredQuestionsByUsername(username: string) {
try {
const answeredQuestions = await prisma.question.findMany({
include: {
answer: true,
},
orderBy: {
createdAt: 'desc',
},
where: {
isAnswered: true,
}
})
return answeredQuestions;
} catch (error) {
console.log("Error getting questions", error);
return {
error: "Error getting questions for username"
}
}
}
我试图找到一种方法以某种方式将 prisma 查询设置为 GET 但没有找到任何解决方案。如果有其他方法可以做到这一点。我将不胜感激。
在 Nextjs 官方文档中找到了这个:
在幕后,操作使用 POST 方法,并且只有此 HTTP 方法可以调用它们。
来源:https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations