PHP get_headers()仅URL使用字符串字面量时返回200 传变量返回204
问题原因
该问题并非缓存机制导致,核心原因是getTaskID()返回的任务ID字符串携带了肉眼不可见的冗余字符,导致拼接后的URL实际请求地址和硬编码的正确地址不一致,接口无法匹配到对应任务,因此返回204 No Content。
肉眼比对两个ID字符串看起来完全一致,是因为这些隐形字符不会被正常打印显示,常见的冗余字符包括:
- 接口返回ID时末尾附带的
\n、\r换行符 - 字符串首尾的空格、制表符
- 字符串开头携带的UTF-8 BOM头
- 接口响应中夹带的其他不可见控制字符
硬编码的ID是手动输入的纯合法字符串,不存在冗余字符,因此请求可以正常返回200状态码和对应响应头。
修复方案
- 先做字节级校验确认问题
不要仅靠肉眼判断字符串一致性,通过打印拼接后URL的长度、转义内容、字节编码,和硬编码的正确URL做对比,即可定位到冗余字符:$taskID = getTaskID(); $url = "https://example.com/api/v1/document/export/$taskID"; // 打印拼接URL的长度、urlencode转义结果、十六进制字节内容 var_dump(strlen($url), urlencode($url), bin2hex($url)); // 打印硬编码正确URL的对应信息做比对 $validUrl = "https://example.com/api/v1/document/export/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; var_dump(strlen($validUrl), urlencode($validUrl), bin2hex($validUrl)); - 对获取到的任务ID做清洗校验
拿到ID后先过滤首尾不可见字符,再校验格式合法性,之后再拼接URL:// 去除首尾所有空白、控制字符 $taskID = trim(getTaskID()); // 如果任务ID是标准UUID格式,增加正则校验,仅保留合法字符 if (!preg_match('/^[a-f0-9-]{36}$/i', $taskID)) { throw new \RuntimeException("获取到的任务ID格式不符合要求"); } $url = "https://example.com/api/v1/document/export/$taskID"; - 可选配置排除缓存干扰
如果完成上述操作后仍有异常,可以在请求上下文中增加禁用缓存的配置,排除PHP HTTP流缓存的影响:$opts = [ 'http' => [ 'header' => [ "Authorization: Basic " . base64_encode('myapikey'), 'Accept: */*', 'Cache-Control: no-cache, no-store' ], 'follow_location' => true ] ]; $context = stream_context_create($opts);
内容的提问来源于stack exchange,提问作者JG Trindade
相关产品推荐
相关产品推荐

