NEXTJS - POST net::ERR_ABORTED 500(内部服务器错误)

问题描述 投票:0回答:1

尝试将数据提交到我的 Supabase 数据库时,我在开发人员控制台中收到 POST http://localhost:3000/api/user-profile net::ERR_ABORTED 500(内部服务器错误) 错误消息。终端显示 TypeError: res.status is not a function at POST。这是我第一次尝试在 NextJS 中创建 API 路由,所以放轻松。

文件夹结构:

project-root/
│
├── app/                                   
│   ├── api/                              
│   │   └── user-profile/                 
│   │       └── route.ts               
│   │
│   ├── user-profile/                     
│   │   └── page.tsx   
│   ├── types/     
│   │   └── userProfile.ts 
│   ├── utils/                                
│   │   └── client.ts                                 
│   │
│   ├── globals.css                          
│   └── page.tsx                          
│
├── public/                               
│
├── package.json                          
├── tsconfig.json                         

/app/api/user-profile/route.ts

import type { NextApiRequest, NextApiResponse } from 'next';
import { supabase } from '@/app/utils/client';
import { UserProfileUpdateData } from '@/app/types/userProfile';

// Named export function specifically for handling POST requests
export async function POST(req: NextApiRequest, res: NextApiResponse) {
    const {
        authUserId,
        name,
        email,
        age,
        gender,
        occupation,
        hourly_rate,
    }: UserProfileUpdateData = req.body;

    const { data: updateData, error: updateError } = await supabase
        .from('users')
        .update({ name, email, age, gender, occupation, hourly_rate })
        .eq('auth_user_id', authUserId);

    if (updateError) {
        return res.status(500).json({ error: updateError.message });
    }

    if (!updateData || (updateData as any[]).length === 0) {
        const { error: insertError } = await supabase.from('users').insert([
            {
                auth_user_id: authUserId,
                name,
                email,
                age,
                gender,
                occupation,
                hourly_rate,
                number_of_active_projects: 0,
                number_of_completed_projects: 0,
            },
        ]);

        if (insertError) {
            return res.status(500).json({ error: insertError.message });
        }
    }

    return res
        .status(200)
        .json({ message: 'User profile updated successfully' });
}

/app/(页面)/用户配置文件/page.tsx

'use client';

import React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import toast from 'react-hot-toast';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import DeveloperButtons from '@/app/components/DeveloperButtons';

const profileSchema = z.object({
    name: z.string().min(1, { message: 'Name is required' }),
    email: z.string().email({ message: 'Invalid email format' }),
    age: z.coerce
        .number()
        .int()
        .min(0, { message: 'Invalid age' })
        .max(100, { message: 'Invalid age' }),
    gender: z.string().min(1, { message: 'Gender is required' }),
    occupation: z.string(),
    hourly_rate: z.coerce
        .number()
        .int()
        .min(0, { message: 'Invalid hourly rate' }),
});

type ProfileFormData = z.infer<typeof profileSchema>;

const UserProfile = () => {
    const {
        register,
        handleSubmit,
        reset,
        formState: { errors },
    } = useForm<ProfileFormData>({
        resolver: zodResolver(profileSchema),
    });

    const onSubmit: SubmitHandler<ProfileFormData> = async (data) => {
        const response = await fetch('/api/user-profile/', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(data),
        });

        if (response.ok) {
            toast.success('Profile updated successfully!');
        } else {
            toast.error('An error occurred while updating the profile.');
        }
    };

    return (
        <div className='container mx-auto p-4'>
            <DeveloperButtons />
            <form
                onSubmit={handleSubmit(onSubmit)}
                className='form-control w-full max-w-xs pt-8'
            >
                <label className='label'>
                    <span className='label-text'>Name</span>
                </label>
                <input
                    type='text'
                    {...register('name')}
                    className='input input-bordered w-full max-w-xs'
                />
                {errors.name && (
                    <p className='text-red-500'>{errors.name.message}</p>
                )}

                <label className='label'>
                    <span className='label-text'>Email</span>
                </label>
                <input
                    type='email'
                    {...register('email')}
                    className='input input-bordered w-full max-w-xs'
                />
                {errors.email && (
                    <p className='text-red-500'>{errors.email.message}</p>
                )}

                <label className='label'>
                    <span className='label-text'>Age</span>
                </label>
                <input
                    type='number'
                    {...register('age')}
                    className='input input-bordered w-full max-w-xs'
                />
                {errors.age && (
                    <p className='text-red-500'>{errors.age.message}</p>
                )}

                <label className='label'>
                    <span className='label-text'>Gender</span>
                </label>
                <input
                    type='text'
                    {...register('gender')}
                    className='input input-bordered w-full max-w-xs'
                />
                {errors.gender && (
                    <p className='text-red-500'>{errors.gender.message}</p>
                )}

                <label className='label'>
                    <span className='label-text'>Occupation</span>
                </label>
                <input
                    type='text'
                    {...register('occupation')}
                    className='input input-bordered w-full max-w-xs'
                />
                {errors.occupation && (
                    <p className='text-red-500'>{errors.occupation?.message}</p>
                )}

                <label className='label'>
                    <span className='label-text'>Hourly Rate</span>
                </label>
                <input
                    type='number'
                    step='0.01'
                    {...register('hourly_rate')}
                    className='input input-bordered w-full max-w-xs'
                />
                {errors.hourly_rate && (
                    <p className='text-red-500'>{errors.hourly_rate.message}</p>
                )}

                <div className='flex space-x-2 justify-center my-4'>
                    <button
                        type='submit'
                        className='btn btn-primary'
                    >
                        Submit
                    </button>
                    <button
                        type='button'
                        onClick={() => reset()}
                        className='btn btn-secondary'
                    >
                        Reset
                    </button>
                </div>
            </form>
        </div>
    );
};

export default UserProfile;

我的 Supabase 架构上的“用户”表:

user_id(主键,不可为空,int4),姓名(可为空 varchar),电子邮件(不可为空,唯一,varchar),年龄(可为空,int4),性别(可为空 varchar),职业(可为空 varchar),organization_id (可为空 int4)、hourly_rate (可为空 int4)、number_of_active_projects (可为空 int4)、number_of_completed_projects (可为空 int4)、auth_user_id (可为空 uuid)。

在输入逗号时有点懒,但你明白了。

我希望将数据输入到数据库中,但遇到了 500(内部服务器错误)问题。我怀疑它必须处理 onSubmit 的 body: JSON.stringify(data) 方面,但我对 api 很陌生,所以我可能完全错了。

更新:

Ahmed 建议使用 Next/Response。这是更新后的route.ts:(我注释掉了旧的返回值

import type { NextApiRequest, NextApiResponse } from 'next';
import { supabase } from '@/app/utils/client';
import { UserProfileUpdateData } from '@/app/types/userProfile';
import { NextResponse } from 'next/server';

// Named export function specifically for handling POST requests
export async function POST(req: NextApiRequest /*, res: NextApiResponse */) {
    const {
        authUserId,
        name,
        email,
        age,
        gender,
        occupation,
        hourly_rate,
    }: UserProfileUpdateData = req.body;

    const { data: updateData, error: updateError } = await supabase
        .from('users')
        .update({ name, email, age, gender, occupation, hourly_rate })
        .eq('auth_user_id', authUserId);

    if (updateError) {
        return NextResponse.json(
            { error: updateError.message },
            { status: 500 }
        );
        // return res.status(500).json({ error: updateError.message });
    }

    if (!updateData || (updateData as any[]).length === 0) {
        const { error: insertError } = await supabase.from('users').insert([
            {
                auth_user_id: authUserId,
                name,
                email,
                age,
                gender,
                occupation,
                hourly_rate,
                number_of_active_projects: 0,
                number_of_completed_projects: 0,
            },
        ]);

        if (insertError) {
            return NextResponse.json(
                { error: insertError.message },
                { status: 500 }
            );
            // return res.status(500).json({ error: insertError.message });
        }
    }

    return NextResponse.json({ message: 'success' }, { status: 201 });
    // return res
    //     .status(200)
    //     .json({ message: 'User profile updated successfully' });
}

在终端中,当我点击提交按钮时,它说它正确编译了 /api/user-profile 。在开发人员控制台中,它仍然显示 POST http://localhost:3000/api/user-profile 500(内部服务器错误)

api post next.js supabase http-status-code-500
1个回答
0
投票

App Router 中的路由处理程序有一些更新:

  1. 请求的类型是
    NextRequest
    而不是
    NextApiRequest
import { NextRequest } from "next/server";

export async function POST(req: NextRequest) {}
  1. 要获取主体,请使用
    request.json()
    而不是
    request.body
  const {
        authUserId,
        name,
        email,
        age,
        gender,
        occupation,
        hourly_rate,
    }: UserProfileUpdateData = await req.json();
  1. 您必须始终通过以下方式返回
    Response
  • return new Response("message", {status: 200})
  • return new NextResponse("message", {status: 200})
  • return Response.json({...}, {status: 200})
  • return NextResponse.json({...}, {status: 200})

这应该有效:

import { NextResponse, type NextRequest } from "next/server";

// Named export function specifically for handling POST requests
export async function POST(req: NextRequest) {
  const { authUserId, name, email, age, gender, occupation, hourly_rate } =
    await req.json();

  // ...;


  return NextResponse.json({ message: "success" }, { status: 201 });
}
© www.soinside.com 2019 - 2024. All rights reserved.