使用HTML+Express调用ChatGPT API时遭遇API密钥未提供错误求助
排查ChatGPT API调用时的API密钥缺失错误
你遇到的错误核心原因是前端直接请求OpenAI API时未携带认证信息,同时代码里还有几处关键逻辑错误,具体问题和修复方案如下:
核心问题分析
- 前端直接请求OpenAI API:浏览器端直接调用OpenAI API时,既没有在请求头里携带
Authorization: Bearer YOUR_KEY,还会触发跨域(CORS)问题,更重要的是直接暴露API密钥会带来安全风险。 - 后端路由配置错误:你把OpenAI的API地址
https://api.openai.com/v1/chat/completions当成了Express的路由路径,这完全不符合后端路由的配置逻辑,后端应该定义自己的接口路径,再由后端去调用OpenAI API。 - getResponse函数无返回值:函数里调用了
openai.completions.create但没有返回结果,导致后续response.choices[0].text会报错。 - API接口与模型不匹配:前端请求的是
chat/completions(聊天模型接口),但后端用的是completions.create(文本补全接口),两者不对应。
修复步骤及完整代码
1. 修正后端代码(index.js)
- 添加
express.json()中间件解析请求体 - 自定义后端路由,比如
/api/get-completion - 完善
getResponse函数的返回逻辑,根据需求选择正确的API接口(示例用文本补全接口,若需聊天模型可改用openai.chat.completions.create) - 确保dotenv正确加载环境变量
import { createRequire } from "module"; import { config } from "dotenv"; config(); import OpenAI from "openai"; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); const require = createRequire(import.meta.url); const express = require("express"); const app = express(); // 解析JSON请求体 app.use(express.json()); // 托管静态文件 app.use("/", express.static("public")); const getResponse = async (text) => { // 文本补全接口(对应text-davinci-003) const response = await openai.completions.create({ model: "text-davinci-003", prompt: text, temperature: 1, max_tokens: 256, }); // 返回响应结果 return response; }; // 自定义后端路由 app.post("/api/get-completion", async (req, res) => { if (!req.body.promptText) { return res.status(400).send("Bad Request: Missing prompt text"); } try { const response = await getResponse(req.body.promptText); res.status(200).send(response.choices[0].text.trim()); } catch (error) { console.error("OpenAI API Error:", error); res.status(500).send("Internal Server Error"); } }); app.listen(3000, () => { console.log("Server running on http://localhost:3000"); });
2. 修正前端代码(index.html)
- 修改fetch地址为后端的自定义路由
/api/get-completion - 改用JSON格式发送请求(替代FormData,更适配后端的json解析)
- 处理响应时正确展示结果
<textarea id="text-prompt" name="promptText" placeholder="type in prompt here" style="width: 300px; height: 150px;"></textarea> <button type="button" id="btn-upload">Upload</button> <textarea id="resultsText" placeholder="Answer goes in here" style="width: 300px; height: 150px;"></textarea> <script> const textPrompt = document.getElementById("text-prompt"); const btnUpload = document.getElementById("btn-upload"); const resultText = document.getElementById("resultsText"); btnUpload.addEventListener("click", () => { const promptText = textPrompt.value.trim(); if (!promptText) { resultText.value = "Please enter a prompt first."; return; } fetch("/api/get-completion", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ promptText }), }) .then(response => { if (!response.ok) throw new Error("Request failed"); return response.text(); }) .then(promptAnswer => { resultText.value = promptAnswer; }) .catch(error => { console.error(error); resultText.value = "Error occurred while fetching response."; }); }); </script>
3. 环境变量配置
确保项目根目录下有.env文件,内容为:
OPENAI_API_KEY=你的OpenAI API密钥
额外注意事项
- 永远不要在前端代码里直接写API密钥,必须通过后端中转调用,避免密钥泄露
- 如果需要使用聊天模型(如gpt-3.5-turbo),需修改
getResponse函数为openai.chat.completions.create,并调整请求参数格式 - 启动项目前确保安装了所有依赖:
npm install express dotenv openai
内容的提问来源于stack exchange,提问作者juanc
相关产品推荐
相关产品推荐

