Home / References / ESP32 Library / WebServer Library
Description
The hasHeader()
method is used to check if a specific HTTP request header exists in the request received by the ESP32 WebServer. This method provides a boolean response indicating whether a particular header was sent by the client. It’s particularly useful for implementing conditional logic based on the presence of headers before attempting to access their values. The method checks headers that have been previously configured for collection using collectHeaders()
or collectAllHeaders()
methods. This is essential for creating robust web applications that need to verify the existence of authentication tokens, content types, custom headers, or any other HTTP headers before processing them.
Syntax and Usage
The hasHeader()
method has a simple usage pattern:
- Check header existence:
server.hasHeader(headerName)
– Returns true if the specified header exists in the current request, false otherwise. The header name is case-insensitive.
Arguments
- headerName (String) – The name of the HTTP header to check for. This is case-insensitive, so “Content-Type”, “content-type”, and “CONTENT-TYPE” will all match the same header. The header must have been configured for collection beforehand.
Return Value
The hasHeader()
method returns a boolean
value: true
if the specified header exists in the current request, or false
if the header is not present or was not configured for collection.
Example Codes
Example 1: Basic Header Existence Check
This example demonstrates the fundamental usage of hasHeader() to check for common HTTP headers before accessing their values, preventing empty string returns.
How to use this example: Upload this code to your ESP32 and replace the WiFi credentials. After connecting, visit the ESP32’s IP address in your browser. The server will display which common headers are present or missing. Test with different clients: browsers, curl commands like curl -H "Authorization: Bearer token123" http://ESP32_IP
, or mobile apps to see how header presence varies.
/*
* Author: Avant Maker
* Date: June 16, 2025
* Version: 1.0
* License: MIT
*
* Description:
* This example demonstrates the fundamental usage of hasHeader() to
* check for common HTTP headers before accessing their values,
* preventing empty string returns.
*
* How to use this example:
* Upload this code to your ESP32 and replace the WiFi credentials.
* After connecting, visit the ESP32's IP address in your browser.
* The server will display which common headers are present or missing.
* Test with different clients: browsers, curl commands like
* curl -H "Authorization: Bearer token123" http://ESP32_IP,
* or mobile apps to see how header presence varies.
*
* Code Source:
* This example code is sourced from the Comprehensive Guide
* to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
* For additional code examples and in-depth documentation related to
* the ESP32 Arduino Core Library, please visit:
*
* https://avantmaker.com/home/all-about-esp32-arduino-core-library/
*
* AvantMaker.com, your premier destination for all things
* DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
* to empowering makers, learners, and enthusiasts with
* the resources they need to bring their nnovative ideas to life.
*/
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";
WebServer server(80);
void handleRoot() {
String message = "AvantMaker ESP32 Header Existence Check\n";
message += "=============================\n\n";
// Check for common headers and display results
message += "Header Presence Report:\n";
message += "-----------------------\n";
if (server.hasHeader("User-Agent")) {
message += "User-Agent: Present (" + server.header("User-Agent") + ")\n";
} else {
message += "User-Agent: Not present\n";
}
if (server.hasHeader("Accept")) {
message += "Accept: Present (" + server.header("Accept") + ")\n";
} else {
message += "Accept: Not present\n";
}
if (server.hasHeader("Authorization")) {
message += "Authorization: Present (value hidden for security)\n";
} else {
message += "Authorization: Not present\n";
}
if (server.hasHeader("Content-Type")) {
message += "Content-Type: Present (" + server.header("Content-Type") + ")\n";
} else {
message += "Content-Type: Not present\n";
}
if (server.hasHeader("Host")) {
message += "Host: Present (" + server.header("Host") + ")\n";
} else {
message += "Host: Not present\n";
}
if (server.hasHeader("Referer")) {
message += "Referer: Present (" + server.header("Referer") + ")\n";
} else {
message += "Referer: Not present\n";
}
// Display total header count
message += "\nTotal headers collected: " + String(server.headers()) + "\n";
server.send(200, "text/plain", message);
}
void setup() {
Serial.begin(115200);
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
// Collect all headers to demonstrate hasHeader() functionality
server.collectAllHeaders();
// Set up route handler
server.on("/", handleRoot);
// Start server
server.begin();
Serial.println("HTTP server started");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
server.handleClient();
}
Example 2: Conditional Processing Based on Header Presence
This example shows how to use hasHeader() to implement conditional logic, handling different scenarios based on which headers are present in the request.
How to use this example: After uploading and connecting to WiFi, test different endpoints with various header combinations. Try: curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' http://ESP32_IP/data
for JSON processing, curl -H "X-API-Key: secret123" http://ESP32_IP/api
for API access, or visit the root page with different browsers to see user agent detection in action.
/*
* Author: Avant Maker
* Date: June 16, 2025
* Version: 1.0
* License: MIT
*
* Description:
* This example shows how to use hasHeader() to implement
* conditional logic, handling different scenarios based
* on which headers are present in the request.
*
* How to use this example:
* After uploading and connecting to WiFi, test different endpoints
* with various header combinations. Try:
* curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' http://ESP32_IP/data for JSON processing,
* curl -H "X-API-Key: secret123" http://ESP32_IP/api
* for API access, or visit the root page with different browsers to see user agent detection in action.
*
* Code Source:
* This example code is sourced from the Comprehensive Guide
* to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
* For additional code examples and in-depth documentation related to
* the ESP32 Arduino Core Library, please visit:
*
* https://avantmaker.com/home/all-about-esp32-arduino-core-library/
*
* AvantMaker.com, your premier destination for all things
* DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
* to empowering makers, learners, and enthusiasts with
* the resources they need to bring their nnovative ideas to life.
*/
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";
WebServer server(80);
const String validApiKey = "secret123";
void handleData() {
String response = "";
// Check if this is a POST request with content
if (server.method() == HTTP_POST) {
if (server.hasHeader("Content-Type")) {
String contentType = server.header("Content-Type");
if (contentType.indexOf("application/json") != -1) {
response = "Processing JSON data...\n";
response += "Content-Type: " + contentType + "\n";
response += "Content received and processed as JSON\n";
} else if (contentType.indexOf("application/x-www-form-urlencoded") != -1) {
response = "Processing form data...\n";
response += "Content-Type: " + contentType + "\n";
response += "Form data received and processed\n";
} else {
response = "Unsupported content type: " + contentType + "\n";
server.send(415, "text/plain", response);
return;
}
} else {
response = "Error: Content-Type header missing for POST request\n";
server.send(400, "text/plain", response);
return;
}
} else {
response = "This endpoint expects POST requests with data\n";
response += "Send POST request with Content-Type header\n";
}
server.send(200, "text/plain", response);
}
void handleAPI() {
String response = "";
// Check for API key authentication
if (server.hasHeader("X-API-Key")) {
String apiKey = server.header("X-API-Key");
if (apiKey == validApiKey) {
response = "API Access Granted\n";
response += "===================\n\n";
// Provide additional info if User-Agent is present
if (server.hasHeader("User-Agent")) {
response += "Client: " + server.header("User-Agent") + "\n";
}
response += "API Key: Valid\n";
response += "Access Level: Full\n";
response += "Request Time: " + String(millis()) + " ms\n";
server.send(200, "text/plain", response);
} else {
server.send(403, "text/plain", "Invalid API key");
}
} else {
response = "API Key Required\n";
response += "================\n\n";
response += "Please include X-API-Key header in your request\n";
response += "Example: curl -H 'X-API-Key: your_key' http://ESP32_IP/api\n";
server.send(401, "text/plain", response);
}
}
void handleRoot() {
String html = "<html><body>";
html += "<h1>AvantMaker ESP32 Conditional Header Processing</h1>";
// Customize greeting based on browser detection
if (server.hasHeader("User-Agent")) {
String userAgent = server.header("User-Agent");
if (userAgent.indexOf("Chrome") != -1) {
html += "<p>👋 Hello Chrome user!</p>";
} else if (userAgent.indexOf("Firefox") != -1) {
html += "<p>🦊 Hello Firefox user!</p>";
} else if (userAgent.indexOf("Safari") != -1) {
html += "<p>🧭 Hello Safari user!</p>";
} else if (userAgent.indexOf("Edge") != -1) {
html += "<p>🌊 Hello Edge user!</p>";
} else {
html += "<p>🤖 Hello there, interesting browser!</p>";
}
} else {
html += "<p>👤 Hello anonymous visitor!</p>";
}
html += "<h2>Available Endpoints:</h2>";
html += "<ul>";
html += "<li><a href='/api'>/api</a> - API endpoint (requires X-API-Key header)</li>";
html += "<li>/data - Data processing endpoint (requires POST with Content-Type)</li>";
html += "</ul>";
// Show referrer if present
if (server.hasHeader("Referer")) {
html += "<p><small>Referred from: " + server.header("Referer") + "</small></p>";
}
html += "</body></html>";
server.send(200, "text/html", html);
}
void setup() {
Serial.begin(115200);
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
// Collect specific headers needed for our functionality
const char* requiredHeaders[] = {"User-Agent", "Content-Type", "X-API-Key", "Referer", "Authorization"};
const size_t headerCount = sizeof(requiredHeaders) / sizeof(requiredHeaders[0]);
server.collectHeaders(requiredHeaders, headerCount);
// Set up route handlers
server.on("/", handleRoot);
server.on("/api", handleAPI);
server.on("/data", HTTP_POST, handleData);
// Start server
server.begin();
Serial.println("HTTP server started");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
server.handleClient();
}
Example 3: Security Headers Validation and Request Analysis
This example demonstrates advanced usage of hasHeader() for implementing security checks, request validation, and comprehensive header analysis for monitoring purposes.
How to use this example: This creates a security-focused server that validates requests based on header presence. Test various scenarios: curl -H "X-Forwarded-For: 192.168.1.100" http://ESP32_IP/secure
for proxy detection, curl -H "Origin: https://trusted-site.com" http://ESP32_IP/secure
for CORS validation, or curl -H "X-Real-IP: 10.0.0.1" -H "User-Agent: SecurityBot" http://ESP32_IP/secure
for multiple security header analysis. Check Serial Monitor for detailed security logs.
/*
* Author: Avant Maker
* Date: June 16, 2025
* Version: 1.0
* License: MIT
*
* Description:
* This example demonstrates advanced usage of hasHeader()
* for implementing security checks, request validation,
* and comprehensive header analysis for monitoring purposes.
*
* How to use this example:
* This creates a security-focused server that validates
* requests based on header presence.
*
* Test for proxy detection:
* curl -H "X-Forwarded-For: 192.168.1.100" http://ESP32_IP/secure
*
* Test for CORS validation:
* curl -H "Origin: https://trusted-site.com" http://ESP32_IP/secure
*
* Test for multiple security header analysis:
* curl -H "X-Real-IP: 10.0.0.1" -H "User-Agent: SecurityBot" http://ESP32_IP/secure
*
* Code Source:
* This example code is sourced from the Comprehensive Guide
* to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
* For additional code examples and in-depth documentation related to
* the ESP32 Arduino Core Library, please visit:
*
* https://avantmaker.com/home/all-about-esp32-arduino-core-library/
*
* AvantMaker.com, your premier destination for all things
* DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
* to empowering makers, learners, and enthusiasts with
* the resources they need to bring their nnovative ideas to life.
*/
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";
WebServer server(80);
// Trusted domains for CORS validation
const String trustedDomains[] = {"https://avantmaker.com", "https://localhost", "https://trusted-site.com"};
const size_t trustedDomainCount = sizeof(trustedDomains) / sizeof(trustedDomains[0]);
bool isTrustedOrigin(const String &origin) {
for (size_t i = 0; i < trustedDomainCount; i++) {
if (origin.indexOf(trustedDomains[i]) == 0) {
return true;
}
}
return false;
}
void logSecurityEvent(const String &event, const String &details) {
Serial.println("=== SECURITY LOG ===");
Serial.print("Timestamp: ");
Serial.println(millis());
Serial.print("Event: ");
Serial.println(event);
Serial.print("Details: ");
Serial.println(details);
Serial.print("Client IP: ");
Serial.println(server.client().remoteIP());
Serial.println("===================");
}
void handleSecure() {
String response = "Security Analysis Report\n";
response += "========================\n\n";
bool hasSecurityIssues = false;
String securityWarnings = "";
// Check for proxy headers (potential security concern)
if (server.hasHeader("X-Forwarded-For")) {
String forwardedFor = server.header("X-Forwarded-For");
response += "⚠️ Proxy detected: X-Forwarded-For = " + forwardedFor + "\n";
logSecurityEvent("PROXY_DETECTED", "X-Forwarded-For: " + forwardedFor);
hasSecurityIssues = true;
}
if (server.hasHeader("X-Real-IP")) {
String realIP = server.header("X-Real-IP");
response += "⚠️ Real IP header: X-Real-IP = " + realIP + "\n";
logSecurityEvent("REAL_IP_HEADER", "X-Real-IP: " + realIP);
hasSecurityIssues = true;
}
// CORS Origin validation
if (server.hasHeader("Origin")) {
String origin = server.header("Origin");
if (isTrustedOrigin(origin)) {
response += "✅ Origin validated: " + origin + "\n";
} else {
response += "❌ Untrusted origin: " + origin + "\n";
logSecurityEvent("UNTRUSTED_ORIGIN", origin);
hasSecurityIssues = true;
}
} else {
response += "ℹ️ No Origin header (direct access)\n";
}
// User-Agent analysis
if (server.hasHeader("User-Agent")) {
String userAgent = server.header("User-Agent");
response += "🔍 User-Agent: " + userAgent + "\n";
// Check for suspicious user agents
if (userAgent.indexOf("bot") != -1 || userAgent.indexOf("crawler") != -1 ||
userAgent.indexOf("scanner") != -1 || userAgent.indexOf("hack") != -1) {
response += "⚠️ Suspicious user agent detected!\n";
logSecurityEvent("SUSPICIOUS_USER_AGENT", userAgent);
hasSecurityIssues = true;
}
} else {
response += "⚠️ No User-Agent header (suspicious)\n";
logSecurityEvent("MISSING_USER_AGENT", "No User-Agent header present");
hasSecurityIssues = true;
}
// Check for authentication headers
if (server.hasHeader("Authorization")) {
response += "🔐 Authorization header present\n";
} else {
response += "❌ No authorization provided\n";
}
// Check for custom security headers
if (server.hasHeader("X-Requested-With")) {
response += "📱 AJAX request detected\n";
}
if (server.hasHeader("Sec-Fetch-Site")) {
String fetchSite = server.header("Sec-Fetch-Site");
response += "🌐 Fetch site: " + fetchSite + "\n";
}
// Final security assessment
response += "\n" + String(hasSecurityIssues ? "🚨" : "✅") + " Security Status: ";
response += hasSecurityIssues ? "Issues detected" : "Clean";
response += "\n";
// Recommendation
if (hasSecurityIssues) {
response += "\n⚠️ Recommendation: Review security logs for details\n";
} else {
response += "\n✅ Recommendation: Request appears legitimate\n";
}
server.send(200, "text/plain", response);
}
void handleStats() {
String response = "Header Statistics\n";
response += "=================\n\n";
int totalHeaders = server.headers();
int securityHeaders = 0;
int standardHeaders = 0;
int customHeaders = 0;
response += "Header Presence Analysis:\n";
response += "-------------------------\n";
// Standard headers
String standardHeaderNames[] = {"Host", "User-Agent", "Accept", "Accept-Language",
"Accept-Encoding", "Connection", "Referer"};
for (size_t i = 0; i < 7; i++) {
if (server.hasHeader(standardHeaderNames[i])) {
response += "✓ " + standardHeaderNames[i] + "\n";
standardHeaders++;
}
}
// Security-related headers
String securityHeaderNames[] = {"Authorization", "Origin", "X-Forwarded-For",
"X-Real-IP", "Sec-Fetch-Site", "X-Requested-With"};
response += "\nSecurity Headers:\n";
for (size_t i = 0; i < 6; i++) {
if (server.hasHeader(securityHeaderNames[i])) {
response += "🔒 " + securityHeaderNames[i] + "\n";
securityHeaders++;
}
}
response += "\nSummary:\n";
response += "--------\n";
response += "Total headers: " + String(totalHeaders) + "\n";
response += "Standard headers: " + String(standardHeaders) + "\n";
response += "Security headers: " + String(securityHeaders) + "\n";
response += "Custom headers: " + String(totalHeaders - standardHeaders - securityHeaders) + "\n";
server.send(200, "text/plain", response);
}
void handleRoot() {
String html = "<html><body>";
html += "<h1>ESP32 Security Header Monitor</h1>";
html += "<p>Advanced header validation and security analysis system.</p>";
html += "<h2>Endpoints:</h2>";
html += "<ul>";
html += "<li><a href='/secure'>/secure</a> - Security analysis with header validation</li>";
html += "<li><a href='/stats'>/stats</a> - Header presence statistics</li>";
html += "</ul>";
html += "<p><strong>Note:</strong> Security events are logged to Serial Monitor.</p>";
// Show current client info
if (server.hasHeader("User-Agent")) {
html += "<p><em>Your browser: " + server.header("User-Agent") + "</em></p>";
}
html += "</body></html>";
server.send(200, "text/html", html);
}
void setup() {
Serial.begin(115200);
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
// Collect all headers for comprehensive security analysis
server.collectAllHeaders();
// Set up route handlers
server.on("/", handleRoot);
server.on("/secure", handleSecure);
server.on("/stats", handleStats);
// Start server
server.begin();
Serial.println("HTTP server started");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Security monitoring active - check Serial Monitor for security logs");
}
void loop() {
server.handleClient();
}
ESP32 Library Index
- ESP32 WiFi Library
- ESP32 WiFiClient Library
- ESP32 HTTPClient Library
- ESP32 WiFiClientSecure Library
- ESP32 AsyncUDP Librarry
- ESP32 WebServer Library
- Server Operation
- Client Hnadling
- Routing and Handlers
- Authentication
- Request Information
- Request Header Management
- Response Information
- Server Configuration
- Which ESP32 Boards are Recommended for Learners
- How to Copy Codes from AvantMaker.com
- What is SPIFFS and how to upload files to it?
- What is LIttleFS and how to upload files to it?
Ready to experiment and explore more about ESP32? Visit our website’s All About ESP32 Resources Hub, packed with tutorials, guides, and tools to inspire your maker journey. Experiment, explore, and elevate your skills with everything you need to master this powerful microcontroller platform!