Axios HEAD请求莫名超时排查:跨机器表现差异及工具兼容问题
问题:Axios HEAD请求在部分机器超时,curl正常的排查方案
背景信息
我尝试用Axios发送HEAD请求,获取目标文件的Last-Modified响应头,目标文件地址:http://daten-hamburg.de/opendata/3d_stadtmodell_lod2/LoD2-DE_HH_2023-04-01.zip
使用的Axios重试配置和获取函数如下:
axiosRetry(axios, { retries: 10, retryDelay: axiosRetry.exponentialDelay, onRetry: (retryCount, error, requestConfig) => { log.warn(`Retry attempt #${retryCount} for ${requestConfig.url}`) }, }) export const getlastModified = async (url: string) => { try { const response = await axios.head(url, { timeout: 20000, }) // 20秒超时 const lastModified = response.headers['last-modified'] log.debug(response.headers) const date = new Date(lastModified) return date } catch (error) { console.error(`Error fetching headers: ${error}`) return undefined } }
两台机器的依赖版本完全一致:
"axios": "^1.7.7", "axios-retry": "^4.5.0",
异常现象
- 代码在一台机器上正常运行,但在另一台网络更快的机器上持续超时
- 两台机器执行
curl -I http://daten-hamburg.de/opendata/3d_stadtmodell_lod2/LoD2-DE_HH_2023-04-01.zip均能正常返回响应头 - 额外发现:curl可以下载该文件,但wget连接服务器时会挂起
排查步骤建议
1. 对比两台机器的HTTP请求细节
在两台机器上分别执行curl -v -I <目标URL>,对比输出的请求头、协商的HTTP版本、SSL/TLS版本,重点关注:
- Axios默认可能使用HTTP/2,而curl默认用HTTP/1.1,目标服务器可能对HTTP/2兼容性有问题
- 检查请求头中的
User-Agent,Axios的默认UA和curl不同,服务器可能对特定UA做了限流或拦截
2. 强制Axios使用HTTP/1.1
修改Axios配置,禁用HTTP/2,模拟curl的行为:
const http = require('http'); const https = require('https'); // 在请求中添加配置 const response = await axios.head(url, { timeout: 20000, httpAgent: new http.Agent({ keepAlive: false }), httpsAgent: new https.Agent({ keepAlive: false }), maxVersion: 'http/1.1' })
3. 模拟curl的请求头
把curl的请求头完全复制到Axios中,尤其是User-Agent和Accept字段:
const response = await axios.head(url, { timeout: 20000, headers: { 'User-Agent': 'curl/7.81.0', // 替换成你机器上curl的实际UA 'Accept': '*/*' } })
4. 检查机器网络环境差异
- 检查防火墙、代理设置:网络更快的机器可能走了代理,而代理对HEAD请求处理有问题
- 对比DNS解析结果:用
nslookup daten-hamburg.de查看两台机器解析到的IP,可能其中一台指向了不稳定的节点 - 抓包分析TCP连接:用
tcpdump或Wireshark抓取超时机器的网络包,看TCP握手是否正常、是否有数据包丢失
5. 替换请求方法测试
尝试用GET请求替代HEAD,只获取响应头(不下载完整内容):
const response = await axios.get(url, { timeout: 20000, headers: { 'Range': 'bytes=0-0' }, // 仅请求第一个字节 responseType: 'stream' }) // 同样提取response.headers['last-modified']
6. 排查wget挂起的原因
在超时机器上执行wget -d <目标URL>,查看调试输出,重点看:
- wget使用的HTTP版本、请求头
- 是卡在TCP连接阶段,还是等待响应阶段
- 这大概率和Axios的问题同源,比如服务器对HTTP/1.1持久连接的处理存在bug
内容的提问来源于stack exchange,提问作者pcace
相关产品推荐
相关产品推荐

