spring-cloud / spring-cloud/spring-cloud-gateway
Websocket handshake response missing added headers
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 4.9k
- Forks
- 3.5k
- Avg merge
- 20h 57m
- Merged PRs (30d)
- 8
Description
Describe the bug
spring-boot-dependencies:2.5.2
spring-cloud-dependencies:2020.0.4 (spring-cloud-gateway-server:3.0.4)
We are using SCG to front a set of web applications implemented in Streamlit. Streamlit applications establish a websocket connection which is used to dynamically return data to the page. When the websocket connection is estabished, the streamlit server returns a Set-Cookie header that contains an XSRF token. This token is then used for operations such as file upload.
After placing this app behind SCG, we noticed that we are no longer receiving the "additional" response headers. They are being lost as the response transits through the gateway.
I have put together a basic setup that replicates the issue using a simple Node.js websocket server, a client HTML page, and the SCG setup.
Steps to Reproduce
- Run the node
server.mjsfile:
// install the one dependency:
// npm install ws
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 5678 });
wss.on('headers', (headers) => {
headers.push('Set-Cookie: _xsrf=1234599');
headers.push('X-Other-Header: hello');
});
wss.on('connection', function connection(ws) {
console.log('Connection')
ws.send('hi from the server');
});
- Open the
client.htmlin your browser. It should establish a connection to the websocket server and displayhi from the serveron the page.
<!DOCTYPE html>
<html lang="en">
<head>
<title>WebSocket demo</title>
</head>
<body>
<script>
port = "5678" // Go direct to server
//port = "6600" // Go through gateway
let ws = new WebSocket("ws://127.0.0.1:" + port + "/"), messages = document.createElement('ul');
ws.onmessage = function (event) {
let messages = document.getElementsByTagName('ul')[0],
message = document.createElement('li'),
content = document.createTextNode(event.data);
message.appendChild(content);
messages.appendChild(message);
};
document.body.appendChild(messages);
</script>
</body>
</html>
- Open up the network tab, and you should also observe that the browser received two response headers (
Set-CookieandX-Other-Header).
- Now configure and start up a gateway to front this server:
# Spring Cloud Gateway Config
spring:
cloud:
gateway:
routes:
- id: websocket
uri: http://localhost:5678
predicates:
- Host=**
server:
port: 6600
logging:
level:
org:
springframework:
cloud:
gateway: TRACE
- The
client.htmlpage needs to be updated to go through the gateway. This is done by changing the port number from 5678 to 6600.
<script>
//port = "5678" // Go direct to server
port = "6600" // Go through gateway
- Go back to the browser and refresh the
client.htmlpage. You should one again seehi from the serveron the page. Now examine the network tab and notice our two added headers are absent from the server response.
Setting a breakpoint in WebsocketRoutingFilter.java, I can see the missing response headers in the proxySession.handshakeinfo.headers map.
But how to get them into the response back to the browser... 🤔. I would appreciate any tips and/or hacks to get these headers through the gateway! Thanks.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with WebsocketRoutingFilter.java at the linked breakpoint and inspect proxySession.handshakeinfo.headers. Reproduce the behavior with server.mjs, client.html, and the Spring Cloud Gateway configuration, comparing direct and proxied websocket responses. Done means the proxied response exposes the added Set-Cookie and X-Other-Header headers in the browser network tab.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, node.js, spring-boot
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100