frame.js 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. function StompFrame(frame) {
  2. if (frame === undefined) {
  3. frame = {};
  4. }
  5. this.command = frame.command || '';
  6. this.headers = frame.headers || {};
  7. this.body = frame.body || '';
  8. this.contentLength = -1;
  9. }
  10. StompFrame.prototype.toString = function() {
  11. return JSON.stringify({
  12. command: this.command,
  13. headers: this.headers,
  14. body: this.body
  15. });
  16. };
  17. StompFrame.prototype.send = function(stream) {
  18. // Avoid small writes, they get sent in their own tcp packet, which
  19. // is not efficient (and v8 does fast string concat).
  20. var frame = this.command + '\n';
  21. for (var key in this.headers) {
  22. frame += key + ':' + this.headers[key] + '\n';
  23. }
  24. if (this.body.length > 0) {
  25. if (!this.headers.hasOwnProperty('suppress-content-length')) {
  26. frame += 'content-length:' + Buffer.byteLength(this.body) + '\n';
  27. }
  28. }
  29. frame += '\n';
  30. if (this.body.length > 0) {
  31. frame += this.body;
  32. }
  33. frame += '\0';
  34. if(frame)
  35. stream.write(frame);
  36. };
  37. StompFrame.prototype.setCommand = function(command) {
  38. this.command = command;
  39. };
  40. StompFrame.prototype.setHeader = function(key, value) {
  41. this.headers[key] = value;
  42. if (key.toLowerCase() === 'content-length') {
  43. this.contentLength = parseInt(value);
  44. }
  45. };
  46. StompFrame.prototype.appendToBody = function(data) {
  47. this.body += data;
  48. };
  49. StompFrame.prototype.validate = function(frameConstruct) {
  50. var frameHeaders = Object.keys(this.headers);
  51. // Check validity of frame headers
  52. for (var header in frameConstruct.headers) {
  53. var headerConstruct = frameConstruct.headers[header];
  54. // Check required (if specified)
  55. if (headerConstruct.hasOwnProperty('required') && headerConstruct.required === true) {
  56. if (frameHeaders.indexOf(header) === -1) {
  57. return {
  58. isValid: false,
  59. message: 'Header "' + header + '" is required for '+this.command,
  60. details: 'Frame: ' + this.toString()
  61. };
  62. }
  63. }
  64. // Check regex of header value (if specified)
  65. if (headerConstruct.hasOwnProperty('regex') && frameHeaders.indexOf(header) > -1) {
  66. if (!this.headers[header].match(headerConstruct.regex)) {
  67. return {
  68. isValid: false,
  69. message: 'Header "' + header + '" has value "' + this.headers[header] + '" which does not match against the following regex: ' + headerConstruct.regex + ' (Frame: ' + this.toString() + ')'
  70. };
  71. }
  72. }
  73. }
  74. return { isValid: true };
  75. };
  76. exports.StompFrame = StompFrame;