Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ Derived from [Adrian McEwen's HttpClient library](https://github.com/amcewen/Htt

In normal usage, handles the outgoing request and Host header. The returned status code is parsed for you, as is the Content-Length header (if present).

If you need to connect to a server by IP address (or IP string) but still send a specific virtual-host name in the `Host` header (common on shared hosting), you can override the Host header:

```cpp
HttpClient http(client, "93.184.216.34", 80); // connect by IP
http.setHostHeader("mypageservices.com"); // send desired Host header
```

Because it expects an object of type Client, you can use it with any of the networking classes that derive from that. Which means it will work with WiFiClient, EthernetClient and GSMClient.

See the examples for more detail on how the library is used.
Expand Down
70 changes: 70 additions & 0 deletions examples/ConnectByIPWithHostHeader/ConnectByIPWithHostHeader.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Connect By IP, Override Host Header
for ArduinoHttpClient library

Some hosting providers serve multiple sites from the same IP.
In that case you may need to connect to an IP address but still send the
correct HTTP Host header (virtual host), e.g. "mypageservices.com".

created 8 Jan 2026

this example is in the public domain
*/

#include <ArduinoHttpClient.h>
#include <WiFi101.h>

#include "arduino_secrets.h"

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
/////// WiFi Settings ///////
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;

// Connect by IP address (string form)
char serverAddress[] = "93.184.216.34"; // example.com
int port = 80;

// But send this virtual-host name in the Host header
char hostName[] = "example.com";

WiFiClient wifi;
HttpClient client = HttpClient(wifi, serverAddress, port);
int status = WL_IDLE_STATUS;

void setup() {
Serial.begin(9600);

while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to Network named: ");
Serial.println(ssid);

status = WiFi.begin(ssid, pass);
}

Serial.print("SSID: ");
Serial.println(WiFi.SSID());

IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// IMPORTANT: override Host header to target the right site on shared hosting
client.setHostHeader(hostName);
}

void loop() {
Serial.println("making GET request");
client.get("/");

int statusCode = client.responseStatusCode();
String response = client.responseBody();

Serial.print("Status code: ");
Serial.println(statusCode);
Serial.print("Response: ");
Serial.println(response);

Serial.println("Wait five seconds");
delay(5000);
}
2 changes: 2 additions & 0 deletions examples/ConnectByIPWithHostHeader/arduino_secrets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define SECRET_SSID ""
#define SECRET_PASS ""
24 changes: 22 additions & 2 deletions src/HttpClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ HttpClient::HttpClient(Client& aClient, const IPAddress& aServerAddress, uint16_
resetState();
}

void HttpClient::setHostHeader(const char* aHostHeader)
{
iHostHeader = aHostHeader ? aHostHeader : "";
}

void HttpClient::clearHostHeader()
{
iHostHeader = "";
}

void HttpClient::resetState()
{
iState = eIdle;
Expand Down Expand Up @@ -158,10 +168,20 @@ int HttpClient::sendInitialHeaders(const char* aURLPath, const char* aHttpMethod
if (iSendDefaultRequestHeaders)
{
// The host header, if required
if (iServerName)
const bool hasCustomHostHeader = (iHostHeader.length() > 0);
const bool shouldSendHostHeader = hasCustomHostHeader || (iServerName != NULL);

if (shouldSendHostHeader)
{
iClient->print("Host: ");
iClient->print(iServerName);
if (hasCustomHostHeader)
{
iClient->print(iHostHeader);
}
else
{
iClient->print(iServerName);
}
if (iServerPort != kHttpPort && iServerPort != kHttpsPort)
{
iClient->print(":");
Expand Down
18 changes: 18 additions & 0 deletions src/HttpClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,23 @@ class HttpClient : public Client
*/
void noDefaultRequestHeaders();

/** Override the value used for the HTTP Host header.
Useful when connecting to an IP address (or an IP string) but needing
a specific virtual-host name in the Host header.

If not set (default), the Host header is generated from the server name
passed to the constructor. If the IPAddress constructor is used and no
override is set, no Host header is sent.
*/
void setHostHeader(const char* aHostHeader);

void setHostHeader(const String& aHostHeader)
{ setHostHeader(aHostHeader.c_str()); }

/** Clear a previously overridden Host header value.
*/
void clearHostHeader();

// Inherited from Print
// Note: 1st call to these indicates the user is sending the body, so if need
// Note: be we should finish the header first
Expand Down Expand Up @@ -390,6 +407,7 @@ class HttpClient : public Client
uint32_t iHttpWaitForDataDelay;
bool iConnectionClose;
bool iSendDefaultRequestHeaders;
String iHostHeader;
String iHeaderLine;
};

Expand Down
Loading