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

在Nuxt中复刻OpenAI API示例时遇500及JSON解析错误求助

问题排查:Nuxt复刻OpenAI官方示例时的500错误与response.json()报错

问题背景

将OpenAI官方的React/Next示例复刻到Nuxt框架,创建了server/api/completion.js后端接口和index.vue前端页面,点击提交按钮时出现两个错误。

后端代码(server/api/completion.js)

import { Configuration, OpenAIApi } from 'openai'

const configuration = new Configuration({
    apiKey: import.meta.env.OPENAI_API_KEY
})
const openai = new OpenAIApi(configuration)

export default async function (req, res) {
    if (!configuration.apiKey) {
        res.status(500).json({
            error: {
                message: 'OpenAI API key not configured, please follow instructions in README.md'
            }
        })
        return
    }

    const animal = req.body.animal || ''
    if (animal.trim().length === 0) {
        res.status(400).json({
            error: {
                message: 'Please enter a valid animal'
            }
        })
        return
    }

    try {
        const completion = await openai.createCompletion({
            model: 'text-davinci-003',
            prompt: generatePrompt(animal),
            temperature: 0.6
        })
        res.status(200).json({ result: completion.data.choices[0].text })
    } catch (error) {
        if (error.response) {
            console.error(error.response.status, error.response.data)
            res.status(error.response.status).json(error.response.data)
        } else {
            console.error(`Error with OpenAI API request: ${error.message}`)
            res.status(500).json({
                error: {
                    message: 'An error occurred during your request.'
                }
            })
        }
    }
}

function generatePrompt(animal) {
    const capitalizedAnimal = animal[0].toUpperCase() + animal.slice(1).toLowerCase()
    return `Suggest three names for an animal that is a superhero.
  
  Animal: Cat
  Names: Captain Sharpclaw, Agent Fluffball, The Incredible Feline
  Animal: Dog
  Names: Ruff the Protector, Wonder Canine, Sir Barks-a-Lot
  Animal: ${capitalizedAnimal}
  Names:`
}

前端代码(index.vue)

<script setup>
const animal = ref('')
const result = ref('')

const onSubmit = async () => {
    try {
        const response = await useFetch('/api/completion', {
            method: 'POST',
            body: JSON.stringify({ animal: animal.value }),
            headers: {
                'Content-Type': 'application/json'
            }
        })

        const data = await response.json()
        result.value = data.result
    } catch (error) {
        console.error(error)
    }
}
</script>

<template>
    <div>
        <form @submit.prevent="onSubmit">
            <label for="animal">Animal:</label>
            <input id="animal" v-model="animal" />
            <button type="submit">Submit</button>
        </form>
        <p v-if="result">Result: {{ result }}</p>
    </div>
</template>

出现的错误

  • 网络错误:POST http://localhost:3000/api/completion 500 (Internal Server Error)
  • 代码错误:TypeError: response.json is not a function

问题排查与修复方案

1. 后端500错误修复

Nuxt 3的服务器路由采用H3框架规范,不兼容Next.js的req/res回调模式,需要调整接口写法:

修改后的server/api/completion.js:

import { Configuration, OpenAIApi } from 'openai'
import { readBody, createError } from 'h3'
import { useRuntimeConfig } from '#imports'

export default defineEventHandler(async (event) => {
  // 用Nuxt官方方式获取环境变量
  const config = useRuntimeConfig()
  const configuration = new Configuration({
    apiKey: config.openaiApiKey
  })
  const openai = new OpenAIApi(configuration)

  if (!configuration.apiKey) {
    return createError({
      statusCode: 500,
      message: 'OpenAI API key未配置,请在.env中设置NUXT_OPENAI_API_KEY'
    })
  }

  // 用H3的readBody获取POST请求体
  const body = await readBody(event)
  const animal = body.animal || ''
  if (animal.trim().length === 0) {
    return createError({
      statusCode: 400,
      message: '请输入有效的动物名称'
    })
  }

  try {
    const completion = await openai.createCompletion({
      model: 'text-davinci-003',
      prompt: generatePrompt(animal),
      temperature: 0.6
    })
    return { result: completion.data.choices[0].text }
  } catch (error) {
    if (error.response) {
      console.error(error.response.status, error.response.data)
      return createError({
        statusCode: error.response.status,
        message: error.response.data.error?.message || 'OpenAI API请求失败'
      })
    } else {
      console.error(`OpenAI API请求错误: ${error.message}`)
      return createError({
        statusCode: 500,
        message: '请求过程中发生错误'
      })
    }
  }
})

function generatePrompt(animal) {
  const capitalizedAnimal = animal[0].toUpperCase() + animal.slice(1).toLowerCase()
  return `Suggest three names for an animal that is a superhero.
  
Animal: Cat
Names: Captain Sharpclaw, Agent Fluffball, The Incredible Feline
Animal: Dog
Names: Ruff the Protector, Wonder Canine, Sir Barks-a-Lot
Animal: ${capitalizedAnimal}
Names:`
}

2. 前端response.json()错误修复

Nuxt的useFetch返回的是封装后的响应对象,不是原生Response,无需调用.json()方法:

修改后的index.vue:

<script setup>
const animal = ref('')
const result = ref('')

const onSubmit = async () => {
  try {
    // useFetch返回包含data、error的响应对象,无需手动序列化body
    const { data, error } = await useFetch('/api/completion', {
      method: 'POST',
      body: { animal: animal.value },
      headers: {
        'Content-Type': 'application/json'
      }
    })

    if (error.value) {
      console.error(error.value)
      return
    }

    result.value = data.value?.result
  } catch (err) {
    console.error(err)
  }
}
</script>

<template>
  <div>
    <form @submit.prevent="onSubmit">
      <label for="animal">Animal:</label>
      <input id="animal" v-model="animal" />
      <button type="submit">Submit</button>
    </form>
    <p v-if="result">Result: {{ result }}</p>
  </div>
</template>

3. 额外环境配置

在项目根目录创建.env文件,添加OpenAI密钥(Nuxt会自动识别带NUXT_前缀的变量):

NUXT_OPENAI_API_KEY=你的OpenAI_API_KEY

内容的提问来源于stack exchange,提问作者Ricardo de Paula

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:20:12