{"action":"created","issue":{"url":"https://api.github.com/repos/nodejs/node/issues/6339","repository_url":"https://api.github.com/repos/nodejs/node","labels_url":"https://api.github.com/repos/nodejs/node/issues/6339/labels{/name}","comments_url":"https://api.github.com/repos/nodejs/node/issues/6339/comments","events_url":"https://api.github.com/repos/nodejs/node/issues/6339/events","html_url":"https://github.com/nodejs/node/issues/6339","id":150203086,"number":6339,"title":"http's 'upgrade' event should be handled one handler at a time","user":{"login":"SEAPUNK","id":4400726,"avatar_url":"https://avatars.githubusercontent.com/u/4400726?v=3","gravatar_id":"","url":"https://api.github.com/users/SEAPUNK","html_url":"https://github.com/SEAPUNK","followers_url":"https://api.github.com/users/SEAPUNK/followers","following_url":"https://api.github.com/users/SEAPUNK/following{/other_user}","gists_url":"https://api.github.com/users/SEAPUNK/gists{/gist_id}","starred_url":"https://api.github.com/users/SEAPUNK/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SEAPUNK/subscriptions","organizations_url":"https://api.github.com/users/SEAPUNK/orgs","repos_url":"https://api.github.com/users/SEAPUNK/repos","events_url":"https://api.github.com/users/SEAPUNK/events{/privacy}","received_events_url":"https://api.github.com/users/SEAPUNK/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/nodejs/node/labels/http","name":"http","color":"c7def8"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":10,"created_at":"2016-04-21T22:04:56Z","updated_at":"2016-04-24T00:45:11Z","closed_at":null,"body":"* **Subsystem**: http (maybe others)\r\n\r\nFrom what I understand, there is only one way to handle connection upgrades: with `http.Server`'s 'upgrade' event. However, from working on a WebSocket implementation, I noticed that there's (what I believe is) an architectural flaw with how the connection upgrades are handled:\r\n\r\nFrom the documentation:\r\n\r\n> Emitted each time a client requests a http upgrade. If this event isn't listened for, then clients requesting an upgrade will have their connections closed.\r\n\r\nFor example:\r\n\r\n```js\r\n// from the 'ws' module\r\nserver.on('upgrade', (req, socket, upgradeHead) => {\r\n  if (req.headers.upgrade !== 'websocket') {\r\n    // close or return?\r\n  }\r\n  // handle the websocket connection\r\n})\r\n\r\n\r\n// from another module that listens to a different type of upgrade\r\nserver.on('upgrade', (req, socket, upgradeHead) => {\r\n  if (req.headers.upgrade !=== 'some-other-protocol') {\r\n    // close or return?\r\n  }\r\n  // handle this connection\r\n})\r\n\r\n```\r\n\r\nIf the WebSocket isn't supposed to handle the socket, should the handler close the socket, or return in hopes that another upgrade handler handles the connection?\r\n\r\n...and I'm not even mentioning non-blocking calls within handlers, which could be done as a part of determining whether the socket connection should be handled by the handler.\r\n\r\nIf there is no other handler for the 'upgrade' event, the socket just stays idle until either the server or the client closes the connection, most likely via timeout (which in itself can cause problems if the timeout is specified to \"none\").\r\n\r\nWhile I do know that what I am suggesting is more than likely a breaking change, could upgrade handling be converted to (or something along the lines) to what is essentially a middleware setup, a bit like [connect](https://github.com/senchalabs/connect)? This way, the socket would only be handled by one handler at a time (blocking or non-blocking), a specific handler can withhold a socket it's handling from the other handlers (prevents conflicts), and if everything falls through, it can fall through to node.js's 'last' middleware, which closes the connection.\r\n\r\nWill something like this be possible?\r\n\r\n*edit:*\r\n\r\nOn my way back home, I realized that the 'connect' event is pretty much the same, and express mitigates it with connect + various libraries that write themselves around it, but I just felt that it could be more standardized in node so people who write libraries that use the event e.g. socket authors would be more convinced to add the option where the websocket handling is done as a middleware instead of an event handler. Either way, middleware (like Promise core API) would be nice."},"comment":{"url":"https://api.github.com/repos/nodejs/node/issues/comments/213858407","html_url":"https://github.com/nodejs/node/issues/6339#issuecomment-213858407","issue_url":"https://api.github.com/repos/nodejs/node/issues/6339","id":213858407,"user":{"login":"alexhultman","id":3397140,"avatar_url":"https://avatars.githubusercontent.com/u/3397140?v=3","gravatar_id":"","url":"https://api.github.com/users/alexhultman","html_url":"https://github.com/alexhultman","followers_url":"https://api.github.com/users/alexhultman/followers","following_url":"https://api.github.com/users/alexhultman/following{/other_user}","gists_url":"https://api.github.com/users/alexhultman/gists{/gist_id}","starred_url":"https://api.github.com/users/alexhultman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexhultman/subscriptions","organizations_url":"https://api.github.com/users/alexhultman/orgs","repos_url":"https://api.github.com/users/alexhultman/repos","events_url":"https://api.github.com/users/alexhultman/events{/privacy}","received_events_url":"https://api.github.com/users/alexhultman/received_events","type":"User","site_admin":false},"created_at":"2016-04-24T00:45:11Z","updated_at":"2016-04-24T00:45:11Z","body":"I guess you could use EventEmitter.listeners('the event') to get a copy of the array of listeners and check if you are the last entry. That should work but is very inefficient."}}