You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
2.6 KiB

7 years ago
  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, i) {
  7. return parseEncoding(e.trim(), i);
  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, i) {
  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. i: i
  55. };
  56. }
  57. function getEncodingPriority(encoding, accepted) {
  58. return (accepted.map(function(a) {
  59. return specify(encoding, a);
  60. }).filter(Boolean).sort(function (a, b) {
  61. if(a.s == b.s) {
  62. return a.q > b.q ? -1 : 1;
  63. } else {
  64. return a.s > b.s ? -1 : 1;
  65. }
  66. })[0] || {s: 0, q: 0});
  67. }
  68. function specify(encoding, spec) {
  69. var s = 0;
  70. if(spec.encoding.toLowerCase() === encoding.toLowerCase()){
  71. s |= 1;
  72. } else if (spec.encoding !== '*' ) {
  73. return null
  74. }
  75. return {
  76. s: s,
  77. q: spec.q,
  78. }
  79. };
  80. function preferredEncodings(accept, provided) {
  81. accept = parseAcceptEncoding(accept || '');
  82. if (provided) {
  83. return provided.map(function(type) {
  84. return [type, getEncodingPriority(type, accept)];
  85. }).filter(function(pair) {
  86. return pair[1].q > 0;
  87. }).sort(function(a, b) {
  88. var pa = a[1];
  89. var pb = b[1];
  90. return (pb.q - pa.q) || (pb.s - pa.s) || (pa.i - pb.i);
  91. }).map(function(pair) {
  92. return pair[0];
  93. });
  94. } else {
  95. return accept.sort(function (a, b) {
  96. // revsort
  97. return (b.q - a.q) || (a.i - b.i);
  98. }).filter(function(type){
  99. return type.q > 0;
  100. }).map(function(type) {
  101. return type.encoding;
  102. });
  103. }
  104. }