Hao 博客自带的音乐 API 服务早已停摆,播放器加载不出歌曲。这篇文章完整记录了从放弃 Vercel 方案、改用国内云服务器,到用 Docker 部署 Meting API、Nginx 反向代理绑定域名,再到修复浏览器混合内容拦截的全过程与踩坑细节。

目录

📌 第一章:背景与起因

  • 起因:Hao 博客默认的音乐 API api.i-meto.com 已停止服务,导致博客播放器无法加载音乐。
  • 目标:自建一个部署在国内、稳定支持 HTTPS、不受版权 IP 限制的专属 Meting API。
  • 环境准备:阿里云 ECS 服务器、宝塔 Linux 面板、FinalShell 终端连接工具。

🚧 第二章:初期尝试(Vercel)与放弃

  • 尝试方案:在 GitHub 上 Fork 了 chuyegzs/Meting-UI-API 并导入 Vercel 部署。
  • 踩坑记录:
    1. 网络阻断:Vercel 默认分配的 *.vercel.app 域名在国内被 DNS 污染,无法访问,必须绑定自定义域名。
    2. IP 限制:即使把 Vercel 的函数区域改到香港(hkg1),但节点依然在海外,请求 QQ 音乐等国内版权严格的音源时,无法获取真实音频地址和歌词。
  • 最终结论:放弃 Vercel,拥抱国内云服务器。

🐳 第三章:宝塔 + Docker 部署实战(核心)

3.1 解决 Docker 拉取镜像超时

  • 报错:docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded...
  • 原因:国内服务器直接连接 Docker 官方仓库极慢,且阿里云旧版加速器已失效。
  • 测试失败的源:
    • docker.xuanyuan.me(提示免费节点繁忙)
    • docker.m.daocloud.io(提示不在白名单)
    • docker.1ms.run(下载到一半卡在 Waiting)
  • ✅ 最终成功方案:使用 dockerproxy.net 代理源直接拉取。
docker pull dockerproxy.net/intemd/meting-api:latest

3.2 给镜像打标签并启动容器

  • 打标签:因为是从代理源拉的,必须重命名让 Docker 识别。
docker tag dockerproxy.net/intemd/meting-api:latest intemd/meting-api:latest
  • 启动容器:映射宿主机 25000 端口到容器内部的 3000 端口。
docker run -d --name meting -p 25000:3000 intemd/meting-api:latest
  • 验证:执行 docker ps,看到状态为 Up,且端口映射为 0.0.0.0:25000->3000/tcp 即成功。

3.3 清理与防坑提示

  • 如果在下载中断或重试后想清理垃圾,可以使用 docker system prune。
  • ⚠️ 避坑:千万不要随意执行 docker image prune -a -f,这会把还没启动的镜像当成垃圾直接删掉,导致前功尽弃。

3.4 穿透防火墙(极其容易被忽略)

  • 宝塔放行:宝塔面板 → 安全 → 放行 TCP 25000 端口。
  • 阿里云放行:阿里云控制台 → 安全组 → 入方向 → 手动添加 TCP 25000 端口(授权对象 0.0.0.0/0)。这是必做步骤,否则外网绝对打不开。

🌐 第四章:绑定域名与反向代理

  1. 添加站点:在宝塔面板新建站点 api-meting-music.jikai666.top。
  2. 反向代理:在该站点的设置中,添加反向代理,目标 URL 指向 http://127.0.0.1:25000。
  3. 申请 SSL:在 SSL 选项卡中,使用 Let's Encrypt 申请免费证书,并开启右上角的"强制 HTTPS"。
  4. 此时,浏览器访问 https://api-meting-music.jikai666.top/ 能看到 API 的测试主页。

💥 第五章:终极难题 —— 混合内容(Mixed Content)拦截

5.1 现象与报错

  • 博客本身是 https://,但播放器无法播放、歌词不显示。
  • 按 F12 查看控制台,出现红字报错:Mixed Content: The page at 'https://halo.jikai666.top/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://api-meting-music.jikai666.top/api?...'
  • 原因:后端的 Meting API 在生成歌词或音频链接时,写死了 http:// 协议。浏览器为了安全,直接拦截了这种请求。

5.2 走过的弯路(失败的尝试)

  1. 前端 JS 覆盖变量:在 Halo 后台注入 window.meting_api = 'https://...',无效。因为前端插件内部写死了逻辑。
  2. 前端拦截 Fetch/XHR:注入代码拦截并替换 http:// 为 https://,无效。因为拦截代码没跑过播放器底层的加载逻辑。
  3. 更换插件:安装官方 APlayer 插件,依然被拦截。
  4. 传递协议头:在 Nginx 反代中加入 proxy_set_header X-Forwarded-Proto $scheme;,后端顽固不化,依然返回 http://。

5.3 🎯 终极必杀技:Nginx sub_filter 暴力替换

既然后端不听话,我们就在 Nginx 这一层,把后端返回给浏览器的所有 http:// 强行替换成 https://。

⚠️ 为什么之前的替换失败?

因为 Nginx 默认开启了 gzip 压缩。数据传回来是乱码,sub_filter 找不到 http:// 文本。

✅ 完整且生效的 Nginx 配置(位于宝塔反代文件中):

#PROXY-START/

location ^~ /
{
    proxy_pass http://127.0.0.1:25000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_http_version 1.1;

    # 1. 告诉后端这是 HTTPS 访问(虽然它不认,但按规范加上)
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Port 443;

    # 2. 👇 核心大招:强制解压、强制替换、覆盖所有文件类型 👇
    gzip off; # 必须关闭压缩,否则无法查找文本
    proxy_set_header Accept-Encoding "";
    sub_filter_types *; # 搜索所有内容类型(包含 JSON 接口数据)
    sub_filter 'http://api-meting-music.jikai666.top' 'https://api-meting-music.jikai666.top'; # 替换规则
    sub_filter_once off; # 替换所有匹配项,不要只替换第一个
    # 👆 核心大招结束 👆

    add_header X-Cache $upstream_cache_status;

    set $static_filezgowjLzS 0;
    if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" )
    {
        set $static_filezgowjLzS 1;
        expires 1m;
    }
    if ( $static_filezgowjLzS = 0 )
    {
        add_header Cache-Control no-cache;
    }
}

#PROXY-END/

5.4 验证结果

重启 Nginx 后,测试页面 https://api-meting-music.jikai666.top/test 里的所有请求成功变绿(https://),博客前端无需任何修改,音乐与歌词完美播放。

💡 第六章:总结与避坑建议

  1. 国内建站首选国内服务器:QQ 音乐、网易云等接口对海外 IP 极其敏感,Vercel 等海外平台不适合做国内音乐解析。
  2. 端口放行双管齐下:宝塔放行了,必须去阿里云/腾讯云控制台的"安全组"再次放行。
  3. Nginx 协议替换必杀技:以后遇到任何"HTTPS 页面请求 HTTP 资源"被拦截的问题,记住三板斧:
    • gzip off;
    • proxy_set_header Accept-Encoding "";
    • sub_filter + sub_filter_types *;