websockets / ws

Simple to use, blazing fast and thoroughly tested WebSocket client and server for Node.js
MIT License
21.6k stars 2.42k forks source link

Get response headers from client? #1081

Closed jwalton closed 7 years ago

jwalton commented 7 years ago

Would be nice if there was a 'headers' event on the client when we get the upgrade event here.

lpinca commented 7 years ago

How would you use it? I'm curious to know why you need it.

jwalton commented 7 years ago

I am essentially building a transparent websocket proxy. So, an upgrade request comes in, I make a new WebSocket connection to my target host. When the upgrade reply comes back, though, if there are any extra header fields in the reply I should copy them into the upgrade reply to the client. If there was a set-cookie header in the upgrade reply, for example, it should get passed on. (I mean, it would be a bit weird for there to be a set-cookie headed, but if it's there, I should forward it.)

jwalton commented 7 years ago

Actually, RFC 6455 s2 explicitly states "Additional header fields may also be present, such as cookies," so I guess it isn't that weird. The other obvious use case here is parsing cookies from a web site, then.

lpinca commented 7 years ago

If I understand correctly you are using ws to do the actual proxying. You use ws to send the upgrade request to the upstream server and want to send back the response to the client that initiated the request. Is this correct? If so I think using ws is not a good idea.

jwalton commented 7 years ago

Yeah, ws is definitely not the perfect solution here. I could just proxy the raw bytes from the request straight through to the server (possibly I'd need to rewrite some headers, but even that is pretty easy - I could just handle the upgrade event straight from node). But, for my use case I also want to be able to inspect each websocket message as it goes through, or be able to filter out specific messages. In a perfect world I'd pass the raw bytes through and I'd have some kind of "ws parser" library that I could for the data to. ws seemed like an easy "this will get me started" solution, though, and it's working pretty well aside from the fact that I need to do some serious hackery to get the response headers. :)

But, I mean, you provide an API for inspecting and modifying the response headers on the server side, only makes sense you'd have one on the client side too.

lpinca commented 7 years ago

Why not using a lib that is specifically designed to do this? Like https://github.com/nodejitsu/node-http-proxy or similar?

jwalton commented 7 years ago

node-http-proxy is awesome, and I've used it before, but node-http-proxy doesn't meet my needs for a few reasons:

lpinca commented 7 years ago

Are you rewriting the frames? Otherwise I fail to understand how you communicate with the upstream WebSocket server and have the ability to alter the messages.

EDIT: nvm I think I got it and if it works like I think it works it's horrible for performance as every message is framed an masked twice :)

jwalton commented 7 years ago

The short version is:

So here either Server A or Server B has the opportunity to examine, rewrite, or discard any websocket message passing through. This is a pretty classic hop-by-hop transparent proxy, aside from the fact that it's split across two servers. I already have a working implementation.

It's easy to think up other use cases outside the crazy one I'm outlining here. If I create a websocket connection to a server, and the sever sends back a set-cookie in the upgrade response, then as a client I want to see the headers so I can add that cookie to my "cookie jar" to send in subsequent requests. ws also provides the means to set custom headers on the server, so if I want to pass an out-of-band message in a custom header, it would be nice if the client could actually see that custom header.

I'm happy to submit a PR.

lpinca commented 7 years ago

I'm not against it, thanks for explaining your use case.