@curveball/kernel
Version:
Curveball is a framework writting in Typescript for Node.js
95 lines • 3.04 kB
JavaScript
/**
* This method will check the following request headers:
*
* 1. If-Match
* 2. If-None-Match
* 3. If-Modified-Since
* 4. If-Unmodified-Since
*
* To check these headers,v alues for lastModified and etag should be passed.
*
* The result of this function will return a suggested HTTP status. It will
* return
* * '200' if all the preconditions passed.
* * '304' is a 'Not Modified' status should be returned, and
* * '412' if a 'Precondition failed' error should be returned.
*/
export function conditionalCheck(request, lastModified, etag) {
validateETag(etag);
if (request.headers.has('If-Match')) {
return ifMatchCheck(request.headers.get('If-Match'), etag);
}
if (request.headers.has('If-None-Match')) {
return ifNoneMatchCheck(request.method, request.headers.get('If-None-Match'), etag);
}
if (request.headers.has('If-Modified-Since')) {
return ifModifiedSinceCheck(request.method, request.headers.get('If-Modified-Since'), lastModified);
}
if (request.headers.has('If-Unmodified-Since')) {
return ifUnmodifiedSinceCheck(request.headers.get('If-Unmodified-Since'), lastModified);
}
return 200;
}
function ifMatchCheck(header, serverState) {
if (header === '*') {
return serverState !== null ? 200 : 412;
}
const headerTags = header.split(',').map(foo => foo.trim());
for (const tag of headerTags) {
if (tag === serverState)
return 200;
}
return 412;
}
function ifNoneMatchCheck(method, header, serverState) {
let pass;
if (header === '*') {
pass = serverState === null;
}
else {
const headerTags = header.split(',').map(foo => foo.trim());
pass = true;
for (const tag of headerTags) {
if (tag === serverState) {
pass = false;
}
}
}
if (!pass) {
if (method === 'GET' || method === 'HEAD') {
return 304;
}
else {
return 412;
}
}
return 200;
}
function ifModifiedSinceCheck(method, header, serverState) {
if (method !== 'GET' && method !== 'HEAD') {
// Only GET and HEAD are supported, everything else is ignored
return 200;
}
if (serverState === null) {
return 200;
}
const headerDate = new Date(header);
return (serverState.getTime() > headerDate.getTime()) ? 200 : 304;
}
function ifUnmodifiedSinceCheck(header, serverState) {
// This is not in any spec, but I believe that we should reject requests
// if we don't know that the Last-Modified value is.
if (serverState === null) {
return 412;
}
const headerDate = new Date(header);
return (serverState.getTime() <= headerDate.getTime()) ? 200 : 412;
}
function validateETag(etag) {
if (etag === null)
return;
if (!/^(W\/)?"[\x21\x23-\x7e]+"$/.test(etag)) {
throw new Error('Etags must be valid. Did you forget the double-quotes?');
}
}
//# sourceMappingURL=conditional.js.map