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.
		
		
		
		
		
			
		
			
				
					80 lines
				
				1.8 KiB
			
		
		
			
		
	
	
					80 lines
				
				1.8 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function negotiate (header, supportedEncodings) {
							 | 
						||
| 
								 | 
							
								  if (!header) {
							 | 
						||
| 
								 | 
							
								    return undefined
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  const supportedEncodingMap = createMap(supportedEncodings)
							 | 
						||
| 
								 | 
							
								  const acceptedEncodings = parse(header)
							 | 
						||
| 
								 | 
							
								    .sort((a, b) => comparator(a, b, supportedEncodingMap))
							 | 
						||
| 
								 | 
							
								    .filter(isNonZeroQuality)
							 | 
						||
| 
								 | 
							
								  return determinePreffered(acceptedEncodings, supportedEncodingMap)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function determinePreffered (acceptedEncodings, supportedEncodings) {
							 | 
						||
| 
								 | 
							
								  for (const encoding of acceptedEncodings) {
							 | 
						||
| 
								 | 
							
								    const selected = supportedEncodings[encoding.name]
							 | 
						||
| 
								 | 
							
								    if (selected) {
							 | 
						||
| 
								 | 
							
								      return selected.encoding
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return null
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function createMap (supported) {
							 | 
						||
| 
								 | 
							
								  const supportedEncodings = {}
							 | 
						||
| 
								 | 
							
								  let priority = 0
							 | 
						||
| 
								 | 
							
								  if (supported.length > 0) {
							 | 
						||
| 
								 | 
							
								    supportedEncodings['*'] = { encoding: supported[0], priority }
							 | 
						||
| 
								 | 
							
								    priority++
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  for (const encoding of supported) {
							 | 
						||
| 
								 | 
							
								    supportedEncodings[encoding] = { encoding, priority }
							 | 
						||
| 
								 | 
							
								    priority++
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return supportedEncodings
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function parse (header) {
							 | 
						||
| 
								 | 
							
								  const split = header.split(',')
							 | 
						||
| 
								 | 
							
								  return split.map(parseEncoding)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function isNonZeroQuality (encoding) {
							 | 
						||
| 
								 | 
							
								  return encoding.quality !== 0
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function parseEncoding (encoding) {
							 | 
						||
| 
								 | 
							
								  const [name, second] = encoding.trim().split(';')
							 | 
						||
| 
								 | 
							
								  const quality = getQuality(second)
							 | 
						||
| 
								 | 
							
								  return {
							 | 
						||
| 
								 | 
							
								    name,
							 | 
						||
| 
								 | 
							
								    quality
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function getQuality (second) {
							 | 
						||
| 
								 | 
							
								  if (!second) {
							 | 
						||
| 
								 | 
							
								    return 1
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  const [, quality] = second.trim().split('=')
							 | 
						||
| 
								 | 
							
								  return parseFloat(quality)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function comparator (a, b, supportedEncodingMap) {
							 | 
						||
| 
								 | 
							
								  if (a.quality === b.quality) {
							 | 
						||
| 
								 | 
							
								    if (supportedEncodingMap[a.name] &&
							 | 
						||
| 
								 | 
							
								      supportedEncodingMap[b.name] &&
							 | 
						||
| 
								 | 
							
								      supportedEncodingMap[a.name].priority < supportedEncodingMap[b.name].priority) {
							 | 
						||
| 
								 | 
							
								      return -1
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      return 1
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return b.quality - a.quality
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								  negotiate
							 | 
						||
| 
								 | 
							
								}
							 |