如何配置Heroku服务器使用Fixie静态IP调用Clash of Clans API
问题
我用Axios调用Clash of Clans API,本地运行正常,但部署到Heroku后因为动态IP无法工作。我想通过Fixie静态IP让Heroku的API请求通过白名单IP访问,但服务器没使用这个静态IP——访问接口时页面失败,网络面板显示请求来自Heroku动态IP,必须配置白名单IP才行。
现有代码
require("dotenv").config(); const express = require("express"); const axios = require("axios"); const app = express(); const path = require('path'); const url = require('url'); const fixieUrl = url.parse(process.env.FIXIE_URL); const requestUrl = url.parse('https://api.clashofclans.com/v1/players/%232889v22uq'); // const URL = "https://api.clashofclans.com/v1/players/%232889v22uq"; const options = { headers: { Host: requestUrl.host, 'Proxy-Authorization': `Basic ${Buffer.from(fixieUrl.auth).toString('base64')}`, "Authorization": `Bearer ${process.env.API_TOKEN}` }, host: fixieUrl.hostname, port: fixieUrl.port, path: requestUrl.href, }; app.get("/api", (req, res) => { const clashReq = async () => { try { const response = await axios.get(requestUrl, options); const { name, townHallLevel, trophies, bestTrophies, builderHallLevel, league: { name: leagueName, iconUrls: { medium: mediumIcon }, }, legendStatistics: { previousSeason: { trophies: previousTrophies}, bestSeason: { trophies: bestSeasonTrophies}, currentSeason: { trophies: currentTrophies}, }, } = response.data; res.json({ name, townHallLevel, trophies, bestTrophies, builderHallLevel, leagueName, mediumIcon, previousTrophies, bestSeasonTrophies, currentTrophies } ); } catch (error) { console.log(error); } }; clashReq(); console.log(res.statusCode); }); if (process.env.NODE_ENV === "production") { app.use(express.static(path.join(__dirname, "/client/build"))); app.get("*", (req, res) => { res.sendFile(path.join(__dirname, "/client/build", "index.html")); }); } app.listen(process.env.PORT || 3001, () => { console.log(`Server running`); });
解决方案
问题出在你用了Node.js原生http.request的配置格式,但Axios有自己的代理规则,导致Fixie代理没生效。按以下方式修正代码:
- 把
requestUrl改成字符串格式,不要传url.parse后的对象给Axios - 用Axios专属的
proxy字段配置代理,不用手动设置Host和Proxy-Authorization头 - 简化异步逻辑,避免嵌套函数
- 错误处理时给客户端返回响应,防止请求挂起
修正后的代码:
require("dotenv").config(); const express = require("express"); const axios = require("axios"); const app = express(); const path = require('path'); const url = require('url'); const fixieUrl = url.parse(process.env.FIXIE_URL); const requestUrl = 'https://api.clashofclans.com/v1/players/%232889v22uq'; app.get("/api", async (req, res) => { try { const response = await axios.get(requestUrl, { headers: { "Authorization": `Bearer ${process.env.API_TOKEN}` }, proxy: { host: fixieUrl.hostname, port: fixieUrl.port, auth: fixieUrl.auth // Axios会自动生成Proxy-Authorization头 } }); const { name, townHallLevel, trophies, bestTrophies, builderHallLevel, league: { name: leagueName, iconUrls: { medium: mediumIcon }, }, legendStatistics: { previousSeason: { trophies: previousTrophies}, bestSeason: { trophies: bestSeasonTrophies}, currentSeason: { trophies: currentTrophies}, }, } = response.data; res.json({ name, townHallLevel, trophies, bestTrophies, builderHallLevel, leagueName, mediumIcon, previousTrophies, bestSeasonTrophies, currentTrophies } ); } catch (error) { console.error(error.response?.data || error.message); res.status(500).json({ error: '请求Clash of Clans API失败' }); } }); if (process.env.NODE_ENV === "production") { app.use(express.static(path.join(__dirname, "/client/build"))); app.get("*", (req, res) => { res.sendFile(path.join(__dirname, "/client/build", "index.html")); }); } app.listen(process.env.PORT || 3001, () => { console.log(`Server running`); });
额外注意:
- 确保Heroku已正确安装Fixie插件,
FIXIE_URL环境变量已自动配置 - 把Fixie提供的静态IP添加到Clash of Clans API的白名单中
内容的提问来源于stack exchange,提问作者k2g
相关产品推荐
相关产品推荐

