1 module.exports = preferredMediaTypes;
2 preferredMediaTypes.preferredMediaTypes = preferredMediaTypes;
4 function parseAccept(accept) {
5 var accepts = accept.split(',');
7 for (var i = 0, j = 0; i < accepts.length; i++) {
8 var mediaType = parseMediaType(accepts[i].trim(), i);
11 accepts[j++] = mediaType;
21 function parseMediaType(s, i) {
22 var match = s.match(/\s*(\S+?)\/([^;\s]+)\s*(?:;(.*))?/);
23 if (!match) return null;
27 full = "" + type + "/" + subtype,
32 params = match[3].split(';').map(function(s) {
33 return s.trim().split('=');
34 }).reduce(function (set, p) {
39 if (params.q != null) {
40 q = parseFloat(params.q);
55 function getMediaTypePriority(type, accepted, index) {
56 var priority = {o: -1, q: 0, s: 0};
58 for (var i = 0; i < accepted.length; i++) {
59 var spec = specify(type, accepted[i], index);
61 if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
69 function specify(type, spec, index) {
70 var p = parseMediaType(type);
77 if(spec.type.toLowerCase() == p.type.toLowerCase()) {
79 } else if(spec.type != '*') {
83 if(spec.subtype.toLowerCase() == p.subtype.toLowerCase()) {
85 } else if(spec.subtype != '*') {
89 var keys = Object.keys(spec.params);
90 if (keys.length > 0) {
91 if (keys.every(function (k) {
92 return spec.params[k] == '*' || (spec.params[k] || '').toLowerCase() == (p.params[k] || '').toLowerCase();
109 function preferredMediaTypes(accept, provided) {
110 // RFC 2616 sec 14.2: no header = */*
111 var accepts = parseAccept(accept === undefined ? '*/*' : accept || '');
114 // sorted list of all types
115 return accepts.filter(isQuality).sort(compareSpecs).map(function getType(spec) {
120 var priorities = provided.map(function getPriority(type, index) {
121 return getMediaTypePriority(type, accepts, index);
124 // sorted list of accepted types
125 return priorities.filter(isQuality).sort(compareSpecs).map(function getType(priority) {
126 return provided[priorities.indexOf(priority)];
130 function compareSpecs(a, b) {
131 return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
134 function isQuality(spec) {