Cloudflare SSL Termination with Nginx - "Upgrade Required" and CORS Issues on HTTPS Requests
I am setting up an application with the following architecture:
Frontend (React): Sends HTTPS API requests to the backend through the Nginx reverse proxy.
Backend (Express.js): Handles API requests directly at http://backend-server:8080/.
NGINX: Acts as a reverse proxy, routing traffic from https://api.example.com to the backend.
Cloudflare SSL: Provides SSL certificates for secure HTTPS communication and subdomain .
Current Functionality
HTTP requests: Work without issues.
WebSocket connections: Successfully established and functioning.
HTTPS requests (e.g., https://api.example.com/api/queue): Failing with CORS errors.
Health check endpoint (e.g., https://api.example.com/api/health): Returns "Upgrade Required" error due to backend behavior.
Pipeline Configuration
Frontend (React):
Sends requests to https://api.example.com.
Uses HTTPS for secure communication.
Backend (Express.js):
Listens on http://backend-server:8080.
Hosts API endpoints, including /api/queue and /api/health.
NGINX Reverse Proxy:
Routes HTTPS traffic from https://api.example.com to the backend.
Configured with Cloudflare-origin SSL certificates.
Cloudflare SSL:
Provides TLS termination for secure HTTPS connections.
1 Reply
Configuration (Simplified)
Nginx Configuration:
The Issues
Health Check Endpoint (/api/health):
Fails with "Upgrade Required" error.
The backend expects WebSocket headers for all requests, even for plain HTTP requests.
CORS Errors on /api/queue:
HTTPS requests from the React frontend to https://api.example.com/api/queue fail due to CORS policy enforcement.
Summary of the Issue
Goal
Set up SSL termination for an API server and ensure the
This error indicates the server is expecting WebSocket behavior for a plain HTTP request. Technical Setup - Nginx Configuration: - SSL is enabled using valid certificates. - A reverse proxy is set up to forward requests to the backend server. - Proxy headers are configured correctly for both HTTP and WebSocket traffic. - Backend: - The backend handles HTTP and WebSocket traffic on separate routes. Observed Behavior - HTTP requests to the
/health
endpoint works for health checks.
Problem
When accessing the /health
endpoint via HTTPS, the server responds with "Upgrade Required" (HTTP 426).This error indicates the server is expecting WebSocket behavior for a plain HTTP request. Technical Setup - Nginx Configuration: - SSL is enabled using valid certificates. - A reverse proxy is set up to forward requests to the backend server. - Proxy headers are configured correctly for both HTTP and WebSocket traffic. - Backend: - The backend handles HTTP and WebSocket traffic on separate routes. Observed Behavior - HTTP requests to the
/health
endpoint are treated as WebSocket upgrade requests, causing the "Upgrade Required" (HTTP 426) error.
#### What Was Done to Diagnose the Issue
1. Tested the backend directly using curl
:
- Confirmed the backend responds with HTTP 426 even when accessed without Nginx.
- This ruled out Nginx as the source of the issue.
2. Debugged Nginx logs:
- Verified that the correct headers are being forwarded.
- Found no issues with the proxy configuration.
Root Cause
- The backend server enforces WebSocket behavior on all routes, including /health
, which should only handle plain HTTP requests.
---
Solutions
Immediate Fix
- Modify the backend logic to allow plain HTTP requests for the /health
endpoint without expecting WebSocket headers.
Alternative Workaround
- Introduce a separate health check endpoint that is specifically configured for HTTP traffic.
---
Next Steps
- Coordinate with the backend team to adjust the route configuration for /health
or create a dedicated health check route..