subprotocol.js 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. 'use strict';
  2. const { tokenChars } = require('./validation');
  3. /**
  4. * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.
  5. *
  6. * @param {String} header The field value of the header
  7. * @return {Set} The subprotocol names
  8. * @public
  9. */
  10. function parse(header) {
  11. const protocols = new Set();
  12. let start = -1;
  13. let end = -1;
  14. let i = 0;
  15. for (i; i < header.length; i++) {
  16. const code = header.charCodeAt(i);
  17. if (end === -1 && tokenChars[code] === 1) {
  18. if (start === -1) start = i;
  19. } else if (
  20. i !== 0 &&
  21. (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
  22. ) {
  23. if (end === -1 && start !== -1) end = i;
  24. } else if (code === 0x2c /* ',' */) {
  25. if (start === -1) {
  26. throw new SyntaxError(`Unexpected character at index ${i}`);
  27. }
  28. if (end === -1) end = i;
  29. const protocol = header.slice(start, end);
  30. if (protocols.has(protocol)) {
  31. throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
  32. }
  33. protocols.add(protocol);
  34. start = end = -1;
  35. } else {
  36. throw new SyntaxError(`Unexpected character at index ${i}`);
  37. }
  38. }
  39. if (start === -1 || end !== -1) {
  40. throw new SyntaxError('Unexpected end of input');
  41. }
  42. const protocol = header.slice(start, i);
  43. if (protocols.has(protocol)) {
  44. throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
  45. }
  46. protocols.add(protocol);
  47. return protocols;
  48. }
  49. module.exports = { parse };