Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support web sockets (WS / WSS) #81

Open
GlenDC opened this issue Mar 9, 2024 · 5 comments
Open

support web sockets (WS / WSS) #81

GlenDC opened this issue Mar 9, 2024 · 5 comments
Labels
mentor available A mentor is available to help you through the issue. needs input
Milestone

Comments

@GlenDC
Copy link
Member

GlenDC commented Mar 9, 2024

Depends on support of upgrades (#17).

Not urgent though, but would be nice if we can support it,
for web servers and proxies this is useful.
But again, not urgent.

@GlenDC GlenDC added this to the v0.3 milestone Mar 9, 2024
@GlenDC GlenDC added the mentor available A mentor is available to help you through the issue. label Mar 28, 2024
@audunhalland
Copy link

I'm looking into using Rama as an HTTP gateway/proxy framework, and WebSocket proxying is one of the requirements. The Rama tower-based architecture looks solid on first glance! I see this says mentor available, so if this is not too hard or requires changing a lot of existing code/architecture, I might be able to contribute something.

@GlenDC
Copy link
Member Author

GlenDC commented Jun 21, 2024

As this is planned only for v0.3 I haven't given this too much thought on what exactly I would want to provide within Rama to explicitly support this. Because AFAIK all the building blocks as they are today would already allow you to integrate it in your project.

https://docs.rs/rama/0.2.0-alpha.0/rama/http/layer/upgrade/struct.UpgradeLayer.html Is what you want need to use as a middleware layer. And then within your own project it would be a matter of writing a matcher for it. Either implementing the trait yourself or building it with one of the matcher builders available.

Once you have that you have the raw TCP Stream again which you can accept the connection using https://docs.rs/tokio-tungstenite/latest/tokio_tungstenite/ and make the connection yourself to the target server. This way you have MITM WS(S) proxying. Or you could treat it like an http proxy and simply copy the bytes starting from the handshake already directly to the target.

That's also one of the goals of Rama to never have you be blocked on the framework. It's supposed to be as modular and flexible as possible to allow you to build whatever services and middleware you want starting from Layer 4 of the network. It's still very early days of the framework though, so plenty of rough edges and short comings still.

So in short, not short: not sure how far I would go in providing support. Maybe a first contribution could be to provide a library agnostic WebSocket Matcher which would also store the info in the Context as an extension. But might be that that is al that is needed within Rama.

Even before this. Might be already very useful if you @audunhalland can try to use Rama for your purpose, using things like tokio_tungstenite and see how the experience is. There is probably a great deal to learn from that. And maybe it will give us better insights on what support / code exactly might still be required for such purposes.

My current idea is that we probably want to implement:

But as said before, probably better to have first you experiment with all the tooling as-is, and see where the shortcomings might be and how your experience with it is. And of course if you succeed or not. Might be all you need (for now).

@roniemartinez
Copy link

+1 on WS.

Please take note that an existing limitation of tungstenite is it does not support upstream proxies (I've been looking for this feature for a long time). snapview/tungstenite-rs#177

@GlenDC
Copy link
Member Author

GlenDC commented Jun 22, 2024

AFAIK nothing in tungstenite prevents you from doing whatever you want. It's one of the reasons why I would start implementing support using that crate directly with our own code living under ::rama::http::ws

How it would work is:

  1. Rama http service receives http upgrade request
  2. Rama connects to target service via proxy establish a transport (tcp) 'rama <=> proxy <=> target'
  3. Rama sends http ws upgrade request to server
  4. If ok is received send ok back to service
  5. Rama terminates ws handshake with client and also does handshake to target
  6. You now have a WS(S) connection in both directions

High level I don't see how that wouldn't work. But there is some stuff to figure out and work to be done. Both for this issue in specific and some other things too.

That's why this is planned only for v0.3 and is my suggestion to for now write your own layer using an off the shelf crate and unblock yourself like that. This also allows you to report back to you with feedback on whether it worked for you or if not why not. What you like, miss, don't like, etc.

@audunhalland
Copy link

Thanks for all of this information, I'll certainly experiment in my codebase and see how far I can get.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mentor available A mentor is available to help you through the issue. needs input
Projects
None yet
Development

No branches or pull requests

3 participants