Skip to content

[BUG] getUri()->getHost() returns server IP instead of domain when using swoole 6.2.0 (server_addr priority issue) #7744

@beyond-infra

Description

@beyond-infra

Bug Report

Swoole version

6.2.0

Hyperf version

hyperf/http-message ~3.1.0 (tested on v3.1.65)

Bug description

Swoole 6.2.0 introduced a new server_addr field in $swooleRequest->server (the server's local IP address). This breaks getUriFromGlobals() in Hyperf\HttpMessage\Server\Request, because server_addr has higher priority than header['host'] in the fallback chain.

In src/Server/Request.php, the current logic is:

if (isset($server['http_host'])) {
    // ...
} elseif (isset($server['server_name'])) {
    // ...
} elseif (isset($server['server_addr'])) {      // ← swoole 6.2.0 hits here
    $uri = $uri->withHost($server['server_addr']); // value: "127.0.0.1" or local IP
} elseif (isset($header['host'])) {               // ← never reached anymore
    // ...
}

Before swoole 6.2.0, server_addr was never set by swoole, so the code fell through to header['host'] which contains the correct domain name (e.g. ai-service.example.com). Now $request->getUri()->getHost() returns the server's local IP instead of the requested domain.

Swoole 6.2.0 change

The relevant new code in swoole 6.2.0 (ext-src/swoole_http_server.cc):

void swoole_http_server_populate_ip_and_port(...) {
    // NEW in 6.2.0 - sets $request->server['server_addr']
    http_server_add_server_array(ht, SW_ZSTR_KNOWN(SW_ZEND_STR_SERVER_ADDR), server->get_local_addr(conn));
    http_server_add_server_array(ht, SW_ZSTR_KNOWN(SW_ZEND_STR_REMOTE_ADDR), server->get_remote_addr(conn));
}

This field did not exist in swoole 5.x or 6.0.0.

How to reproduce

  1. Run Hyperf with swoole 6.2.0
  2. Send a request with Host: example.com header
  3. Check $request->getUri()->getHost() — it returns the server's local IP (e.g. 127.0.0.1) instead of example.com

Evidence from production logs

Normal (swoole 5.x)server_addr absent, host resolved from header['host']:

{
  "uri_host": "ai-service.example.com",
  "header_host": "ai-service.example.com",
  "server": {
    "server_port": 9501,
    "remote_addr": "127.0.0.1"
  }
}

Broken (swoole 6.2.0)server_addr present, overrides header['host']:

{
  "uri_host": "127.0.0.1",
  "header_host": "ai-service.example.com",
  "server": {
    "server_port": 9501,
    "server_addr": "127.0.0.1",
    "remote_addr": "127.0.0.1"
  }
}

Note: header['host'] is correct in both cases, but getUri()->getHost() is wrong in swoole 6.2.0.

Suggested fix

The header['host'] (HTTP Host header from the client) should take priority over server_addr (server's own IP), since server_addr represents the server's local address, not the requested domain. This aligns with how PHP-FPM and nginx handle the same situation — $_SERVER['HTTP_HOST'] always takes precedence.

if (isset($server['http_host'])) {
    // ...
} elseif (isset($header['host'])) {        // ← move this BEFORE server_name/server_addr
    // ...
} elseif (isset($server['server_name'])) {
    // ...
} elseif (isset($server['server_addr'])) {
    // ...
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions