How to Mock HTTP Responses to Verify HSTS Headers in Python
This code demonstrates how to use unittest.mock to intercept and capture HTTP response headers, specifically the Strict-Transport-Security header, from a mocked HTTPServer handler for security validation.
Python code
24 linesfrom http.server import BaseHTTPRequestHandler, HTTPServer
from unittest.mock import patch
class StrictTransportMock(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
self.end_headers()
self.wfile.write(b"Secure response")
def log_message(self, format, *args):
pass
def check_hsts_header(handler):
response_headers = {}
with patch.object(handler, 'send_header', side_effect=lambda k, v: response_headers.update({k: v})):
handler.do_GET()
return response_headers.get("Strict-Transport-Security")
if __name__ == "__main__":
mock_handler = StrictTransportMock.__new__(StrictTransportMock)
hsts_value = check_hsts_header(mock_handler)
print(f"HSTS header: {hsts_value}")
print(f"Is valid: {'max-age=31536000' in hsts_value and 'includeSubDomains' in hsts_value}")
Output
HSTS header: max-age=31536000; includeSubDomains
Is valid: True
How it works
The StrictTransportMock class defines a minimal HTTP handler that, when do_GET is invoked, simulates a secure response with an HSTS header. The check_hsts_header function uses patch.object to replace the send_header method on the handler instance, capturing each header key-value pair into a dictionary instead of actually sending them over the wire. This allows you to assert the presence and correctness of the HSTS header without starting a real server. The log_message override suppresses request logging, keeping test output clean. The script instantiates the handler without calling __init__ (via __new__) to avoid the network setup, runs do_GET, and prints whether the HSTS header meets the required max-age and includeSubDomains criteria.
Common mistakes
- Forgetting to call `end_headers()` in the mock handler, which breaks the header-capture logic.
- Using `patch` without `object` when patching a method on an instance, causing a TypeError.
- Not overriding `log_message`, leading to noisy test output from the standard logger.
Variations
- Use `requests_mock` to intercept real HTTP calls and inspect response headers in integration tests.
- Use `unittest.mock.Mock(wraps=handler)` to automatically forward calls while capturing headers.
Real-world use cases
- Unit-testing security middleware that must always emit HSTS headers in response to HTTP requests.
- Verifying that a reverse-proxy or app server configuration sends the correct Strict-Transport-Security header in CI pipelines.
- Simulating HTTPS responses in a test harness to validate client-side certificate pinning or redirect logic.
Sponsored
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.