ESP32 WebServer Library – responseHeader()

Home / References / ESP32 Library / WebServer Library

Description

The responseHeader() method is used to retrieve HTTP response header values that have been previously set using the sendHeader() method. This method allows you to access specific header information that will be sent to clients in the HTTP response. It’s particularly useful for debugging HTTP responses, implementing conditional logic based on response headers, logging server activity, and validating that the correct headers are being sent to clients. The method provides two ways to access headers: by name (case-insensitive) or by index position, making it flexible for different programming scenarios. This functionality is essential for creating robust web applications that need to inspect or modify response headers before they are sent to the client.


Syntax and Usage

The responseHeader() method can be used in two different ways:

  • By header name: server.responseHeader(headerName) – Retrieves the value of a specific response header by its name (case-insensitive). Returns an empty string if the header doesn’t exist.
  • By header index: server.responseHeader(index) – Retrieves the value of a response header at a specific index position. Useful for iterating through all response headers.

For practical applications and examples of this method, please consult the “Example Code” section on this page. This section provides comprehensive guidance to help you better understand and apply the method effectively.


Arguments

This webpage is part of the Comprehensive Guide to the ESP32 Arduino Core Library, accessible on AvantMaker.com.

  • headerName (String) – The name of the HTTP response header to retrieve. This is case-insensitive, so “Content-Type”, “content-type”, and “CONTENT-TYPE” will all match the same header.
  • index (int) – The zero-based index of the response header to retrieve. Use with responseHeaders() method to determine the total number of available headers before accessing by index.

Return Value

The responseHeader() method returns a const String& containing the value of the requested response header. If the header is not found (when using header name) or if the index is out of range, the method returns an empty string (“”).


Example Code

Response Header Inspector and Validator

This example demonstrates how to use the responseHeader() method to inspect and validate HTTP response headers before they are sent to clients. The server shows how to access headers by name and index, and provides detailed information about header management for debugging and quality assurance purposes.

How to use this example: Upload this code to your ESP32 and replace the WiFi credentials. After connecting, access different endpoints to see header inspection in action: http://ESP32_IP/ for the main dashboard, http://ESP32_IP/api/secure for security headers, http://ESP32_IP/api/cached for caching headers, and http://ESP32_IP/inspect for detailed header analysis. The server logs header information to both the Serial Monitor and the web response, making it easy to debug and validate response configurations.

/*
 * Author: Avant Maker
 * Date: June 18, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to use the responseHeader() method to
 * inspect and validate HTTP response headers before they are sent to clients.
 * The server shows how to access headers by name and index, and provides
 * detailed information about header management for debugging and quality
 * assurance purposes.
 *
 * How to use this example:
 * Upload this code to your ESP32 and replace the WiFi credentials.
 * After connecting, access different endpoints to see header inspection in action:
 * http://ESP32_IP/ for the main dashboard, http://ESP32_IP/api/secure for
 * security headers, http://ESP32_IP/api/cached for caching headers, and
 * http://ESP32_IP/inspect for detailed header analysis. The server logs header
 * information to both the Serial Monitor and the web response.
 *
 * 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_SSID";          // Replace with your Wi-Fi SSID
const char* password = "your_PASSWORD";  // Replace with your Wi-Fi password

WebServer server(80);

// Statistics for header tracking
struct HeaderStats {
  unsigned long totalRequests = 0;
  unsigned long totalResponseHeaders = 0;
  String mostCommonHeader = "";
  int mostCommonCount = 0;
} stats;

void logHeaderInspection(const String& endpoint) {
  Serial.println("=== Response Header Inspection ===");
  Serial.println("Endpoint: " + endpoint);
  Serial.println("Total Response Headers: " + String(server.responseHeaders()));
  
  // Log all headers by index
  for (int i = 0; i < server.responseHeaders(); i++) {
    String headerName = server.responseHeaderName(i);
    String headerValue = server.responseHeader(i);
    Serial.println("Header[" + String(i) + "]: " + headerName + " = " + headerValue);
  }
  
  // Check specific headers by name
  String contentType = server.responseHeader("Content-Type");
  if (contentType.length() > 0) {
    Serial.println("Content-Type found: " + contentType);
  }
  
  Serial.println("==================================");
}

void handleRoot() {
  // Add custom headers for this response
  server.sendHeader("X-Server-Info", "ESP32 Response Header Inspector");
  server.sendHeader("X-Version", "1.0");
  server.sendHeader("X-Request-ID", String(millis()));
  server.sendHeader("X-Build-Date", "2025-06-18");
  
  // Inspect headers before sending response
  logHeaderInspection("/");
  
  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:#f8f9fa;}";
  html += ".container{max-width:900px;margin:0 auto;background:white;padding:30px;border-radius:10px;box-shadow:0 2px 10px rgba(0,0,0,0.1);}";
  html += ".header-info{background:#e3f2fd;padding:20px;border-radius:8px;margin:20px 0;border-left:4px solid #1976d2;}";
  html += ".button{background:#1976d2;color:white;padding:12px 24px;border:none;border-radius:6px;cursor:pointer;margin:8px;text-decoration:none;display:inline-block;}";
  html += ".button:hover{background:#1565c0;}";
  html += ".stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:15px;margin:20px 0;}";
  html += ".stat-card{background:#f5f5f5;padding:15px;border-radius:6px;text-align:center;}";
  html += ".stat-number{font-size:1.5em;font-weight:bold;color:#1976d2;}";
  html += "</style></head><body>";
  html += "<div class='container'>";
  html += "<h1>AvantMaker ESP32 Response Header Inspector</h1>";
  html += "<p>This tool demonstrates the responseHeader() method for inspecting HTTP response headers.</p>";
  
  // Display current response headers using responseHeader() method
  html += "<div class='header-info'>";
  html += "<h3>Current Response Headers (accessed by name):</h3>";
  html += "<ul>";
  
  // Access specific headers by name using responseHeader()
  String serverInfo = server.responseHeader("X-Server-Info");
  if (serverInfo.length() > 0) {
    html += "<li><strong>X-Server-Info:</strong> " + serverInfo + "</li>";
  }
  
  String version = server.responseHeader("X-Version");
  if (version.length() > 0) {
    html += "<li><strong>X-Version:</strong> " + version + "</li>";
  }
  
  String requestId = server.responseHeader("X-Request-ID");
  if (requestId.length() > 0) {
    html += "<li><strong>X-Request-ID:</strong> " + requestId + "</li>";
  }
  
  html += "</ul></div>";
  
  // Display statistics
  html += "<div class='stats'>";
  html += "<div class='stat-card'><div class='stat-number'>" + String(server.responseHeaders()) + "</div>Response Headers</div>";
  html += "<div class='stat-card'><div class='stat-number'>" + String(stats.totalRequests) + "</div>Total Requests</div>";
  html += "<div class='stat-card'><div class='stat-number'>" + String(millis()/1000) + "s</div>Uptime</div>";
  html += "</div>";
  
  // Test endpoints
  html += "<h3>Test Different Header Configurations:</h3>";
  html += "<a href='/api/secure' class='button'>Security Headers</a>";
  html += "<a href='/api/cached' class='button'>Caching Headers</a>";
  html += "<a href='/inspect' class='button'>Header Inspector</a>";
  html += "<a href='/api/cors' class='button'>CORS Headers</a>";
  
  html += "</div></body></html>";
  
  stats.totalRequests++;
  server.send(200, "text/html", html);
}

void handleSecureAPI() {
  // Add comprehensive 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; includeSubDomains");
  server.sendHeader("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline'");
  server.sendHeader("Referrer-Policy", "strict-origin-when-cross-origin");
  
  // Inspect security headers before sending
  logHeaderInspection("/api/secure");
  
  String json = "{";
  json += "\"message\":\"Secure API endpoint with comprehensive security headers\",";
  json += "\"headerCount\":" + String(server.responseHeaders()) + ",";
  json += "\"securityHeaders\":[";
  
  // Use responseHeader() to verify security headers are set
  if (server.responseHeader("X-Content-Type-Options").length() > 0) {
    json += "\"X-Content-Type-Options\",";
  }
  if (server.responseHeader("X-Frame-Options").length() > 0) {
    json += "\"X-Frame-Options\",";
  }
  if (server.responseHeader("Strict-Transport-Security").length() > 0) {
    json += "\"Strict-Transport-Security\",";
  }
  
  // Remove trailing comma if any headers were added
  if (json.endsWith(",")) {
    json = json.substring(0, json.length() - 1);
  }
  
  json += "],";
  json += "\"timestamp\":" + String(millis()) + ",";
  json += "\"cspPolicy\":\"" + server.responseHeader("Content-Security-Policy") + "\"";
  json += "}";
  
  stats.totalRequests++;
  server.send(200, "application/json", json);
}

void handleCachedAPI() {
  // Add caching headers
  server.sendHeader("Cache-Control", "public, max-age=3600, must-revalidate");
  server.sendHeader("Expires", "Thu, 18 Jun 2025 12:00:00 GMT");
  server.sendHeader("Last-Modified", "Wed, 17 Jun 2025 10:00:00 GMT");
  server.sendHeader("ETag", "\"esp32-cached-v1-" + String(millis()) + "\"");
  server.sendHeader("Vary", "Accept-Encoding, User-Agent");
  
  logHeaderInspection("/api/cached");
  
  String json = "{";
  json += "\"message\":\"Cached API response with optimized headers\",";
  json += "\"headerCount\":" + String(server.responseHeaders()) + ",";
  json += "\"cacheControl\":\"" + server.responseHeader("Cache-Control") + "\",";
  json += "\"etag\":\"" + server.responseHeader("ETag") + "\",";
  json += "\"expires\":\"" + server.responseHeader("Expires") + "\",";
  json += "\"lastModified\":\"" + server.responseHeader("Last-Modified") + "\",";
  json += "\"timestamp\":" + String(millis());
  json += "}";
  
  stats.totalRequests++;
  server.send(200, "application/json", json);
}

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, X-Requested-With");
  server.sendHeader("Access-Control-Max-Age", "86400");
  server.sendHeader("Access-Control-Expose-Headers", "X-Total-Count, X-Page-Count");
  
  logHeaderInspection("/api/cors");
  
  String json = "{";
  json += "\"message\":\"CORS-enabled API endpoint\",";
  json += "\"headerCount\":" + String(server.responseHeaders()) + ",";
  json += "\"allowOrigin\":\"" + server.responseHeader("Access-Control-Allow-Origin") + "\",";
  json += "\"allowMethods\":\"" + server.responseHeader("Access-Control-Allow-Methods") + "\",";
  json += "\"maxAge\":\"" + server.responseHeader("Access-Control-Max-Age") + "\",";
  json += "\"timestamp\":" + String(millis());
  json += "}";
  
  stats.totalRequests++;
  server.send(200, "application/json", json);
}

void handleInspect() {
  // Add inspection headers
  server.sendHeader("X-Inspector", "Active");
  server.sendHeader("X-Debug-Mode", "Enabled");
  server.sendHeader("X-Response-Time", String(millis()) + "ms");
  
  logHeaderInspection("/inspect");
  
  String response = "Response Header Detailed Analysis\n";
  response += "==================================\n\n";
  
  int headerCount = server.responseHeaders();
  response += "Total Response Headers: " + String(headerCount) + "\n\n";
  
  // Iterate through all headers using both methods
  response += "Headers accessed by INDEX:\n";
  response += "--------------------------\n";
  for (int i = 0; i < headerCount; i++) {
    String headerName = server.responseHeaderName(i);
    String headerValue = server.responseHeader(i);
    response += "[" + String(i) + "] " + headerName + ": " + headerValue + "\n";
  }
  
  response += "\nHeaders accessed by NAME:\n";
  response += "-------------------------\n";
  
  // Test specific headers by name
  String inspector = server.responseHeader("X-Inspector");
  if (inspector.length() > 0) {
    response += "X-Inspector: " + inspector + "\n";
  }
  
  String debugMode = server.responseHeader("X-Debug-Mode");
  if (debugMode.length() > 0) {
    response += "X-Debug-Mode: " + debugMode + "\n";
  }
  
  String responseTime = server.responseHeader("X-Response-Time");
  if (responseTime.length() > 0) {
    response += "X-Response-Time: " + responseTime + "\n";
  }
  
  // Test case sensitivity
  response += "\nCase Sensitivity Test:\n";
  response += "----------------------\n";
  response += "x-inspector (lowercase): " + server.responseHeader("x-inspector") + "\n";
  response += "X-INSPECTOR (uppercase): " + server.responseHeader("X-INSPECTOR") + "\n";
  response += "X-Inspector (mixed case): " + server.responseHeader("X-Inspector") + "\n";
  
  response += "\nNon-existent header test: '" + server.responseHeader("Non-Existent-Header") + "'\n";
  
  stats.totalRequests++;
  server.send(200, "text/plain", response);
}

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/secure", handleSecureAPI);
  server.on("/api/cached", handleCachedAPI);
  server.on("/api/cors", handleCORSAPI);
  server.on("/inspect", handleInspect);
  
  // Start server
  server.begin();
  Serial.println("HTTP server started");
  Serial.println("Response Header Inspector available at: http://" + WiFi.localIP().toString());
  Serial.println("Check Serial Monitor for detailed header inspection logs");
}

void loop() {
  server.handleClient();
  
  // Optional: Print periodic statistics
  static unsigned long lastPrint = 0;
  if (millis() - lastPrint > 60000) { // Every 60 seconds
    lastPrint = millis();
    Serial.println("Stats - Total Requests: " + String(stats.totalRequests) + 
                   ", Free Heap: " + String(ESP.getFreeHeap()));
  }
}

For more ESP32 development resources and tutorials, visit AvantMaker.com

error: Content is protected !!