Recently, I encountered an issue while setting up WebSocket connections through an Apache reverse proxy to Spring Boot application.
The error message in application log like below.
2025-02-18 17:01:05.255 ERROR 242411 --- [nio-8080-exec-2] o.s.w.s.s.s.DefaultHandshakeHandler : "Handshake failed due to invalid Upgrade header: null"
This error occurs when WebSocket connection fails to establish properly through Apache2 reverse proxy.
The Problem
When running Spring Boot application behind an Apache reverse proxy, Websocket requires special handling. The default Apache2 configuration doesn’t automatically support Websocket protocol upgrade process, leading to the handshake failures.
In my case, the WebSocket client was trying to connect to:
wss://dttracking.phamanhduc.com/gps-socket/245/nbllozux/websocket
The Solution
The fix involves modifying the Apache virtual host configuration to properly support WebSocket connections. Here’s the solution:
1. Ensure have the necessary Apache modules installed
sudo a2enmod proxy
sudo a2enmod proxy_wstunnel
sudo a2enmod proxy_http
2. Update Apache virtual host configuration file (typically found in /etc/apache2/sites-available/
)
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName dttracking.phamanhduc.com
# Enable required modules
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyPreserveHost On
# WebSocket specific configuration
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/gps-socket/(.*) ws://localhost:8080/gps-socket/$1 [P,L]
....
</VirtualHost>
</IfModule>
3. After making the changes, test the configuration and restart Apache
sudo apache2ctl configtest
sudo systemctl restart apache2
Key components Explained
Let’s break down the important parts of this configuration:
- Module loading: The configuration ensure that necessary modules for proxying and WebSocket support are available
- WebSocket Rules: The RewriteEngine rules specifically handle Websocket connections:
- Check for
Upgrade: websocket
header - Check for
Connection: upgrade
header - Forward WebSocket connections to the appropriate backend endpoints. In my case is:
ws://localhost:8080/gps-socket
- Check for
Conclution
If you’re implementing WebSockets in your Spring Boot application, this configuration should help you avoid the common pitfall of handshake failures through Apache reverse proxy.