Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for populating $http_host with the :authority header in HTTP/3 (QUIC) #455

Open
MarcoMarcoaldi opened this issue Jan 16, 2025 · 1 comment
Labels

Comments

@MarcoMarcoaldi
Copy link

Description

I would like to report a technical issue regarding the use of HTTP/3 (also known as QUIC) with all versions of NGINX. The problem involves the $http_host variable, which remains empty in HTTP/3 because it is not populated using the values from the :authority header. This behavior differs from HTTP/1 and HTTP/2, where $http_host is correctly populated using client-provided data.

Technical Configuration

In my case, I am using NGINX 1.23.7 for a Magento 2 installation that hosts three multilingual sites. The configuration uses a map directive to determine the language code of the site (e.g., Italian, English, or German) based on the value of $http_host. Below is a simplified example of the configuration:

map $http_host $MAGE_RUN_CODE {
    www.bselfie.it website_it;
    www.bselfie.it/en website_en;
    www.bselfie.de website_de;
}

This configuration works perfectly with HTTP/2: the $http_host value is correctly passed and allows the appropriate site or language to be served. However, with HTTP/3, $http_host remains empty because this protocol uses the :authority header, which does not automatically populate $http_host.

The Problem

In HTTP/3, the lack of a value for $http_host causes routing logic to fail. For instance:

Requests to www.bselfie.it/en are not correctly mapped because $http_host is empty.
Magento cannot identify the specific site and always defaults to the primary site (Italian in this case).
This behavior makes it impossible to use HTTP/3 alongside configurations that rely on $http_host unless HTTP/3 support is completely disabled, which is not an ideal solution.

Technical Considerations

While the $host variable could be considered an alternative, it is not suitable in this scenario. $host only contains the main domain (www.bselfie.it) and does not include critical parts of the URL, such as /en, which are necessary for differentiating configurations. Therefore, $host cannot replace $http_host for setups that depend on advanced routing logic or mapping.

Proposal

I propose that NGINX be updated to support the automatic population of $http_host in HTTP/3 by retrieving values from the :authority header, as is done for HTTP/1 and HTTP/2. This improvement would ensure consistent behavior across HTTP protocol versions and resolve issues like the one described.

Conclusion

I believe this functionality is crucial for improving the adoption and compatibility of HTTP/3 in complex scenarios. I am available to provide further details or examples if needed.

Thank you,
Marco Marcoaldi
MANAGED SERVER SRL

@HanadaLee
Copy link

$host only contains the main domain (www.bselfie.it) and does not include critical parts of the URL, such as /en, which are necessary for differentiating configurations.

I don't understand your case, why $http_host includes the uri part.

$http_ prefixed variables are used to point to http request headers. Therefore, even if nginx needs to support getting pseudo header values, h2/h3 pseudo headers should not be associated with $http_host unless the request is really initiated with a host request header. Instead, I think nginx should provide another set of variables to get pseudo header values, such as $pseudo_http_authority.

The $host variable exists to parse and normalize the host name, which is why nginx specifically distinguishes between $host and $http_host variables. $host only contains the host name part, separating the port number from $http_host, and also supports parsing the host name in the request line and :authority in h2/h3. It is also the basis for finding virtual hosts in nginx.

I noticed that your $http_host has a uri part. I guess this should be your custom behavior? Since $http_host only faithfully records the host header of the original http request, you can get the host name with the path from this variable. Incorrect use of the $http_host variable to execute routing or functional logic may pose a security risk.

In the rfc, the host header only allows the host name and optional port number to appear, and there should be no uri part.
https://www.rfc-editor.org/rfc/rfc9110.html#name-host-and-authority

Also in your use case I believe you can combine the $host header with something else and do a map like.

map $host$uri $MAGE_RUN_CODE {
~*^www\.bselfie\.it/en website_en;
~*^www\.bselfie\.it website_it;
~*^www\.bselfie\.de website_de;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants