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

handleUpgrade() and undefined upgrade header #1838

Closed
FranckFreiburger opened this issue Jan 28, 2021 · 9 comments
Closed

handleUpgrade() and undefined upgrade header #1838

FranckFreiburger opened this issue Jan 28, 2021 · 9 comments

Comments

@FranckFreiburger
Copy link

req.headers.upgrade.toLowerCase() !== 'websocket' ||

req.headers.upgrade may be undefined, that will raise TypeError: Cannot read property 'toLowerCase' of undefined

@lpinca
Copy link
Member

lpinca commented Jan 28, 2021

It can only happen if the req argument is not an upgrade request. wss.handleUpgrade() must be called from the listener of the 'upgrade' event.

httpServer.on('upgrade', function (req, socket, head) {
  // Here `req.headers.upgrade` cannot be `undefined`, otherwise there is a bug in Node.js.
  wss.handleUpgrade(req, socket, head, callback);
});

@lpinca
Copy link
Member

lpinca commented Jan 28, 2021

Please fill the issue template, it's there for a reason. Also, if you can, please write a test case using only ws to reproduce the issue.

@FranckFreiburger
Copy link
Author

Sorry for that, I created the issue from the code view (Reference in new issue), no model was requested.

@FranckFreiburger
Copy link
Author

FranckFreiburger commented Jan 28, 2021

In fact I am using handleUpgrade() in a get() handler of express :

app.get('/myWs', (req, res) => {
  wss.handleUpgrade(req, req.socket, [], handler);
})

Everything seems to work properly except for non-ws requests (that is expected of course)

@lpinca
Copy link
Member

lpinca commented Jan 28, 2021

Yes, you can't do that, it doesn't make sense. The HTTP parser is still attached to the http.IncomingMessage object (req) in your example.

I would even say that the thrown error is good in that case.

@FranckFreiburger
Copy link
Author

FranckFreiburger commented Jan 28, 2021

Thanks, however, I don't understand properly why it can't work (at least with upgrade requests only)
eg.

app.get('/myWs', (req, res) => {
	if ( req.get('upgrade')?.toLowerCase() !== 'websocket' )
		return void res.status(400).end();
	wss.handleUpgrade(req, req.socket, [], handler);
})

@lpinca
Copy link
Member

lpinca commented Jan 28, 2021

Because upgrade requests are used to upgrade to another protocol not HTTP and are handled differently by Node.js. When you use app.get() you are handling a request received via

httpServer.on('request', function (req, res) {});

Upgrade requests are handled with

httpServer.on('upgrade', function (req, socket, head) {});

and the socket in this case is freed.

In your example the socket is still piped to the HTTP parser so it might not work if the client writes something using a different protocol. Also there is no reason to keep the HTTP parser and the http.IncomingMessage objects alive for the new protocol.

@FranckFreiburger
Copy link
Author

ok I see, thanks !

@lpinca
Copy link
Member

lpinca commented Jan 28, 2021

I'm closing this as answered. Discussion can continue if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants