#3554·h2o

Host matching rules for HTTP/1.1 requests permits invalid values per RFC

Author: hQian2718Created Jan 27, 2026Updated Jan 27, 2026

Description

When sending an HTTP/1.1 request with an explicitly empty Host header or a missing Host header, h2o returns 200 OK and serves content, whereas the HTTP/1.1 specification requires a 400 Bad Request response for invalid Host header values.

Affected Version

built from source from the master branch. h2o -v shows

h2o version 2.3.0-DEV@a9ba592b9
OpenSSL: OpenSSL 3.0.2 15 Mar 2022
mruby: YES
ssl-zerocopy: YES
ktls: YES
key-exchanges: secp521r1, secp384r1, x25519, secp256r1

Steps to Reproduce

I ran h2o on localhost with this config file:

# h2o.conf
user: root
hosts:
  "default":
    strict-match: OFF
    listen:
      port: 80
    paths:
      "/":
        file.dir: /usr/share/h2o/htdocs

The following raw HTTP/1.1 requests for a static file return 200.

printf "GET /index.html HTTP/1.1\r\nHost: \r\nConnection: close\r\n\r\n" | nc localhost 80 printf "GET /index.html HTTP/1.1\r\nConnection: close\r\n\r\n" | nc localhost 80

With strict-match: ON these requests return 404.

Expected behavior

The HTTP/1.1 RFC states that a server MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message that contains a Host header field with an invalid field value.

An empty string is not a valid value for the Host header per the URI RFC.

Notes

I'm wondering if this behavior is intended to be more lenient than the RFC as part of the server design. Nevertheless, this seems to be an instance where the behavior directly violates a RFC MUST statement. It would be helpful to add documentation to reflect this choice at least.