You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中GET接口获取JSON请求体触发500错误的问题

问题:Next.js GET接口调用request.json()返回500错误

我写了下面这个Next.js API接口,只要加上const rawRequest = await request.json();这一行,接口就返回500状态码。试过重装依赖、升级Next.js到最新版、重启服务器,都没用。想问下GET请求是不是不能带请求体?

import { NextResponse } from "next/server";
import z from "zod";
import { Review, User, } from "@/mongo";
import { findReview } from "@/mongo/functions/review";

export async function GET (request: Request) {
    const rawRequest = await request.json();
    
    const Schema = z.object ({
        id: z.string().optional(),
        filters: z.any().optional(),
    }).strict()

    const parsedRequest: RequestType = rawRequest.body;

    const valid = Schema.safeParse(parsedRequest);

    type RequestType = z.infer<typeof Schema>;

    if (!valid.success) {
        return NextResponse.json(
            { message: `Error: ${valid.error}` },
            { status: 400 }
        );
    }

    try {
        const reviews = await findReview ({})
        return NextResponse.json ({reviews})
    } catch (error) {
        return NextResponse.json ({message: `Error: ${error}`})
    }
}

export async function POST (request: Request) {
    const rawRequest = await request.json();

    const statusOptions = {
        unlisted: "unlisted",
        public: "public",
    } as const

    const Schema = z.object({
        title: z.string().min(5).max(20),
        text: z.string().min(10).max(1000),
        stars: z.number().gte(1).lte(5),
        type: z.string(),
        status: z.nativeEnum(statusOptions),
        author: z.string(),
        recipient: z.string().min(5),
    });

    const parsedRequest: RequestType = rawRequest.body;

    const valid = Schema.safeParse(parsedRequest);

    type RequestType = z.infer<typeof Schema>;

    if (!valid.success) {
        return NextResponse.json(
            { message: `Error: ${valid.error}` },
            { status: 400 }
        );
    }

    let isCustomer = false;

    if (parsedRequest.type === "customer") {
        isCustomer = true;
    }

    try {
         await Review.create ({
            title: parsedRequest.title,
            text: parsedRequest.text,
            stars: parsedRequest.stars,
            isReviewOnCustomer: isCustomer,
            author: parsedRequest.author,
            recipient: parsedRequest.recipient,
            status: parsedRequest.status,
        })

        const allReviews = await Review.find({recipient: parsedRequest.recipient});

        const stars: number[] = []
        
        allReviews.forEach(review => {
            stars.push(review.stars)
        })
        let total = 0;
        for(let i = 0; i < stars.length; i++) {
            total += stars[i];
        }
        const avg = total / stars.length;

        if (isCustomer) {
            await User.updateOne ({_id: parsedRequest.recipient}, {customerRating: avg})
        }
        else {
            await User.updateOne ({userId: parsedRequest.recipient}, {businessRating: avg})
        }

        return NextResponse.json({ message: "Successfully added a review" });
    } catch (error) {
        return NextResponse.json({ message: `Error: ${error}` }, { status: 500 });
    }
}

错误信息

⨯ SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at parseJSONFromBytes (node:internal/deps/undici/undici:6662:19)
    at successSteps (node:internal/deps/undici/undici:6636:27)
    at specConsumeBody (node:internal/deps/undici/undici:6642:9)
    at NextRequest.json (node:internal/deps/undici/undici:6533:18)
    at GET (webpack-internal:///(rsc)/./app/api/reviews/add/route.ts:15:38)
    at /Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:62597
    at /Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/lib/trace/tracer.js:131:36
    at NoopContextManager.with (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:7062)
    at ContextAPI.with (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:518)
    at NoopTracer.startActiveSpan (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:18093)
    at ProxyTracer.startActiveSpan (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:18854)
    at /Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/lib/trace/tracer.js:120:103
    at NoopContextManager.with (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:7062)
    at ContextAPI.with (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:518)
    at NextTracerImpl.trace (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/lib/trace/tracer.js:120:28)
    at /Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:56181
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at Object.wrap (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:36760)
    at /Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:53968
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at Object.wrap (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:36288)
    at /Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:53930
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at eI.execute (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:53904)
    at eI.handle (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:63840)
    at doRender (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/base-server.js:1332:60)
    at cacheEntry.responseCache.get.routeKind (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/base-server.js:1571:34)
    at ResponseCache.get (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/response-cache/index.js:54:26)
    at DevServer.renderToResponseWithComponentsImpl (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/base-server.js:1479:53)
    at /Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/base-server.js:983:121
    at NextTracerImpl.trace (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/lib/trace/tracer.js:102:20)
    at DevServer.renderToResponseWithComponents (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/base-server.js:983:41)
    at DevServer.renderPageComponent (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/base-server.js:1850:35)
    at async DevServer.renderToResponseImpl (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/base-server.js:1888:32)
    at async DevServer.pipeImpl (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/base-server.js:902:25)
    at async NextNodeServer.handleCatchallRenderRequest (/Users/ekrich/git/commerce-karma-prod/node_modules/next/dist/server/next-server.js:266:17)

解答

  1. GET请求不应该带请求体
    虽然HTTP规范没有完全禁止GET请求带请求体,但绝大多数客户端、服务器和中间件都不支持这种做法,Next.js的request.json()在处理没有请求体的GET请求时,就会抛出你看到的Unexpected end of JSON input错误——因为根本没有JSON数据可以解析。

  2. 修复方案
    如果你需要传递参数给GET接口,应该用URL查询参数或者路由参数,而不是请求体:

修改后的GET接口代码

export async function GET(request: Request) {
    // 解析URL查询参数
    const { searchParams } = new URL(request.url);
    const parsedRequest = {
        id: searchParams.get("id") || undefined,
        filters: searchParams.get("filters") ? JSON.parse(searchParams.get("filters")!) : undefined
    };

    const Schema = z.object({
        id: z.string().optional(),
        filters: z.any().optional(),
    }).strict();

    const valid = Schema.safeParse(parsedRequest);

    if (!valid.success) {
        return NextResponse.json(
            { message: `Error: ${valid.error}` },
            { status: 400 }
        );
    }

    try {
        // 把解析后的参数传给findReview
        const reviews = await findReview(parsedRequest);
        return NextResponse.json({ reviews });
    } catch (error) {
        return NextResponse.json({ message: `Error: ${error}` });
    }
}
  1. 额外问题修复
    另外你的代码里还有个小问题:不管是GET还是POST接口,request.json()返回的就是请求体本身,不需要再取rawRequest.body——await request.json()直接得到的就是POST请求发送的JSON对象,所以POST接口里的const parsedRequest: RequestType = rawRequest.body;应该改成const parsedRequest: RequestType = rawRequest;,不然会拿到undefined导致验证失败。

内容的提问来源于stack exchange,提问作者Ethan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:25:56