root / HServer / 00.Server / 00.Program / node_modules / fresh / index.js
이력 | 보기 | 이력해설 | 다운로드 (2.65 KB)
| 1 |
/*!
|
|---|---|
| 2 |
* fresh
|
| 3 |
* Copyright(c) 2012 TJ Holowaychuk
|
| 4 |
* Copyright(c) 2016-2017 Douglas Christopher Wilson
|
| 5 |
* MIT Licensed
|
| 6 |
*/
|
| 7 |
|
| 8 |
'use strict'
|
| 9 |
|
| 10 |
/**
|
| 11 |
* RegExp to check for no-cache token in Cache-Control.
|
| 12 |
* @private
|
| 13 |
*/
|
| 14 |
|
| 15 |
var CACHE_CONTROL_NO_CACHE_REGEXP = /(?:^|,)\s*?no-cache\s*?(?:,|$)/ |
| 16 |
|
| 17 |
/**
|
| 18 |
* Module exports.
|
| 19 |
* @public
|
| 20 |
*/
|
| 21 |
|
| 22 |
module.exports = fresh |
| 23 |
|
| 24 |
/**
|
| 25 |
* Check freshness of the response using request and response headers.
|
| 26 |
*
|
| 27 |
* @param {Object} reqHeaders
|
| 28 |
* @param {Object} resHeaders
|
| 29 |
* @return {Boolean}
|
| 30 |
* @public
|
| 31 |
*/
|
| 32 |
|
| 33 |
function fresh (reqHeaders, resHeaders) { |
| 34 |
// fields
|
| 35 |
var modifiedSince = reqHeaders['if-modified-since'] |
| 36 |
var noneMatch = reqHeaders['if-none-match'] |
| 37 |
|
| 38 |
// unconditional request
|
| 39 |
if (!modifiedSince && !noneMatch) {
|
| 40 |
return false |
| 41 |
} |
| 42 |
|
| 43 |
// Always return stale when Cache-Control: no-cache
|
| 44 |
// to support end-to-end reload requests
|
| 45 |
// https://tools.ietf.org/html/rfc2616#section-14.9.4
|
| 46 |
var cacheControl = reqHeaders['cache-control'] |
| 47 |
if (cacheControl && CACHE_CONTROL_NO_CACHE_REGEXP.test(cacheControl)) {
|
| 48 |
return false |
| 49 |
} |
| 50 |
|
| 51 |
// if-none-match
|
| 52 |
if (noneMatch && noneMatch !== '*') { |
| 53 |
var etag = resHeaders['etag'] |
| 54 |
|
| 55 |
if (!etag) {
|
| 56 |
return false |
| 57 |
} |
| 58 |
|
| 59 |
var etagStale = true |
| 60 |
var matches = parseTokenList(noneMatch)
|
| 61 |
for (var i = 0; i < matches.length; i++) { |
| 62 |
var match = matches[i]
|
| 63 |
if (match === etag || match === 'W/' + etag || 'W/' + match === etag) { |
| 64 |
etagStale = false
|
| 65 |
break
|
| 66 |
} |
| 67 |
} |
| 68 |
|
| 69 |
if (etagStale) {
|
| 70 |
return false |
| 71 |
} |
| 72 |
} |
| 73 |
|
| 74 |
// if-modified-since
|
| 75 |
if (modifiedSince) {
|
| 76 |
var lastModified = resHeaders['last-modified'] |
| 77 |
var modifiedStale = !lastModified || !(parseHttpDate(lastModified) <= parseHttpDate(modifiedSince))
|
| 78 |
|
| 79 |
if (modifiedStale) {
|
| 80 |
return false |
| 81 |
} |
| 82 |
} |
| 83 |
|
| 84 |
return true |
| 85 |
} |
| 86 |
|
| 87 |
/**
|
| 88 |
* Parse an HTTP Date into a number.
|
| 89 |
*
|
| 90 |
* @param {string} date
|
| 91 |
* @private
|
| 92 |
*/
|
| 93 |
|
| 94 |
function parseHttpDate (date) { |
| 95 |
var timestamp = date && Date.parse(date)
|
| 96 |
|
| 97 |
// istanbul ignore next: guard against date.js Date.parse patching
|
| 98 |
return typeof timestamp === 'number' |
| 99 |
? timestamp |
| 100 |
: NaN
|
| 101 |
} |
| 102 |
|
| 103 |
/**
|
| 104 |
* Parse a HTTP token list.
|
| 105 |
*
|
| 106 |
* @param {string} str
|
| 107 |
* @private
|
| 108 |
*/
|
| 109 |
|
| 110 |
function parseTokenList (str) { |
| 111 |
var end = 0 |
| 112 |
var list = []
|
| 113 |
var start = 0 |
| 114 |
|
| 115 |
// gather tokens
|
| 116 |
for (var i = 0, len = str.length; i < len; i++) { |
| 117 |
switch (str.charCodeAt(i)) {
|
| 118 |
case 0x20: /* */ |
| 119 |
if (start === end) {
|
| 120 |
start = end = i + 1
|
| 121 |
} |
| 122 |
break
|
| 123 |
case 0x2c: /* , */ |
| 124 |
list.push(str.substring(start, end)) |
| 125 |
start = end = i + 1
|
| 126 |
break
|
| 127 |
default:
|
| 128 |
end = i + 1
|
| 129 |
break
|
| 130 |
} |
| 131 |
} |
| 132 |
|
| 133 |
// final token
|
| 134 |
list.push(str.substring(start, end)) |
| 135 |
|
| 136 |
return list
|
| 137 |
} |