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

Heroku部署后axios重定向请求无法获取响应如何解决

问题原因
  • 进程崩溃直接原因:接口为async函数但未做全局异常捕获,只要axios请求、数据库操作抛出任何错误(比如目标站拦截、TLS握手失败、重定向逻辑异常),就会触发未捕获的Promise rejection,直接导致Node进程以状态码1退出,对应Heroku日志里的H13(连接无响应关闭)报错。
  • 拿不到重定向后内容的原因:Heroku环境下发的出站请求默认带axios/xxx的User-Agent标识,很容易被MaxPreps的反爬策略拦截;同时你没有显式配置axios的重定向次数、超时参数,部分Heroku dyno的网络环境下默认重定向逻辑会直接返回套接字对象,而非最终的HTML响应。
  • 隐性逻辑bug:你用全局displayGames数组存单次请求的临时数据,并发访问时会出现不同请求的数据串扰;另外数据库的findOne/save异步操作没有做等待处理,就直接返回响应、清空数组,很容易触发写入异常、偶发报错。
修复后可直接运行的代码

先在文件顶部按需引入依赖:

const https = require('https') // 用于TLS配置,出现握手报错时使用

接口代码替换为如下内容:

server.get('/displayGames', async (req, res) => {
  // 临时数据改为接口内部局部变量,彻底避免并发污染
  const displayGames = []
  try {
    const response = await axios.get('https://www.maxpreps.com/list/schedules_scores_redirect.aspx?gendersport=boys,football', {
      maxRedirects: 10, // 显式配置最多10次重定向,覆盖默认配置的异常问题
      timeout: 15000, // 设置15秒超时,避免请求长期挂死
      headers: {
        // 模拟真实浏览器请求头,绕过目标站基础反爬
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.5'
      },
      // 如果仍报TLS握手错误,放开下面这行注释
      // httpsAgent: new https.Agent({ minVersion: 'TLSv1.2' })
    })
    const html = response.data
    const $ = cheerio.load(html)
    const dbTasks = []

    $('.contest-box-item').find('.teams').each(function() {
      const winner = $(this).find('.winner').find('.name').text().trim()
      const loser = $(this).find('[data-result="3"]').find('.name').text().trim()
      const winningScore = $(this).find('.winner').find('.score').text().trim()
      const losingScore = $(this).find('[data-result="3"]').find('.score').text().trim()
      const winningTeamLogo = $(this).find('.winner').find('.image').attr('data-lazy-image')
      const losingTeamLogo = $(this).find('[data-result="3"]').find('.image').attr('data-lazy-image')

      if (winner && loser) {
        displayGames.push({winner, loser, winningScore, losingScore, winningTeamLogo, losingTeamLogo})
        // 数据库操作统一收集,单独捕获错误不影响主流程
        const task = displayGameModel.findOne({winnerName: winner, loserName: loser})
          .then(existRecord => {
            if (!existRecord) {
              return new displayGameModel({
                winnerName: winner,
                winnerScore: winningScore,
                winnerLogo: winningTeamLogo,
                loserName: loser,
                loserScore: losingScore,
                loserLogo: losingTeamLogo
              }).save()
            }
          })
          .catch(dbErr => console.error('单条数据写入失败:', dbErr))
        dbTasks.push(task)
      }
    })

    // 等待所有数据库操作执行完成,避免异步进程挂死
    await Promise.allSettled(dbTasks)
    res.json(displayGames)
  } catch (reqErr) {
    console.error('接口处理异常:', reqErr)
    // 异常时返回标准错误响应,不中断整个Node进程
    res.status(500).json({
      error: '数据获取失败,请稍后重试'
    })
  }
})
部署注意项
  • 部署前确认Heroku的环境变量里数据库连接地址配置正确,数据库IP白名单已放开Heroku dyno的出站IP段。
  • 如果后续出现目标站返回403/Cloudflare拦截,不要频繁请求,可适当增加请求缓存逻辑,避免IP被封禁。
  • 所有Node.js服务的async路由必须加异常捕获,未捕获的Promise rejection在新版Node.js里会直接终止进程,是线上服务崩溃的高频诱因。

内容的提问来源于stack exchange,提问作者Daniel Brannon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:33:39