当前位置: 首页 > news >正文

Node.js 倒计时图片服务部署与 Nginx 反向代理实战总结

Node.js 倒计时图片服务部署与 Nginx 反向代理实战总结

场景描述

我们希望实现一个倒计时图片接口,供邮件等外部平台引用,如:

https://your-domain.com/countdown/countdown.png?end=2025-09-30T00:00:00

通过访问该链接生成实时倒计时 PNG 图,用于促销活动倒计时展示。


技术栈与组件

  • Node.js + Express
  • canvas 模块绘制 PNG
  • Nginx 反向代理(启用 HTTPS)
  • Let’s Encrypt 免费 SSL 证书
  • curl 用于调试

Node.js 服务核心逻辑

监听路径:

app.get('/countdown/countdown.png', (req, res) => { ... })

监听端口:

app.listen(7897, '0.0.0.0', () => {console.log(`Countdown image server running`);
});

遇到的问题

1. curl 本地访问正常,但通过 nginx 转发返回 404

  • http://127.0.0.1:7897/countdown/countdown.png?... → 正常返回图片
  • https://182.92.100.57/countdown/countdown.png?...404 Not Found(nginx)

问题排查过程

检查点 1:Node 是否监听公网(0.0.0.0

app.listen(7897, '0.0.0.0')

否则 nginx 无法连接 127.0.0.1:7897(仅限本地)


检查点 2:Nginx location 匹配是否命中

原配置示例(错误):

location /countdown/ {proxy_pass http://127.0.0.1:7897/countdown/;
}

此配置导致路径变成:

http://127.0.0.1:7897/countdown/countdown.png → 实际访问 /countdown/countdown/countdown.png ❌

最终解决方案

正确 Nginx 配置示例

location ^~ /countdown/ {proxy_pass http://127.0.0.1:7897;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# 可选:禁止缓存,确保每次图片实时更新add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}

关键点总结:

配置项是否正确说明
proxy_pass 末尾是否 没有加/countdown/确保拼接路径不重复
是否使用 ^~ 提前匹配避免被 / 的 Vue 路由兜底
Node 是否监听 0.0.0.0否则 nginx 无法访问
Node 路由是否正好是 /countdown/countdown.png保证路径一致
是否 reload 了 nginx修改配置后记得运行:nginx -t && nginx -s reload

成功效果

访问:

https://your-domain.com/countdown/countdown.png?end=2025-09-30T00:00:00

返回状态码:

200 OK
Content-Type: image/png

可嵌入邮箱、网页、推广活动页面等使用。


优化

功能说明
支持中文字体registerFont() 引入字体解决中文显示
可配置颜色 / 样式支持 query 参数自定义文字颜色、背景等
支持透明背景 / GIF 动画使用 canvas+GIFEncoder 生成动态图
域名绑定innorapidzs.cn 替代 IP,便于引用

测试命令

curl -v "https://your-domain.com/countdown/countdown.png?end=2025-09-30T00:00:00" --insecure

Node 服务快速启动脚本(如 pm2)

pm2 start countdown-server.js --name countdown-server
http://www.dtcms.com/a/294918.html

相关文章:

  • RCE随笔-奇技淫巧(2)
  • Android热修复实现方案深度分析
  • AI面试如何提升物流行业招聘效率?实战案例解析
  • ESP32-S3学习笔记<5>:SPI的应用
  • JDK 介绍与使用指南
  • CMake进阶:检查头文件存在性(check_include_file 和 check_include_fileCXX)
  • uniapp拦截返回事件
  • 应该切换到 NVMe 吗?
  • 学习 Pandas 库:Series 与 DataFrame 核心操作指南
  • c语言:预处理详解
  • CRMEB 单商户PRO多商户通用去版权教程
  • 二叉树解析
  • 51c大模型~合集158
  • RockyLinux 9.6 解决删除home后无法开机问题
  • 视觉BPE统一多模态理解-北大
  • Python+大模型 day03
  • 面试实战,问题四,介绍一下dubbo框架,如何回答
  • 河南萌新联赛2025第二场-河南农业大学
  • 解决uniapp 使用uview生成小程序包太大无法上传的问题
  • 亚马逊广告优化技巧:如何减少预算浪费
  • Tang Prime 20K板I2S输入输出例程
  • lumerical——光纤布拉格光栅(Fiber Bragg gratings)
  • AI驱动攻防升级,API安全走到关键档口
  • MyBatis整合SpringBoot终极指南
  • 设备维修记录可追溯:管理系统选型指南
  • ESP32-S3 小电视学习笔记2:Arduino开发环境搭建(垃圾)
  • PyTorch深度学习入门记录2
  • sql注入171到185
  • 使用Qemu模拟Arm处理器,运行Linux系统
  • 做了个震动APP