Skip to content

Commit b84b7de

Browse files
committed
fix: host header wrong 🚀
1 parent 83514bf commit b84b7de

5 files changed

Lines changed: 119 additions & 2 deletions

File tree

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ Derived from [Adrian McEwen's HttpClient library](https://github.com/amcewen/Htt
2323

2424
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).
2525

26+
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:
27+
28+
```cpp
29+
HttpClient http(client, "93.184.216.34", 80); // connect by IP
30+
http.setHostHeader("mypageservices.com"); // send desired Host header
31+
```
32+
2633
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.
2734
2835
See the examples for more detail on how the library is used.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
Connect By IP, Override Host Header
3+
for ArduinoHttpClient library
4+
5+
Some hosting providers serve multiple sites from the same IP.
6+
In that case you may need to connect to an IP address but still send the
7+
correct HTTP Host header (virtual host), e.g. "mypageservices.com".
8+
9+
created 8 Jan 2026
10+
11+
this example is in the public domain
12+
*/
13+
14+
#include <ArduinoHttpClient.h>
15+
#include <WiFi101.h>
16+
17+
#include "arduino_secrets.h"
18+
19+
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
20+
/////// WiFi Settings ///////
21+
char ssid[] = SECRET_SSID;
22+
char pass[] = SECRET_PASS;
23+
24+
// Connect by IP address (string form)
25+
char serverAddress[] = "93.184.216.34"; // example.com
26+
int port = 80;
27+
28+
// But send this virtual-host name in the Host header
29+
char hostName[] = "example.com";
30+
31+
WiFiClient wifi;
32+
HttpClient client = HttpClient(wifi, serverAddress, port);
33+
int status = WL_IDLE_STATUS;
34+
35+
void setup() {
36+
Serial.begin(9600);
37+
38+
while (status != WL_CONNECTED) {
39+
Serial.print("Attempting to connect to Network named: ");
40+
Serial.println(ssid);
41+
42+
status = WiFi.begin(ssid, pass);
43+
}
44+
45+
Serial.print("SSID: ");
46+
Serial.println(WiFi.SSID());
47+
48+
IPAddress ip = WiFi.localIP();
49+
Serial.print("IP Address: ");
50+
Serial.println(ip);
51+
52+
// IMPORTANT: override Host header to target the right site on shared hosting
53+
client.setHostHeader(hostName);
54+
}
55+
56+
void loop() {
57+
Serial.println("making GET request");
58+
client.get("/");
59+
60+
int statusCode = client.responseStatusCode();
61+
String response = client.responseBody();
62+
63+
Serial.print("Status code: ");
64+
Serial.println(statusCode);
65+
Serial.print("Response: ");
66+
Serial.println(response);
67+
68+
Serial.println("Wait five seconds");
69+
delay(5000);
70+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define SECRET_SSID ""
2+
#define SECRET_PASS ""

src/HttpClient.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ HttpClient::HttpClient(Client& aClient, const IPAddress& aServerAddress, uint16_
2929
resetState();
3030
}
3131

32+
void HttpClient::setHostHeader(const char* aHostHeader)
33+
{
34+
iHostHeader = aHostHeader ? aHostHeader : "";
35+
}
36+
37+
void HttpClient::clearHostHeader()
38+
{
39+
iHostHeader = "";
40+
}
41+
3242
void HttpClient::resetState()
3343
{
3444
iState = eIdle;
@@ -158,10 +168,20 @@ int HttpClient::sendInitialHeaders(const char* aURLPath, const char* aHttpMethod
158168
if (iSendDefaultRequestHeaders)
159169
{
160170
// The host header, if required
161-
if (iServerName)
171+
const bool hasCustomHostHeader = (iHostHeader.length() > 0);
172+
const bool shouldSendHostHeader = hasCustomHostHeader || (iServerName != NULL);
173+
174+
if (shouldSendHostHeader)
162175
{
163176
iClient->print("Host: ");
164-
iClient->print(iServerName);
177+
if (hasCustomHostHeader)
178+
{
179+
iClient->print(iHostHeader);
180+
}
181+
else
182+
{
183+
iClient->print(iServerName);
184+
}
165185
if (iServerPort != kHttpPort && iServerPort != kHttpsPort)
166186
{
167187
iClient->print(":");

src/HttpClient.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,23 @@ class HttpClient : public Client
295295
*/
296296
void noDefaultRequestHeaders();
297297

298+
/** Override the value used for the HTTP Host header.
299+
Useful when connecting to an IP address (or an IP string) but needing
300+
a specific virtual-host name in the Host header.
301+
302+
If not set (default), the Host header is generated from the server name
303+
passed to the constructor. If the IPAddress constructor is used and no
304+
override is set, no Host header is sent.
305+
*/
306+
void setHostHeader(const char* aHostHeader);
307+
308+
void setHostHeader(const String& aHostHeader)
309+
{ setHostHeader(aHostHeader.c_str()); }
310+
311+
/** Clear a previously overridden Host header value.
312+
*/
313+
void clearHostHeader();
314+
298315
// Inherited from Print
299316
// Note: 1st call to these indicates the user is sending the body, so if need
300317
// Note: be we should finish the header first
@@ -390,6 +407,7 @@ class HttpClient : public Client
390407
uint32_t iHttpWaitForDataDelay;
391408
bool iConnectionClose;
392409
bool iSendDefaultRequestHeaders;
410+
String iHostHeader;
393411
String iHeaderLine;
394412
};
395413

0 commit comments

Comments
 (0)