Why am I getting "500 (Internal Server Error)" and "Uncaught (in promise) SyntaxError: Unexpected token < "?

Why am I getting "500 (Internal Server Error)" and "Uncaught (in promise) SyntaxError: Unexpected token < "?

我试图通过对 Next.js API 路由的提取 API POST 请求将一些数据插入数据库,但我收到以下两个错误浏览器控制台中的消息:

api/addCompany/addCompany:1 加载资源失败:服务器响应状态为 500(内部服务器错误)register:1

未捕获(承诺)SyntaxError:意外标记 < 在 JSON 位置 0

这些是我项目的文件夹(因为 Next.js 的路由系统所以相关)

这是我执行提取 API 请求的组件(请不要判断我糟糕的 Typescript 技能,我是新手,仍然没有找到合适的事件类型):

import styles from '../styles/Register.module.css'
import { NextPage } from "next"
import { prisma } from '../prisma/prisma_client';
import { Prisma } from '@prisma/client';
import { useSession } from "next-auth/react"

const Register: NextPage = () => {
  
  const createCompany: any = async (event: any) => {
    event.preventDefault()

    const company: Prisma.CompanyCreateInput = {
      companyName: event.target.companyName.value,
      gender: event.target.gender.value,
      firstName: event.target.firstName.value,
      lastName: event.target.lastName.value,
      street: event.target.street.value,
      houseNumber: parseInt(event.target.houseNumber.value),
      postcode: parseInt(event.target.postcode.value),
      city: event.target.city.value,
      country: event.target.country.value,
      countryCode: event.target.countryCode.value,
      callNumber: parseInt(event.target.callNumber.value),
      emailAddress: event.target.emailAddress.value,
      website: event.target.website.value,
      socials: {},
      companyUser: {
        connect: { id: 'cl0y4y8xo0021mwtcmwlqfif6' }
      }
    }

    const companyJSON = JSON.stringify(company)
    const endpoint = '/api/addCompany/addCompany'
    const options = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: companyJSON,
    }

    const response = await fetch(endpoint, options)

    const data = await response.json()
    console.log(data)
  }

  return (
    <form onSubmit={createCompany} className={styles.form} id="signupForm" noValidate>
      <h2>Company Information</h2>

      <div className="fieldWrapper">
        <input type="text" id="companyName" name="companyName" placeholder=" " />
        <label htmlFor="companyName">Company Name<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="text" list="genders" id="gender" name="gender" placeholder=" " />
        <label htmlFor="gender">Gender<span>*</span></label>
        <div className='errorMessage'></div>
        <datalist id="genders">
          <option>Female</option>
          <option>Male</option>
        </datalist>
      </div>

      <div className="fieldWrapper">
        <input type="text" id="firstName" name="firstName" placeholder=" " />
        <label htmlFor="firstName">First Name<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="text" id="lastName" name="lastName" placeholder=" " />
        <label htmlFor="lastName">Last Name<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="text" id="street" name="street" placeholder=" " />
        <label htmlFor="street">Street<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="number" id="houseNumber" name="houseNumber" placeholder=" " />
        <label htmlFor="houseNumber">House Number<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="number" id="postcode" name="postcode" placeholder=" " />
        <label htmlFor="postcode">Postcode<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="text" id="city" name="city" placeholder=" " />
        <label htmlFor="city">City<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="text" id="country" name="country" placeholder=" " />
        <label htmlFor="country">Country<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="text" id="countryCode" name="countryCode" placeholder=" " />
        <label htmlFor="countryCode">Country Code<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="number" id="callNumber" name="callNumber" placeholder=" " />
        <label htmlFor="callNumber">Call Number<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="email" id="emailAddress" name="emailAddress" placeholder=" " />
        <label htmlFor="emailAddress">Email Address<span>*</span></label>
        <div className='errorMessage'></div>
      </div>

      <div className="fieldWrapper">
        <input type="text" id="website" name="website" placeholder=" " />
        <label htmlFor="website">Website</label>
      </div>

      <div className="fieldWrapper">
        <input type="text" id="socials" name="socials" placeholder=" " />
        <label htmlFor="socials">Socials</label>
      </div>

      <div className="fieldWrapper">
        <button type="submit">Save</button>
      </div>
    </form>
  )
}

export default Register

这是 addCompany 文件的代码,用作我的提取 API 请求的 Next.js API 路由:

import { Prisma } from '@prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../../prisma/prisma_client';

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
    const {body} = req;

    const companyData: Prisma.CompanyCreateInput = JSON.parse(body);

    const addCompany = await prisma.company.create({
        data: companyData
    })
     res.status(200).json(addCompany);
}

export default handler

感谢任何帮助。谢谢。

我试着注释掉 const data = await response.json() console.log(data) 在 Register 组件中,因此错误“Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0”消失了,但这根本不是问题的解决方案。 我还尝试将我的获取请求的路由调整为任何可能的选项,因为我不确定 Next.js 是如何自动完成它的,例如我尝试过:'/api/addCompany/addCompany.ts' 等等。

我希望问题不大,希望不是打字错误。 再次感谢。

PS: 我也查看了关于这个问题的类似帖子,但找不到解决我的问题的方法。

不需要重新解析 API 端点中的正文数据,因为 Next.js middleware 已经将该数据转换为对象:

API routes provide built in middlewares which parse the incoming request (req). Those middlewares are:

  • req.cookies - An object containing the cookies sent by the request. Defaults to {}
  • req.query - An object containing the query string. Defaults to {}
  • req.body - An object containing the body parsed by content-type, or null if no body was sent

像下面这样的东西应该可以工作:

import { Prisma } from '@prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../../prisma/prisma_client';

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
    const {body: companyData} = req;

    //const companyData: Prisma.CompanyCreateInput = JSON.parse(body);<- No need to reparse the data here

    const addCompany = await prisma.company.create({
        data: companyData
    })
     res.status(200).json(addCompany);
}

export default handler

感谢这个回答 的澄清。