workerman 中 $_server['http_host'] 未定义是因为其 http 解析器不初始化完整 $_server 数组;应通过 $http->host() 或 $http->header('host') 获取 host 头。

Workerman 的 HTTP_HOST 不是自动注入的全局变量,直接读 $_SERVER['HTTP_HOST'] 会报 Undefined index: HTTP_HOST —— 因为 Workerman 的 HTTP 协议解析器不默认填充全部 CGI 环境变量,$_SERVER 是空的或极简的。
为什么 $_SERVER 里没有 HTTP_HOST?
Workerman 的 Worker 类(尤其是 WebServer 或直接 new Worker('http://0.0.0.0:8080'))使用自研 HTTP 解析器,不走 PHP-FPM 的 CGI 流程,所以不会初始化完整的 $_SERVER 数组。常见被误用的键还有 REQUEST_URI、QUERY_STRING、HTTP_REFERER 等。
你看到的错误通常出现在:
- 直接在
onMessage里写$_SERVER['HTTP_HOST'] - 搬了传统 Apache/Nginx 下的 PHP 路由逻辑过来,没适配 Workerman 的请求对象
- 用了框架封装但没搞清底层——比如 ThinkPHP 的 Workerman 扩展若未开启 HTTP 上下文代理,
$_SERVER仍是空的
正确获取 Host 和请求信息的方式
Workerman 的 HTTP 请求数据全在 $http 对象(即 $connection 参数)上,它是 Workerman\Protocols\Http\Request 实例。
你应该这样取:
-
$http->host()→ 返回 Host 头的值(如example.com:8080) -
$http->header('host')→ 手动取原始 Host 头(小写键名) -
$http->uri()→ 替代$_SERVER['REQUEST_URI'] -
$http->method()→ 替代$_SERVER['REQUEST_METHOD'] -
$http->get()/$http->post()→ 替代$_GET/$_POST
示例:
use Workerman\Protocols\Http\Request;
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function($connection, $http) {
// ✅ 正确
$host = $http->host();
$path = $http->uri();
// ❌ 错误(会触发 Undefined index)
// $host = $_SERVER['HTTP_HOST'];
$connection->send("Host: {$host}, Path: {$path}");
};
如果必须兼容旧代码(比如引入第三方库依赖 $_SERVER)
可以手动补全关键 $_SERVER 字段,但仅限必要项,且要在 onMessage 开头做:
- 只设置你真正在用的键,避免污染全局
- 优先用
$http->header()取值,再赋给$_SERVER,别硬编码 - 注意 Host 头可能带端口,需按需截取(
parse_url($host, PHP_URL_HOST))
示例:
$worker->onMessage = function($connection, $http) {
$_SERVER['HTTP_HOST'] = $http->header('host') ?: 'localhost';
$_SERVER['REQUEST_URI'] = $http->uri();
$_SERVER['REQUEST_METHOD'] = $http->method();
// 后续可安全调用依赖 $_SERVER 的旧逻辑
require 'legacy_router.php';
};
最易被忽略的是:很多人在 onConnect 或 onWorkerStart 里试图读 $_SERVER,那连请求上下文都没有,必然为空——Host 只存在于 HTTP 请求头里,必须在 onMessage 中、有 $http 对象时才能取。











