-
-
Notifications
You must be signed in to change notification settings - Fork 75
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
feat: add message validation #191
Conversation
index.js
Outdated
const connection = WebSocket.createWebSocketStream(socket, opts.connectionOptions) | ||
socket.afterDuplex = true | ||
socket.validator = request && request.context.schema ? fastify.validatorCompiler({ schema: request.context.schema.body }) : null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should move to onRoute
hook. It compiles on every request which is not optimal.
// onRoute hook
const kWebSocketSchema = Symbol('websocket-body-schema')
requset.context[kWebSocketSchema] = routeOption.schema && routeOption.schema.body ? fastify.validatorCompiler({ schema: routeOption.schema.body }) : null
// here
socket.validator = requset.context[kWebSocketSchema]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you emit an event in case a packet is dropped?
In a case of |
@zekth I see why you'd want to do this but I am wondering if this could be done completely in userland or in a separate package. Not super opposed to merging this, but this implementation has to make a few big assumptions:
I can contrive situations where each one of those things is not true. If any of those are not true, the developer has to go back to square one and write validation code themselves -- dunno how likely they are or how likely the happy path is where this thing helps. But because it hasn't come up a lot, I am a little hesitant to stick it right in the mainline code. It also requires some kinda ugly stuff like setting those properties on the socket. One other thing we could do would be to add the facilities to make this possible and nice in userland, and then add examples that show how you might validation json yourself to the docs, as well as showing how you might validate |
I don't get why some people would want to validate only a subset of messages
Would you change your route schema on the fly?
currently indeed it validates only the JSON, but using the schema definition we can validate any type, this case juste needs to be handled too.
What would be a better approach?
How would you achieve that? Seems like a bad DX as the user won't have the benefit of using the tools that Main idea behind this feature is to be able to build AsyncApi specs like: https://www.asyncapi.com/blog/websocket-part2 |
Sometimes other systems are already doing validation and hand you back strings to send, like
No, but for stateful connections like a websocket, you might enter different phases of the connection that only accept certain message types at certain times. Lots of wire protocols have modes where they flip from some structured message format to a binary stream for a while, like Postgres' COPY instruction
That's kinda what I am saying -- this is a maximalist approach, do we want that? I am ok if we do, it just increases the maintenance burden here for a potentially narrow set of use cases which require it.
|
I think we are in a chicken vs egg problem in here. Is there a reason not to push forward api contracts and message validation over websocket?
With this approach there is no need for this feature in the end, because anybody can use their own validator in the end.
But the logic is in |
Any thoughts @mcollina ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docs are missing.
I'm ok with adding this feature. It fits with the ethos of Fastify and I would use it in a few places myself.
@@ -200,7 +205,46 @@ function close (fastify, done) { | |||
server.close(done) | |||
} | |||
|
|||
class ValidateWebSocket extends WebSocket { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to a separate file in lib
@@ -119,10 +122,12 @@ function fastifyWebsocket (fastify, opts, next) { | |||
// we always override the route handler so we can close websocket connections to routes to handlers that don't support websocket connections | |||
// This is not an arrow function to fetch the encapsulated this | |||
routeOptions.handler = function (request, reply) { | |||
request.context[kWebSocketSchema] = request.context.schema ? fastify.validatorCompiler({ schema: request.context.schema.body }) : null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not reuse body, but use a different property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're not using body
property the issue is the validator will not be available because the fastify instance won't compute and expose it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we need to expose something more from Fastify to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. I'll make a proposal in fastify
return this.close(1003, 'Unsupported payload') | ||
} else { | ||
return this.send('Unsupported payload') | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of adding a strict flag, make the validation error handling configurable.
fix: #190
First implementation. Basically the use would be:
This also adds 2 way of handling the validation errors with the
strictMode
. If is set totrue
it closes the connection with a1003
code, otherwise it sends the validator errors in the payload.Kudos to @climba03003 who helped a lot
Checklist
npm run test
andnpm run benchmark
and the Code of conduct