-
-
Notifications
You must be signed in to change notification settings - Fork 72
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
Start using FastifyRequest objects for the upgrade request so hooks fire and decorators can be used #70
Comments
A couple other things worth noting:
|
Thanks for this really nice writeup. This module is implemented the way it is because it was extremely simple to implement. In order to get the hook system to comply, we might have to implement this in Fastify itself. Note that the current hook system is designed for a request/response pattern, so something that works for websockets might be something slightly different, If you are keen to work on this problem, I'll be very happy to review. |
I love the structure of this plugin, but having an easy way to share session state between sockets/requests is the only thing I'm missing. Access to |
I'd like to work on this feature but I'm still a little uncertain of how it would be best accomplished. @mcollina, It'd be of great help if you can give me any indication on what you think would be a viable approach to get the hook system to comply. |
@AyoubElk this feature should be designed from scratch. I do not have an API in mind. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
I haven't made any progress on this but it is worth mentioning one bit of prior art from the Ruby world which is |
I'll be working on this feature and I wanted to get some feedback on how I'm thinking of implementing it before I get started:
|
That makes sense to me! What do you think about creating a With that in place, I think websocket handlers could just be totally normal handlers in the same router, because you can use this: https://www.npmjs.com/package/ws#multiple-servers-sharing-a-single-https-server to upgrade one request at a time. You'd do |
To be honest it's still unfamiliar to the end user on how the api is implemented. Websockets have urls, have everything to make it more like the a http method. fastify.ws('/:urlParams', (request, ws) => {
// reply can be the socket object,
// the method itself is called upon the connection object
// ws.send({msg: 'hello from server'})
}) Nobody needs to know that websockets is actually a get request upgrade. |
@adminy can you be more specific about what you'd like to see? I don't really understand.
I kind of disagree. That's how they work, there's no other way to initiate them, you can't around this. Let's say you want to build authentication for websocket connections to your server. If your server already serves normal authenticated HTTP requests, you already have some way to look at an HTTP request and figure out who is making it and if you trust them, lets say through cookies and |
An alternative api where you can say Your security example is a middleware problem. I was only talking about the request api. I can write a polyfill myself like so: fastify.ws = (url, cb) => {
fastify.get(url, { websocket: true }, (connection, req, params) => {
req.params = params
cb(req, connection.socket)
})
} |
I see what you mean, it does remove some noise for creating websocket handlers, but I think the mission of this library should be to make more possible as opposed to just making the common case easier. I think some folks might want access to the |
Cool, let me know when this PR makes it into the release, otherwise I'll have an unexpexted upgrade which breaks the working version. |
🚀 Feature Proposal
fastify-websocket
currently passes the rawhttp.IncomingMessage
into websocket route handlers, not aFastifyRequest
object. I think instead passing aFastifyRequest
to handlers would improve a number of things.Motivation
First off, it is unfortunate to not have access to
FastifyRequest
's basic helpers. The higher level object is more useful than the rawIncomingMessage
and has some handy doodads for getting say route params or the logger to work with. Second, fastify promotes and has a really healthy ecosystem of things that decorateFastifyRequest
that websocket handlers also can't access. Things like a session fromfastify-secure-session
, utilities fromfastify-url-data
, or user-land decorators to get a database client or what have you aren't available in route handlers.Finally, it's unfortunate that hooks don't run for websocket handlers. We'd have to discuss semantically how this might work, but, if we could come up with sane semantics for this, it'd be really handy. I want to use hooks to implement authorization for example -- deny requests based on the presence of a session value or whatever. This same logic needs to apply to work done over normal HTTP requests as well as work done over websocket connections, but currently I have to duplicate it in a hook and in a
verifyClient
option. One place (especially one place that had access to decorators) would be simpler.I also think there's an argument to be made that websocket handlers being different like this violates the principle of least surprise.
How
This'd definitely be a breaking change, so knowing that, we'd either introduce a new API or just do a major version bump. With that, I think it'd be possible to actually implement this by using
ws
ability to bind to an existinghttp.Server
, as is detailed here: https://www.npmjs.com/package/ws#external-https-serverI think for an
UPGRADE
request we'd probably not want to provide aFastifyReply
object, or we'd want to change the API to useFastifyReply
to actually start the websocket connection. I think there's really only one thing you want to do with an upgrade request, which is delegate it to the websocket server, so I think having to do that manually isn't really worth it, and that it's a special enough scenario that having a different handler signature is actually a good thing anyways. So I'd suggest having websocket handlers look pretty similar to how the do right now.Hooks wise, the semantics that make sense to me are firing everything up until the reply is sending. So,
onRequest
,preParsing
,preValidation
,preHandler
,preSerialization
, andonError
could all be relied on, butonSend
andonResponse
would never be called and would be documented as such. I am not really familiar with Fastify's internals enough to say how hard it would be to actually do this weird half-chain of hooks, but were that easy enough, this makes sense to me.Context
I don't really know why
fastify-websocket
works the way it does right now, but if I had to guess, I'd say it's because its really simple to implement. That's not a bad reason. I am finding that I have to do more work in userland because of this though, and I think implementing this inside the library instead of in bespoke and crappy ways outside it each time would save devs lots of time.Thoughts?
The text was updated successfully, but these errors were encountered: