Skip to content

Conversation

@Artur-
Copy link
Member

@Artur- Artur- commented Jan 15, 2026

Heartbeat requests and responses both have empty bodies, so the Content-Type: text/plain header is unnecessary and causes issues with Web Application Firewalls (WAFs). WAFs struggle to validate text/plain requests with no body content, triggering false positive security alerts in SOC monitoring systems.

Changes:

  • Server: Remove Content-Type header from successful heartbeat responses in HeartbeatHandler (empty body = no content type needed)
  • Client: Remove Content-Type from heartbeat POST requests in Heartbeat.java (request body is null)
  • Tests: Add verification that Content-Type is not set while Cache-Control remains in place

The original Content-Type header was added in 2013 to fix Firefox issue vaadin/framework#4167, where Firefox tried to parse the empty response as HTML and threw errors. This is no longer relevant because:

  1. Vaadin's client code never reads the response body, avoiding any parsing that would trigger browser errors
  2. Modern browsers handle empty responses without Content-Type
  3. HTTP best practices recommend no Content-Type for empty bodies

The Cache-Control: no-cache header is retained as it's still required for iOS 6 Safari compatibility (vaadin/framework#3226).

Fixes #23217

Heartbeat requests and responses both have empty bodies, so the
Content-Type: text/plain header is unnecessary and causes issues
with Web Application Firewalls (WAFs). WAFs struggle to validate
text/plain requests with no body content, triggering false positive
security alerts in SOC monitoring systems.

Changes:
- Server: Remove Content-Type header from successful heartbeat
  responses in HeartbeatHandler (empty body = no content type needed)
- Client: Remove Content-Type from heartbeat POST requests in
  Heartbeat.java (request body is null)
- Tests: Add verification that Content-Type is not set while
  Cache-Control remains in place

The original Content-Type header was added in 2013 to fix Firefox
issue vaadin/framework#4167, where Firefox tried to parse the empty
response as HTML and threw errors. This is no longer relevant because:
1. Vaadin's client code never reads the response body, avoiding
   any parsing that would trigger browser errors
2. Modern browsers handle empty responses without Content-Type
3. HTTP best practices recommend no Content-Type for empty bodies

The Cache-Control: no-cache header is retained as it's still required
for iOS 6 Safari compatibility (vaadin/framework#3226).

Fixes #23217
@sonarqubecloud
Copy link

@github-actions
Copy link

Test Results

1 313 files  ± 0  1 313 suites  ±0   1h 15m 0s ⏱️ - 1m 53s
9 307 tests + 1  9 239 ✅ + 1  68 💤 ±0  0 ❌ ±0 
9 767 runs  +10  9 691 ✅ +10  76 💤 ±0  0 ❌ ±0 

Results for commit 968dbb3. ± Comparison against base commit 258d811.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor Heartbeat HTTP communication to be more WAF friendly

2 participants