ESP32 how do I add a Host header with http.addHeader()

Viewed 509

I'm debugging some DNS issues on a WiFi access point I'm setting up. I am connecting an ESP32 to my network so it can output what it's up to. I want to get my Public IP address as a test and I want to use http://ifconfig.me/ip to go and get it. This is superb when DNS is working, but as per standard HTTPS stuff, I can use the Host: name header in a call to the IP address to test connectivity to determine if it's just a DNS failure I'm seeing. If I set up the following in Postman, everything is super...

Postman screenshot

When I do the following on the ESP32, which should mimic the above, I get a 404 - which happens when the Host header is not sent or is incorrect.

...
    String new_url = "http://34.117.59.81/ip";
    String host = "ifconfig.me";

    HTTPClient http;
    http.begin(new_url.c_str());
    http.addHeader("Host", host.c_str());
    int httpResponseCode = http.GET();
...

What am I doing wrong? I've tried the addHeader() call either side of the begin()

I've tried collectHeaders() call, but that only keeps the response headers so I can't see what I'm actually sending.

On the positive note, the fact I'm getting a 404 does mean connectivity is fine, and the issue is my DNS as expected, but why can't I (allegedly) send the Host header?

1 Answers

The HTTPClient library adds the Host header for you automatically.

The library is written to silently ignore attempts to add your own Host field (along with Connection, UserAgent and Authorization):

    // not allow set of Header handled by code
    if(!name.equalsIgnoreCase(F("Connection")) &&
       !name.equalsIgnoreCase(F("User-Agent")) &&
       !name.equalsIgnoreCase(F("Host")) &&
       !(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())){

        String headerLine = name;

Unfortunately it doesn't currently offer a method to tell it to use a particular Host with an IP address that's not resolved from it.

You could copy the library into your project and just delete the check that stops it from using your Host field. Or (I hate suggesting this because I usually push people to use the HTTPClient library rather than roll their own) you could do your own simple HTTP implementation using WiFiClient.

It sounds like you understand this already but for others who may read this, HTTP allows one IP address to serve multiple domains (back in the old days it didn't but as we ran low on IP addresses this became critical). The server uses the Host field to decide which domain to direct traffic to. It's likely that the server you're connecting to is accepting the connection but without the Host field being set properly the request isn't making it to the correct server and is failing with a 404.

Related