Host-based routing sits behind many reverse proxies, multi-tenant applications, and staging cutovers, so being able to send a request with a different HTTP Host value is useful when validating the backend that a listener will choose. That makes cURL practical for checking virtual hosts, previewing name-based routes, or testing a tenant path before any shared DNS change is made.

In HTTP, the Host header tells the server which site or tenant the request targets, while the URL host still controls where cURL connects unless another option overrides name resolution. Supplying --header 'Host: ...' changes the header that the server receives, and combining it with --resolve keeps the request pointed at a specific address without editing /etc/hosts or touching system-wide DNS.

A custom Host value changes only the HTTP layer. For HTTPS, cURL still sends SNI and verifies the certificate against the hostname in the URL, so TLS tests usually need the URL host, certificate, and any --resolve mapping to stay aligned. Keep these requests scoped to controlled test targets because cookie matching, tenant selection, access policy, and generated absolute URLs can all change with the overridden name. The example hostnames below stay masked while preserving a realistic preview-routing pattern.

Steps to override the Host header with cURL:

  1. Request the test listener without a custom header to confirm the hostname and routing target that it receives by default.
    $ curl --silent --show-error http://localhost:18081/
    {
      "received_host": "localhost:18081",
      "matched_site": "default-listener",
      "method": "GET"
    }

    Any endpoint that echoes request headers or writes access logs is sufficient for this check. The example listener returns the received Host value plus the site that the routing layer matched.

  2. Send the same request with a custom Host header so the server treats it as a different name-based site.
    $ curl --silent --show-error \
      --header 'Host: tenant-preview.internal.example' \
      http://localhost:18081/
    {
      "received_host": "tenant-preview.internal.example",
      "matched_site": "tenant-preview",
      "method": "GET"
    }

    Success is visible when the echoed Host value and matched site change from the default listener to the intended preview tenant.

  3. Pair the header override with --resolve when the request must keep a production-style URL hostname while reaching a specific backend address.
    $ curl --verbose --silent --show-error \
      --header 'Host: tenant-preview.internal.example' \
      --resolve preview-gateway.example.test:18081:127.0.0.1 \
      http://preview-gateway.example.test:18081/ --output /dev/null 2>&1 | grep -E '^\* Added|^\*   Trying|^> Host:'
    * Added preview-gateway.example.test:18081:127.0.0.1 to DNS cache
    *   Trying 127.0.0.1:18081...
    > Host: tenant-preview.internal.example

    The Trying line shows the network destination, while the Host: line shows what the HTTP server or reverse proxy receives for routing.

    On HTTPS, this header override does not change SNI or certificate validation. curl still uses the hostname from the URL for the TLS handshake.

  4. Capture both the matched site and the final remote address when scripts need a decisive success check.
    $ curl --silent --show-error \
      --header 'Host: tenant-preview.internal.example' \
      --resolve preview-gateway.example.test:18081:127.0.0.1 \
      --write-out '\nremote_ip=%{remote_ip}\n' \
      http://preview-gateway.example.test:18081/
    {
      "received_host": "tenant-preview.internal.example",
      "matched_site": "tenant-preview",
      "method": "GET"
    }
    
    remote_ip=127.0.0.1

    Success is when the response or logs show the overridden Host value and remote_ip confirms that the request reached the intended backend.