浏览器默认额外发起get /favicon.ico请求,需在swoole on('request')回调开头用$request->server['request_uri']判断并$response->end()快速响应,或启用enable_static_handler配合document_root托管静态文件。

为什么浏览器总发两次请求,其中一次是/favicon.ico
Chrome、Edge、Firefox 等主流浏览器在访问任意 URL 时,**默认会额外发起一个 GET /favicon.ico 请求**,不管你的 HTML 里有没有 <link rel="icon">。这不是 bug,是规范行为。如果你没处理它,Swoole 就会把这次请求当作普通路由走一遍 on('request') 回调,导致日志刷屏、响应延迟、甚至触发意外逻辑(比如误执行登录校验或数据库查询)。
直接在 on('request') 里拦截 /favicon.ico 最省事
不需要改 Nginx、不依赖静态文件服务,只要在回调开头加几行判断就行。关键点是:用 $request->server['request_uri'] 判断,不是 $request->server['path_info'](后者在某些 Swoole 版本下可能为空或不准)。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 必须放在
on('request')回调最前面,否则后续逻辑可能已执行 - 推荐用
$response->end()空响应,而不是$response->status(404)—— 404 会写入 access log,且无实际意义 - 如果项目真有 favicon.ico 文件,可以配合
enable_static_handler和document_root直接返回静态文件(见下一条)
$http->on('request', function ($request, $response) {
if ($request->server['request_uri'] === '/favicon.ico') {
$response->end();
return;
}
// 后续业务逻辑...
});
启用静态文件服务自动托管 favicon.ico
如果你的项目根目录(或 document_root 指定目录)下已有 favicon.ico 文件,开启 Swoole 内置静态资源处理更干净,不用手写拦截逻辑。
- 必须同时设置
enable_static_handler => true和document_root(路径需真实存在且可读) -
document_root值应为包含favicon.ico的**父目录**,比如文件在/var/www/html/favicon.ico,那document_root就设成/var/www/html - 注意权限:PHP 进程用户(如 www-data)需对该目录有读取权限,否则静默失败,仍会 fallback 到
on('request') - 不支持自定义 MIME 类型映射,
.ico默认识别为image/x-icon,一般够用
$http->set([
'enable_static_handler' => true,
'document_root' => __DIR__ . '/public',
]);
常见踩坑点:路径、缓存和调试盲区
你以为加了 <link rel="icon" href="/static/favicon.ico"> 就万事大吉?错。浏览器仍会发默认的 /favicon.ico 请求,除非你显式禁止(不推荐)。真正要盯住的是三件事:
- 检查浏览器开发者工具 Network 标签页,筛选
favicon.ico,看请求 URL 是什么、状态码是多少、响应头有没有Content-Type: image/x-icon - 硬刷新(Ctrl+Shift+R)会绕过缓存,暴露真实缺失问题;普通 F5 可能命中缓存,掩盖错误
- 别只信日志——
$response->end()后没报错不等于成功,要用 curl 或浏览器验证是否真没返回内容:curl -I http://127.0.0.1:9501/favicon.ico应返回HTTP/1.1 200 OK或HTTP/1.1 204 No Content - Windows 下路径分隔符用反斜杠可能出问题,统一用
__DIR__ . '/public'而不是__DIR__ . '\public'










