-
Notifications
You must be signed in to change notification settings - Fork 647
Description
Environment
- Kubernetes Version: 1.33.4
- Envoy Gateway Version: 1.6.1
- Installation: Default configuration (Helm)
Problem
I have an nginx frontend pod that serves static files and reverse proxies /api/* to a backend Java Gateway service.
What works:
- ✅ Static files (HTML/CSS/JS) load correctly via Envoy Gateway
- ✅ Direct access to API endpoints in a separate browser tab works perfectly (both HTTP and HTTPS)
What fails:
- ❌ XHR/API requests from the web application via HTTP (port 80): Return
400 Bad Request - ❌ XHR/API requests from the web application via HTTPS (port 443): Return
HTTP/2 error
Key Finding
This is the most important clue: When I open API endpoints like http://gateway-ip/api/getConfig or https://gateway-ip/api/getConfig directly in a new browser tab, they work perfectly fine and return correct JSON responses.
However, when the exact same endpoints are called via XHR from the JavaScript application running in the browser, they fail with 400 or HTTP/2 errors.
This suggests the issue is related to how Envoy Gateway handles XHR requests specifically, possibly related to CORS, request headers, or how it processes requests from JavaScript versus direct browser navigation.
Architecture
Browser → Envoy Gateway (LoadBalancer) → nginx Pod → /api/* → Java Gateway Service
Nginx Configuration
Basic reverse proxy setup in nginx:
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://java-gateway:8080/api/;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}Observed Behavior
From browser Network tab:
- Static resources:
Status: 200,Type: javascript/png/etc- ✅ Success - API direct access (new tab):
Status: 200,Type: xhr/document- ✅ Success - API XHR calls (from app):
Status: 400(HTTP) or(failed) HTTP/2 error(HTTPS),Type: xhr- ❌ Failed
All XHR requests to endpoints like /api/getConfig, /api/getLoginConfig fail when called from JavaScript, but the same URLs work when accessed directly.
What I've Tried
I attempted various ClientTrafficPolicy configurations:
- Increased buffer limits up to 10Mi
- Disabled all timeouts (set to 0s)
- Configured HTTP/2 window sizes
- Added
BackendTrafficPolicywith permissive circuit breaker settings
Result: None of these changes resolved the issue. XHR requests continue to fail.
Comparison
The exact same nginx configuration works perfectly with:
- ✅ nginx-ingress-controller
- ✅ Direct NodePort access to nginx
The issue only occurs with Envoy Gateway.
Question
Is there a known compatibility issue with Envoy Gateway when nginx acts as a reverse proxy to backend services? This is a very common architecture pattern (frontend nginx → backend APIs), and it's surprising that it doesn't work out of the box.
The fact that direct browser navigation works but XHR calls fail suggests there might be specific headers or request characteristics that Envoy Gateway is rejecting when the request comes from JavaScript.
Any guidance on required configuration or workarounds would be greatly appreciated. This is currently a production blocker for us.
Additional Context
- Browser screenshots showing the failures are attached above
- Envoy proxy logs show 400 responses for XHR requests
- No obvious errors in Envoy Gateway controller logs
- Same API endpoints work when accessed directly in browser, fail when called via XHR from app
