问题根源是系统级代理劫持https请求,导致composer获取到301跳转或html页面而非json响应;需关闭代理或精确配置代理规则、清除环境变量、导入代理根证书、在ci/cd中显式隔离网络环境。

curl -I 测镜像返回 301 或 HTML 页面,说明代理在中间改响应
这不是 Composer 配置问题,而是系统级代理(如 Clash、Surge、小火箭)把 HTTPS 请求劫持并重定向了。Composer 发出的请求被代理拦截后,返回的是代理的人机验证页或跳转页,而不是真实的 packages.json,导致解析失败。
典型现象:curl -I https://mirrors.aliyun.com/composer/packages.json 返回 HTTP/1.1 301 Moved Permanently 或 Content-Type: text/html;composer install -vvv 日志里出现 Could not parse response 或卡在 Loading repository 不动。
- 先关掉所有代理软件,再跑一次
curl -I https://mirrors.aliyun.com/composer/packages.json—— 必须看到HTTP/2 200或HTTP/1.1 200 OK且Content-Type: application/json - 如果关代理后正常,说明问题定位准确;此时不要“绕过 SSL”或换源,直接修代理规则
- Clash 用户:检查
rules段是否写了- DOMAIN-SUFFIX,aliyun.com,PROXY这类泛匹配——它会把镜像域名也送进代理链;应改为精确域名放行:- DOMAIN,mirrors.aliyun.com,DIRECT - Surge 用户:确认
[Rule]里有DOMAIN,mirrors.aliyun.com,DIRECT,避免走FINAL或Proxy策略
代理开着但 Composer 仍直连 packagist.org,说明全局配置被忽略
代理软件常会设置系统级环境变量(如 http_proxy、https_proxy),而 Composer 在检测到这些变量时,会自动禁用自定义镜像源——这是它的安全策略:防止敏感包经不可信代理中转。
表现是:composer config -g repositories.packagist.org 显示已配好,composer diagnose 却显示 Repo packagist.org: https://packagist.org,且 composer install -vvv 日志第一行就是 Downloading https://packagist.org/...。
- 运行
env | grep -i proxy查看是否设置了http_proxy或https_proxy - 临时清除:执行
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY,再试composer install - 若必须保留代理(比如公司内网),可在命令前加
no_proxy=mirrors.aliyun.com composer install,让 Composer 对镜像域名跳过代理 - 注意大小写:
NO_PROXY和no_proxy都要设,某些 shell 只认其中一个
代理未关闭但 curl 正常,Composer 却报 SSL certificate problem
这通常是代理启用了 HTTPS 解密(MITM 模式),用自己的根证书签发了镜像站证书,而 PHP/cURL 没信任该证书。和镜像站证书过期无关,是本地代理证书未导入信任链。
现象:curl -I https://mirrors.aliyun.com/composer/packages.json 成功,但 composer install 报 SSL certificate problem: unable to get local issuer certificate。
- 确认代理是否开启 HTTPS 解密:Clash 的
tls-decision: strict、Surge 的Enable TLS Interception开关 - 导出代理的根证书(如 Clash 的
ca.crt),然后告诉 PHP 使用它:export SSL_CERT_FILE=/path/to/ca.crt - 或全局指定 CA bundle:
composer config -g cafile /path/to/ca.crt - 不推荐用
COMPOSER_DISABLE_TLS=1绕过——它会让整个连接降级为 HTTP,风险远高于证书问题本身
CI/CD 中代理干扰更隐蔽,需显式隔离网络环境
Docker 构建或 GitHub Actions 里,代理变量可能来自基础镜像或 runner 环境,且不易察觉。Composer 表现为偶发失败、有时快有时慢、不同节点行为不一致。
- GitHub Actions:在
steps中加env: { http_proxy: '', https_proxy: '' }彻底清空 - Dockerfile:构建阶段前插入
ENV http_proxy="" https_proxy="" no_proxy="*",避免继承 base image 的代理设置 - GitLab CI:用
variables: { HTTP_PROXY: null, HTTPS_PROXY: null }显式覆盖 - 关键动作:每次构建前加一行
curl -I https://mirrors.aliyun.com/composer/packages.json || exit 1,作为网络就绪检查
代理层的问题从来不在 Composer 配置本身,而在于它和系统网络栈之间的边界是否干净。最容易被忽略的是:你以为关了图形界面代理,但终端里的环境变量还在;你以为配了镜像,但 no_proxy 漏写了 mirrors.aliyun.com;你以为在 CI 里清了变量,却没意识到 runner 自带的 HTTP_PROXY 是只读的。处理这类问题,优先验证底层网络通路,再谈 Composer 配置。











