Next.js API参数Undefined问题:请求报错及原因排查问询
问题描述
我有如下React组件:
import React, { useEffect } from "react"; import styles from "../styles/success.module.css"; import { useRouter } from "next/router"; import axios from "axios"; const Success = () => { const { query: { id }, } = useRouter(); useEffect(() => { getId(); }, [id]); const getId = () => { axios .put("api/getOrder", { id, }) .then((res) => { if (res.status === 200) { console.log(res.data.session); } }) .catch((err) => { console.log(err); }); }; return ( <div className={styles.success}> <h1>Thank you for your purchase {id}</h1> </div> ); }; export default Success;
预期是id加载完成后向API发起请求。
后端代码:
const stripe = require('stripe')(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY); export default async function handler(req, res) { const session = await stripe.checkout.sessions.retrieve(`${req.body.id}`) res.status(200).send({ nessage: '200', session }); res.status(500).send({ message: '500' }); }
问题:尝试将id动态传入session变量时,id为undefined,请求最终完成但控制台报错。
控制台报错信息:
error - StripeInvalidRequestError: No such checkout.session: undefined at Function.generate (C:\Users\user\Desktop\zigi\my-app\node_modules\stripe\lib\Error.js:40:16) at res.toJSON.then.StripeAPIError.message (C:\Users\user\Desktop\zigi\my-app\node_modules\stripe\lib\StripeResource.js:238:35) at processTicksAndRejections (node:internal/process/task_queues:96:5) { type: 'StripeInvalidRequestError', raw: { code: 'resource_missing', doc_url: 'https://stripe.com/docs/error-codes/resource-missing', message: 'No such checkout.session: undefined', request_log_url: 'https://dashboard.stripe.com/test/logs/req_ZrNElSd58VVHSA?t=1666409724', type: 'invalid_request_error', headers: { server: 'nginx', date: 'Sat, 22 Oct 2022 03:35:24 GMT', 'content-type': 'application/json', 'content-length': '311', connection: 'keep-alive', 'access-control-allow-credentials': 'true', 'access-control-allow-methods': 'GET, POST, HEAD, OPTIONS, DELETE', 'access-control-allow-origin': '*', 'access-control-expose-headers': 'Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required', 'access-control-max-age': '300', 'cache-control': 'no-cache, no-store', 'request-id': 'req_ZrNElSd58VVHSA', 'stripe-version': '2022-08-01', 'strict-transport-security': 'max-age=63072000; includeSubDomains; preload' }, statusCode: 404, requestId: 'req_ZrNElSd58VVHSA' }, rawType: 'invalid_request_error', code: 'resource_missing', doc_url: 'https://stripe.com/docs/error-codes/resource-missing', param: undefined, detail: undefined, headers: { server: 'nginx', date: 'Sat, 22 Oct 2022 03:35:24 GMT', 'content-type': 'application/json', 'content-length': '311', connection: 'keep-alive', 'access-control-allow-credentials': 'true', 'access-control-allow-methods': 'GET, POST, HEAD, OPTIONS, DELETE', 'access-control-allow-origin': '*', 'access-control-expose-headers': 'Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required', 'access-control-max-age': '300', 'cache-control': 'no-cache, no-store', 'request-id': 'req_ZrNElSd58VVHSA', 'stripe-version': '2022-08-01', 'strict-transport-security': 'max-age=63072000; includeSubDomains; preload' }, requestId: 'req_ZrNElSd58VVHSA', statusCode: 404, charge: undefined, decline_code: undefined, payment_intent: undefined, payment_method: undefined, payment_method_type: undefined, setup_intent: undefined, source: undefined, page: '/api/getOrder' } error - Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at new NodeError (node:internal/errors:372:5) at ServerResponse.setHeader (node:_http_outgoing:576:11) at Object.sendEtagResponse (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\send-payload\index.js:29:13) at sendData (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\api-utils\node.js:172:27) at ServerResponse.apiRes.send (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\api-utils\node.js:349:31) at handler (webpack-internal:///(api)/./pages/api/getOrder.js:12:21) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async Object.apiResolver (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\api-utils\node.js:366:9) at async DevServer.runApi (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\next-server.js:481:9) at async Object.fn (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\next-server.js:735:37) { code: 'ERR_HTTP_HEADERS_SENT', page: '/api/getOrder' } Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at new NodeError (node:internal/errors:372:5) at ServerResponse.setHeader (node:_http_outgoing:576:11) at NodeNextResponse.setHeader (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\base-http\node.js:61:19) at DevServer.renderError (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\base-server.js:1012:17) at DevServer.renderError (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\next-server.js:843:22) at DevServer.run (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\dev\next-dev-server.js:715:35) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async DevServer.handleRequest (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\base-server.js:285:20) { code: 'ERR_HTTP_HEADERS_SENT' }
错误分析与修复
1. 前端:路由query.id初始为undefined,提前触发请求
Next.js的useRouter中query.id初始状态是undefined,组件挂载时useEffect会因为id为undefined先执行一次getId,导致后端收到undefined的id。
修复:
在getId函数中新增判断,仅当id存在时才发起请求:
const getId = () => { if (!id) return; axios .put("/api/getOrder", { id }) .then((res) => { if (res.status === 200) { console.log(res.data.session); } }) .catch((err) => { console.log(err); }); };
2. 后端:未处理请求方法、错误捕获,且重复发送响应
- 未校验请求方法,可能接收非PUT请求导致错误
- 调用Stripe API时无错误捕获,失败会直接抛出异常
- 同时执行
res.status(200).send()和res.status(500).send(),导致重复发送响应,触发ERR_HTTP_HEADERS_SENT错误 - 存在拼写错误:
nessage应为message
修复后的后端代码:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); export default async function handler(req, res) { // 仅处理PUT请求 if (req.method !== 'PUT') { return res.status(405).send({ message: 'Method Not Allowed' }); } const { id } = req.body; // 校验id是否存在 if (!id) { return res.status(400).send({ message: 'Missing session ID' }); } try { const session = await stripe.checkout.sessions.retrieve(id); res.status(200).send({ message: '200', session }); } catch (err) { res.status(err.statusCode || 500).send({ message: err.message || 'Internal Server Error' }); } }
3. 额外注意事项
- Stripe密钥不应使用
NEXT_PUBLIC_前缀,该前缀会将密钥暴露给前端,改用普通环境变量(如STRIPE_SECRET_KEY)仅在后端使用 - 前端请求URL需添加斜杠:
/api/getOrder,避免路径解析错误
内容的提问来源于stack exchange,提问作者lying
相关产品推荐
相关产品推荐

