Next.js与Axios请求在Vercel生产环境超时问题求助
解决Vercel部署后请求加拿大政府JSON超时的问题
可能的原因
- 加拿大政府服务器可能将Vercel的云IP段识别为非信任来源(如爬虫、自动化请求),从而拒绝或延迟响应
- 请求缺少符合浏览器规范的
User-Agent头,被目标服务器的反爬机制拦截
解决方案
1. 为请求添加合法请求头并设置超时
修改你的/api/checkUpdates.tsx代码,模拟浏览器请求并设置超时,避免无限等待:
import type { NextApiRequest, NextApiResponse } from 'next' const url = 'https://www.canada.ca/content/dam/ircc/documents/json/ee_rounds_123_en.json' export default async (req: NextApiRequest, res: NextApiResponse) => { try { console.log('before fetch request') console.time('fetch') const data = await fetch(url, { headers: { // 模拟Chrome浏览器的User-Agent,绕过基础反爬拦截 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' }, // 设置10秒超时,避免请求挂起 signal: AbortSignal.timeout(10000) }) console.timeEnd('fetch') console.log('fetch success') if (!data.ok) { throw new Error(`请求失败,状态码:${data.status}`) } const json = await data.json(); console.log('success') const thisDraw = json.rounds[0] res.send(thisDraw?.drawNumber) } catch (error) { console.error('请求出错:', error) res.status(500).json({ error: '获取数据失败,请稍后重试' }) } }
2. 切换为Vercel Edge Functions(备选)
如果常规API路由仍被拦截,可尝试改为Edge Functions——Edge节点的IP更容易通过目标服务器的信任验证:
export const config = { runtime: 'edge', } const url = 'https://www.canada.ca/content/dam/ircc/documents/json/ee_rounds_123_en.json' export default async function handler(req: Request) { try { const data = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' }, signal: AbortSignal.timeout(10000) }) const json = await data.json(); const thisDraw = json.rounds[0] return new Response(JSON.stringify(thisDraw?.drawNumber), { status: 200 }) } catch (error) { return new Response(JSON.stringify({ error: '获取数据失败' }), { status: 500 }) } }
3. 增加数据缓存(推荐)
该JSON更新频率较低(移民邀请轮次不会实时变更),设置缓存可减少重复请求,避免触发目标服务器限制:
在常规API路由中添加缓存头:
// 缓存1小时,后续请求优先用缓存,同时后台自动更新 res.setHeader('Cache-Control', 's-maxage=3600, stale-while-revalidate') res.send(thisDraw?.drawNumber)
或使用Next.js的fetch缓存选项:
const data = await fetch(url, { headers: { 'User-Agent': '...' }, cache: 'force-cache', next: { revalidate: 3600 } // 每1小时重新验证一次数据 })
验证方法
- 部署修改后的代码后,查看Vercel函数日志,确认请求是否成功
- 用
vercel dev命令在本地模拟生产环境,排查网络差异问题
内容的提问来源于stack exchange,提问作者Flavio Silva
相关产品推荐
相关产品推荐

