Swoole 4 协程 HTTP 客户端默认不自动处理重定向,需手动实现并防护循环跳转;应限制跳转次数、去重已访问 URL、校验 Location 合法性。

Swoole 4 的协程 Swoole\Coroutine\Http\Client 默认**不自动处理重定向**,也不会自动跟随 301/302 响应跳转。也就是说,它本身不内置重定向逻辑,自然也就没有“默认循环重定向”风险——但这也意味着:如果你自己实现重定向逻辑,就需主动防护循环跳转。
为什么需要手动防护循环重定向
当你收到 301 或 302 响应时,服务端会在 Location 头中返回跳转地址。若你用 $client->get($location) 递归/循环发起新请求,而目标站点存在跳转环(如 A → B → A),或恶意响应伪造了循环 Location,就可能陷入无限请求,耗尽协程栈、内存或连接数。
安全实现重定向的 3 个关键控制点
以下是在协程中安全实现最多 N 次跳转的推荐做法(以最多 5 次为例):
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 显式计数器 + 递归深度限制:在每次重定向调用前检查已跳转次数,达到阈值(如 5)直接终止,返回原始响应或抛异常
-
记录已访问 URL(去重):用
spl_object_hash($client)或协程上下文存储一个简单数组,保存已请求过的host:port/path(注意规范化 URL,如去掉末尾/、统一协议、忽略 query 参数差异等),发现重复立即中断 -
校验 Location 头合法性:确保
Location是绝对 URL(含http://或https://),且域名不超出白名单范围(如只允许跳转到同域或指定 CDN 域名),避免 SSRF 或跳转到不可信第三方
代码示例:带循环防护的重定向封装
以下是一个简洁可复用的封装函数:
(注意:需配合set(['timeout' => 10]) 防止单次跳转卡死)function safeGetWithRedirect($host, $path, $maxRedirect = 5, $visited = []) {<br> $client = new Swoole\Coroutine\Http\Client($host, 80);<br> $client->set(['timeout' => 10]);<br> $client->get($path);<br> if ($client->statusCode >= 300 && $client->statusCode < 400 && $client->headers['location'] && $maxRedirect > 0) {<br> $location = $client->headers['location'];<br> $parsed = parse_url($location);<br> if (!$parsed || !isset($parsed['scheme'], $parsed['host'])) {<br> return ['err' => 'invalid_location', 'body' => $client->body];<br> }<br> $key = $parsed['host'] . ':' . ($parsed['port'] ?? '80') . $parsed['path'];<br> if (in_array($key, $visited)) {<br> return ['err' => 'redirect_loop', 'body' => $client->body];<br> }<br> $visited[] = $key;<br> return safeGetWithRedirect($parsed['host'], $parsed['path'] . ($parsed['query'] ? '?' . $parsed['query'] : ''), $maxRedirect - 1, $visited);<br> }<br> return [<br> 'status' => $client->statusCode,<br> 'headers' => $client->headers,<br> 'body' => $client->body<br> ];<br>}
额外建议:生产环境加固项
- 对
Location中的域名做 DNS 缓存或白名单校验,防止跳转到内网地址(防 SSRF) - 设置全局最大重定向总耗时(例如所有跳转加起来不超过 8 秒),避免慢速跳转链拖垮协程
- 记录重定向链路日志(如
trace_id → A → B → C),便于排查异常跳转行为 - 禁用非必要协议跳转(如拒绝
ftp://、javascript:等非法 scheme)

















