ESP32 WebServer Library – responseHeaders()

Home / References / ESP32 Library / WebServer Library

Description

The responseHeaders() method is used to get the number of headers that have been added to the current HTTP response. This method returns an integer count of all response headers that have been set using the sendHeader() method before sending the response to the client. It’s particularly useful for debugging HTTP responses, logging server activity, implementing dynamic header management, and validating that the correct number of headers are being sent. The method provides insight into the response structure and can be used to ensure that security headers, caching directives, and custom headers are properly included in the server’s responses.

Syntax and Usage

The responseHeaders() method has a simple syntax:

  • Get header count: int count = server.responseHeaders() – Returns the number of response headers currently set for the active response.

Arguments

  • None – This method takes no arguments.

Return Value

The responseHeaders() method returns an int representing the total number of response headers that have been added to the current HTTP response. The count includes all headers added via sendHeader() and any automatic headers added by the server (such as Content-Type, Content-Length, etc.).

Example Code

HTTP Response Header Inspector and Manager

This example demonstrates how to use the responseHeaders() method to monitor and manage HTTP response headers. The server shows how many headers are added to different types of responses and provides detailed information about header management for debugging and optimization purposes.

How to use this example: Upload this code to your ESP32 and replace the WiFi credentials. After connecting, access the main page at http://ESP32_IP/ to see the response header dashboard. Test different endpoints to see how header counts vary: http://ESP32_IP/api/simple for minimal headers, http://ESP32_IP/api/secure for security headers, and http://ESP32_IP/api/cached for caching headers. Use browser developer tools (F12 → Network tab) to inspect the actual headers being sent and compare with the reported counts.

/*
 * Author: Avant Maker
 * Date: June 18, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to use the responseHeaders() method to
 * monitor and manage HTTP response headers. The server shows how many
 * headers are added to different types of responses and provides detailed
 * information about header management for debugging and optimization purposes.
 *
 * How to use this example:
 * Upload this code to your ESP32 and replace the WiFi credentials.
 * After connecting, access the main page at http://ESP32_IP/ to see the
 * response header dashboard. Test different endpoints to see how header
 * counts vary: http://ESP32_IP/api/simple for minimal headers,
 * http://ESP32_IP/api/secure for security headers, and
 * http://ESP32_IP/api/cached for caching headers. Use browser developer
 * tools (F12 → Network tab) to inspect the actual headers being sent
 * and compare with the reported counts.
 *
 * 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);

// Statistics for header tracking
struct HeaderStats {
  unsigned long totalRequests = 0;
  unsigned long totalHeaders = 0;
  int minHeaders = 999;
  int maxHeaders = 0;
  float avgHeaders = 0.0;
} stats;

void updateHeaderStats(int headerCount) {
  stats.totalRequests++;
  stats.totalHeaders += headerCount;
  stats.avgHeaders = (float)stats.totalHeaders / stats.totalRequests;
  
  if (headerCount < stats.minHeaders) {
    stats.minHeaders = headerCount;
  }
  if (headerCount > stats.maxHeaders) {
    stats.maxHeaders = headerCount;
  }
}

void handleRoot() {
  // Add custom headers for this response
  server.sendHeader("X-Server-Info", "ESP32 Header Inspector");
  server.sendHeader("X-Build-Version", "1.0");
  server.sendHeader("X-Request-ID", String(millis()));
  
  // Check how many headers we have before sending
  int headerCount = server.responseHeaders();
  updateHeaderStats(headerCount);
  
  String html = "<!DOCTYPE html><html><head>";
  html += "<title>AvantMaker ESP32 Response Header Inspector</title>";
  html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
  html += "<style>";
  html += "body{font-family:Arial,sans-serif;margin:20px;background:#f5f5f5;}";
  html += ".container{max-width:900px;margin:0 auto;background:white;padding:30px;border-radius:10px;box-shadow:0 4px 15px rgba(0,0,0,0.1);}";
  html += ".stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:20px;margin:20px 0;}";
  html += ".stat-card{background:#e8f4fd;padding:20px;border-radius:8px;text-align:center;border-left:4px solid #007bff;}";
  html += ".stat-number{font-size:2em;font-weight:bold;color:#007bff;margin-bottom:5px;}";
  html += ".stat-label{color:#666;font-size:0.9em;}";
  html += ".header-info{background:#f8f9fa;padding:20px;border-radius:8px;margin:20px 0;}";
  html += ".button{background:#007bff;color:white;padding:12px 24px;border:none;border-radius:6px;cursor:pointer;margin:8px;text-decoration:none;display:inline-block;}";
  html += ".button:hover{background:#0056b3;}";
  html += ".button.success{background:#28a745;} .button.success:hover{background:#1e7e34;}";
  html += ".button.warning{background:#ffc107;color:#212529;} .button.warning:hover{background:#e0a800;}";
  html += ".button.danger{background:#dc3545;} .button.danger:hover{background:#c82333;}";
  html += ".endpoint-list{background:#fff3cd;padding:20px;border-radius:8px;margin:20px 0;border:1px solid #ffeaa7;}";
  html += "</style></head><body>";
  
  html += "<div class='container'>";
  html += "<h1>AvantMaker ESP32 Response Header Inspector</h1>";
  
  // Current response info
  html += "<div class='header-info'>";
  html += "<h3>Current Response Information</h3>";
  html += "<p><strong>Headers in this response:</strong> " + String(headerCount) + "</p>";
  html += "<p><strong>Content-Type:</strong> text/html</p>";
  html += "<p><strong>Custom headers added:</strong> X-Server-Info, X-Build-Version, X-Request-ID</p>";
  html += "<p><em>Use browser developer tools (F12 → Network tab) to see all headers</em></p>";
  html += "</div>";
  
  // Statistics
  html += "<div class='stats'>";
  html += "<div class='stat-card'><div class='stat-number'>" + String(stats.totalRequests) + "</div><div class='stat-label'>Total Requests</div></div>";
  html += "<div class='stat-card'><div class='stat-number'>" + String(stats.avgHeaders, 1) + "</div><div class='stat-label'>Avg Headers/Response</div></div>";
  html += "<div class='stat-card'><div class='stat-number'>" + String(stats.minHeaders == 999 ? 0 : stats.minHeaders) + "</div><div class='stat-label'>Min Headers</div></div>";
  html += "<div class='stat-card'><div class='stat-number'>" + String(stats.maxHeaders) + "</div><div class='stat-label'>Max Headers</div></div>";
  html += "<div class='stat-card'><div class='stat-number'>" + String(stats.totalHeaders) + "</div><div class='stat-label'>Total Headers Sent</div></div>";
  html += "</div>";
  
  // Test endpoints
  html += "<div class='endpoint-list'>";
  html += "<h3>Test Different Header Configurations</h3>";
  html += "<p>Click these endpoints to see how header counts vary:</p>";
  html += "<a href='/api/simple' class='button success'>Simple API (Minimal Headers)</a>";
  html += "<a href='/api/secure' class='button warning'>Secure API (Security Headers)</a>";
  html += "<a href='/api/cached' class='button'>Cached API (Cache Headers)</a>";
  html += "<a href='/api/cors' class='button danger'>CORS API (Cross-Origin Headers)</a>";
  html += "<a href='/stats/reset' class='button'>Reset Statistics</a>";
  html += "</div>";
  
  // System info
  html += "<h3>System Information</h3>";
  html += "<p>Free Heap: " + String(ESP.getFreeHeap()) + " bytes</p>";
  html += "<p>Uptime: " + String(millis()/1000) + " seconds</p>";
  html += "<p>WiFi Signal: " + String(WiFi.RSSI()) + " dBm</p>";
  
  html += "</div></body></html>";
  
  server.send(200, "text/html", html);
  
  // Log the actual header count after sending
  Serial.println("Sent HTML response with " + String(headerCount) + " headers");
}

void handleSimpleAPI() {
  // Minimal headers - just the basics
  int headerCount = server.responseHeaders();
  updateHeaderStats(headerCount);
  
  String json = "{";
  json += "\"message\":\"Simple API response\",";
  json += "\"headerCount\":" + String(headerCount) + ",";
  json += "\"timestamp\":" + String(millis()) + ",";
  json += "\"type\":\"minimal\"";
  json += "}";
  
  server.send(200, "application/json", json);
  
  Serial.println("Simple API - Headers: " + String(headerCount));
}

void handleSecureAPI() {
  // Add security headers
  server.sendHeader("X-Content-Type-Options", "nosniff");
  server.sendHeader("X-Frame-Options", "DENY");
  server.sendHeader("X-XSS-Protection", "1; mode=block");
  server.sendHeader("Strict-Transport-Security", "max-age=31536000");
  server.sendHeader("Content-Security-Policy", "default-src 'self'");
  
  int headerCount = server.responseHeaders();
  updateHeaderStats(headerCount);
  
  String json = "{";
  json += "\"message\":\"Secure API response\",";
  json += "\"headerCount\":" + String(headerCount) + ",";
  json += "\"securityHeaders\":[";
  json += "\"X-Content-Type-Options\",\"X-Frame-Options\",\"X-XSS-Protection\",";
  json += "\"Strict-Transport-Security\",\"Content-Security-Policy\"],";
  json += "\"timestamp\":" + String(millis()) + ",";
  json += "\"type\":\"secure\"";
  json += "}";
  
  server.send(200, "application/json", json);
  
  Serial.println("Secure API - Headers: " + String(headerCount));
}

void handleCachedAPI() {
  // Add caching headers
  server.sendHeader("Cache-Control", "public, max-age=3600");
  server.sendHeader("Expires", "Thu, 01 Jan 2025 00:00:00 GMT");
  server.sendHeader("Last-Modified", "Wed, 01 Jan 2024 00:00:00 GMT");
  server.sendHeader("ETag", "\"esp32-cached-response-v1\"");
  
  int headerCount = server.responseHeaders();
  updateHeaderStats(headerCount);
  
  String json = "{";
  json += "\"message\":\"Cached API response\",";
  json += "\"headerCount\":" + String(headerCount) + ",";
  json += "\"cacheHeaders\":[\"Cache-Control\",\"Expires\",\"Last-Modified\",\"ETag\"],";
  json += "\"timestamp\":" + String(millis()) + ",";
  json += "\"type\":\"cached\"";
  json += "}";
  
  server.send(200, "application/json", json);
  
  Serial.println("Cached API - Headers: " + String(headerCount));
}

void handleCORSAPI() {
  // Add CORS headers
  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.sendHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
  server.sendHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
  server.sendHeader("Access-Control-Max-Age", "86400");
  server.sendHeader("Vary", "Origin");
  
  int headerCount = server.responseHeaders();
  updateHeaderStats(headerCount);
  
  String json = "{";
  json += "\"message\":\"CORS-enabled API response\",";
  json += "\"headerCount\":" + String(headerCount) + ",";
  json += "\"corsHeaders\":[";
  json += "\"Access-Control-Allow-Origin\",\"Access-Control-Allow-Methods\",";
  json += "\"Access-Control-Allow-Headers\",\"Access-Control-Max-Age\",\"Vary\"],";
  json += "\"timestamp\":" + String(millis()) + ",";
  json += "\"type\":\"cors\"";
  json += "}";
  
  server.send(200, "application/json", json);
  
  Serial.println("CORS API - Headers: " + String(headerCount));
}

void handleResetStats() {
  stats.totalRequests = 1; // Keep this request
  stats.totalHeaders = 0;
  stats.minHeaders = 999;
  stats.maxHeaders = 0;
  stats.avgHeaders = 0.0;
  
  int headerCount = server.responseHeaders();
  updateHeaderStats(headerCount);
  
  server.send(200, "text/plain", "Statistics reset!\nGo back to: http://" + WiFi.localIP().toString());
  
  Serial.println("Statistics reset");
}

void setup() {
  Serial.begin(115200);
  
  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  
  Serial.println("WiFi connected!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  // Set up route handlers
  server.on("/", handleRoot);
  server.on("/api/simple", handleSimpleAPI);
  server.on("/api/secure", handleSecureAPI);
  server.on("/api/cached", handleCachedAPI);
  server.on("/api/cors", handleCORSAPI);
  server.on("/stats/reset", handleResetStats);
  
  // Start server
  server.begin();
  Serial.println("HTTP server started");
  Serial.println("Header inspector available at: http://" + WiFi.localIP().toString());
  Serial.println("Monitor different header configurations and counts");
}

void loop() {
  server.handleClient();
  
  // Optional: Print periodic statistics
  static unsigned long lastPrint = 0;
  if (millis() - lastPrint > 60000) { // Every 60 seconds
    lastPrint = millis();
    Serial.println("Header Stats - Requests: " + String(stats.totalRequests) + 
                   ", Avg Headers: " + String(stats.avgHeaders, 1) + 
                   ", Min: " + String(stats.minHeaders == 999 ? 0 : stats.minHeaders) + 
                   ", Max: " + String(stats.maxHeaders));
  }
}
error: Content is protected !!