-
Notifications
You must be signed in to change notification settings - Fork 7.5k
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
fix(esp_http_client): Fix host header for IPv6 address literal (IDFGH-14640) #15388
base: master
Are you sure you want to change the base?
Conversation
An IPv6 IP that occurs in the 'Host:' header of an HTTP request must be enclosed in square brackets (RFC3986 section 3.2.2). Searches for ':' in the host string to efficiently determine if the host is an IPv6 IP address.
👋 Hello thelazt, we appreciate your contribution to this project! 📘 Please review the project's Contributions Guide for key guidelines on code, documentation, testing, and more. 🖊️ Please also make sure you have read and signed the Contributor License Agreement for this project. Click to see more instructions ...
Review and merge process you can expect ...
|
isn't lwip part of the network stack for esp32? |
Yes, the function in question is implemented in My main concern with this alternative approach is whether the higher overhead of
vs
I cannot see any valid real-world cases where this would make a difference, and since GNU Wget uses the same |
since this is a |
if config with a perhaps it is simply necessary to change the documentation, indicating that the user should monitor the valid value of this entity |
This does not solve the problem: For the (valid) URL
The value of But there are additional problems along the way: Furthermore, this will not solve the case of calling the HTTP client with With
the If we use
instead, the HTTP header would be correct, but this config will not succeed in establishing a connection to the host (because
With the findings from above, I am convinced that there is no appropriate place to integrate this somewhere higher in the API. Instead, this is a bug in the code that is probably unlikely to occur often (as some web servers may be quite forgiving of bad headers, and using IPv6 addresses for HTTP is not that common). By the way: To test the results of the HTTP parser, one can use the following snippet - with URLs to test as CLI parameters.
|
An IPv6 IP that occurs in the 'Host:' header of an HTTP request must be enclosed in square brackets
Description
When performing an HTTP request to an IPv6 address via URL, for example
the HTTP request header of the ESP IDF will contain
This IPv6 format is invalid and webservers will refuse to process the request.
The correct host in the header would be
Background
HTTP RFC 7230 Section 5.4 defines the
Host
header field as:and explicitly references Section 2.7.1, which specifies that host needs to conform to RFC 3986 Section 3.2.2.
The RFC 3986 Section 3.2.2 mandates that, a host identified by an Internet Protocol literal address, version 6 or later, needs to be enclosed in square brackets within an http URI:
Therefore, an IPv6 occuring in the
Host
header of an HTTP request must be enclosed by square brackets.Fix
The attached solution will test for a
:
character in the_get_host_header
helper function to determine if the host is an IPv6 address, and in such a case create the header hostname with the address in square brackets.This is a very simple approach and effectively the same check as GNU Wget uses.
I have also considered alternatives:
One would be testing for an valid IPv6 address (e.g., using
inet_pton
), however, this would probably add overhead and additional dependencies (lwip
).Another solutions would employ the parser to track if the URL contains an IPv6 literal.
While this would be a rather clean solution, it would require to changes
components/http_parser/http_parser.c
, in particular tracking the occurance ofs_http_host_v6_start
.Such a solution would be similar to Curl, which sets an IPv6 IP flag.
However, for ESP IDF such a solution would mean to adjust the HTTP parser (which, to the best of my knowledge, is an outdated version originating from the now unmaintained Node.js HTTP parser).
Furthermore, it would not handle the case of providing
config->host
(instead ofconfig->url
) for theesp_http_client_init
call.Related
There have been similar issues in other projects, e.g. https://bugzilla.mozilla.org/show_bug.cgi?id=45891
Testing
Without the fix, a request to a lighttpd) server fails.
![esp_http_client_ipv6_pcap](https://private-user-images.githubusercontent.com/6424875/412837965-e026df1c-ebde-4ac7-a12c-c166819652d9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2ODU2ODcsIm5iZiI6MTczOTY4NTM4NywicGF0aCI6Ii82NDI0ODc1LzQxMjgzNzk2NS1lMDI2ZGYxYy1lYmRlLTRhYzctYTEyYy1jMTY2ODE5NjUyZDkucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMDU1NjI3WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZTIyYTU0YjQ3ZDRkYjAwZTNhYWMzMTVkNGYyMDdiYzQ3ODk2OGI2MWI4MmVkZjFiYjk2YmZkNTM2MzBhNDI5NiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.411wxoaPzDk8qt0SMlaNoY82yRwZw2ISecp2DTmjMXQ)
With the fix, it succeeds.
Using network package capturing, the fixed host header can be seen:
Checklist
Before submitting a Pull Request, please ensure the following:
Documentation is updated as needed.Tests are updated or added as necessary.