encoding.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. module.exports = preferredEncodings;
  2. preferredEncodings.preferredEncodings = preferredEncodings;
  3. function parseAcceptEncoding(accept) {
  4. var acceptableEncodings;
  5. if (accept) {
  6. acceptableEncodings = accept.split(',').map(function(e) {
  7. return parseEncoding(e.trim());
  8. });
  9. } else {
  10. acceptableEncodings = [];
  11. }
  12. if (!acceptableEncodings.some(function(e) {
  13. return e && specify('identity', e);
  14. })) {
  15. /*
  16. * If identity doesn't explicitly appear in the accept-encoding header,
  17. * it's added to the list of acceptable encoding with the lowest q
  18. *
  19. */
  20. var lowestQ = 1;
  21. for(var i = 0; i < acceptableEncodings.length; i++){
  22. var e = acceptableEncodings[i];
  23. if(e && e.q < lowestQ){
  24. lowestQ = e.q;
  25. }
  26. }
  27. acceptableEncodings.push({
  28. encoding: 'identity',
  29. q: lowestQ / 2,
  30. });
  31. }
  32. return acceptableEncodings.filter(function(e) {
  33. return e;
  34. });
  35. }
  36. function parseEncoding(s) {
  37. var match = s.match(/^\s*(\S+?)\s*(?:;(.*))?$/);
  38. if (!match) return null;
  39. var encoding = match[1];
  40. var q = 1;
  41. if (match[2]) {
  42. var params = match[2].split(';');
  43. for (var i = 0; i < params.length; i ++) {
  44. var p = params[i].trim().split('=');
  45. if (p[0] === 'q') {
  46. q = parseFloat(p[1]);
  47. break;
  48. }
  49. }
  50. }
  51. return {
  52. encoding: encoding,
  53. q: q
  54. };
  55. }
  56. function getEncodingPriority(encoding, accepted) {
  57. return (accepted.map(function(a) {
  58. return specify(encoding, a);
  59. }).filter(Boolean).sort(function (a, b) {
  60. if(a.s == b.s) {
  61. return a.q > b.q ? -1 : 1;
  62. } else {
  63. return a.s > b.s ? -1 : 1;
  64. }
  65. })[0] || {s: 0, q: 0});
  66. }
  67. function specify(encoding, spec) {
  68. var s = 0;
  69. if(spec.encoding === encoding){
  70. s |= 1;
  71. } else if (spec.encoding !== '*' ) {
  72. return null
  73. }
  74. return {
  75. s: s,
  76. q: spec.q,
  77. }
  78. };
  79. function preferredEncodings(accept, provided) {
  80. accept = parseAcceptEncoding(accept || '');
  81. if (provided) {
  82. return provided.map(function(type) {
  83. return [type, getEncodingPriority(type, accept)];
  84. }).filter(function(pair) {
  85. return pair[1].q > 0;
  86. }).sort(function(a, b) {
  87. var pa = a[1];
  88. var pb = b[1];
  89. if(pa.q == pb.q) {
  90. return pa.s < pb.s ? 1 : -1;
  91. } else {
  92. return pa.q < pb.q ? 1 : -1;
  93. }
  94. }).map(function(pair) {
  95. return pair[0];
  96. });
  97. } else {
  98. return accept.sort(function (a, b) {
  99. // revsort
  100. return a.q < b.q ? 1 : -1;
  101. }).filter(function(type){
  102. return type.q > 0;
  103. }).map(function(type) {
  104. return type.encoding;
  105. });
  106. }
  107. }