request模块与curl处理302重定向Location含转义字符无法跳转问题
问题根因
你遇到的问题本质是服务端实现不符合HTTP规范:返回的Location响应头被错误做了两层编码,先做了HTML实体编码(比如:转为:、&转为&),又做了URL编码(比如;转为%3B)。Chrome处理响应头时会额外执行HTML实体解码,所以可以正常跳转,但curl和request模块默认仅处理标准URL编码,不会主动解码HTML实体,因此无法识别重定向地址。
curl和request本身没有内置的开箱即用配置项来自动处理这种不符合规范的编码,只能通过少量自定义逻辑修正后使用原生跳转能力。
解决方案
Node.js request 模块
无需自己实现完整跳转逻辑,仅需将followRedirect从布尔值改为回调函数,在跳转前修正Location地址即可:
const request = require('request'); request({ method: "POST", url: "https://balbalab.com", headers: { 'Cookie': "XXXXX", 'Accept-Encoding': 'gzip, deflate, fr', 'Accept-Language': 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/55.0.2883.87 Chrome/55.0.2883.87 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', "Pragma": "no-cache" }, gzip: true, form: formFields, followAllRedirects: true, // 替换原有followRedirect: true为以下回调 followRedirect: function(res) { if (!res.headers.location) return false; // 解码HTML实体 let fixedLocation = res.headers.location .replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(dec)) .replace(/&/g, '&'); // 解码多余的URL编码层 fixedLocation = decodeURIComponent(fixedLocation); // 替换响应头的Location为修正后的地址 res.headers.location = fixedLocation; return true; } }, function(err, res, body) { // 原有业务逻辑不变 })
该方案仅解码服务端额外添加的编码层,不会影响参数本身需要保留的正常编码。
curl
curl无内置对应配置,可通过两步请求实现自动跳转:先获取原始Location头,解码后再发起跳转请求:
# 1. 发起POST请求获取原始Location raw_location=$(curl -s -o /dev/null -w "%{redirect_url}" -X POST "https://url1.url1.com" \ -H 'Accept-Encoding: gzip, deflate, fr' \ -H 'Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' \ -H 'Upgrade-Insecure-Requests: 1' \ -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/55.0.2883.87 Chrome/55.0.2883.87 Safari/537.36' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \ -H 'Cache-Control: no-cache' \ -H 'Connection: keep-alive' \ -H "Pragma: no-cache" \ -d 'xx=ff') # 2. 解码Location decoded_location=$(echo "$raw_location" | python3 -c "import html, urllib.parse, sys; print(urllib.parse.unquote(html.unescape(sys.stdin.read().strip())))") # 3. 发起跳转请求 curl -L "$decoded_location" [你的其他请求参数]
补充说明
如果有权限调整服务端逻辑,最优方案是修复服务端的响应头生成逻辑:HTTP响应头的Location值不需要做HTML实体编码,仅HTML页面内的链接需要做实体编码,修复后curl和request的原生自动跳转能力即可正常使用。
内容的提问来源于stack exchange,提问作者Daphoque
相关产品推荐
相关产品推荐

