All files / lib/checkers http.js

96.87% Statements 31/32
100% Branches 8/8
88.88% Functions 8/9
100% Lines 31/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82    1x   1x 1x                         12x 12x     12x 12x     12x         11x     11x 11x     11x     11x     11x 11x   11x 11x       1x   1x 1x 1x 1x         11x 10x 4x   6x           11x 13x 9x   4x         1x
'use strict';
/* global fetch */
const validator = require('validator');
 
const Result = require('../result');
const checker = require('../checker');
 
/**
 * Health check a http resource.
 *
 * @param {Object} setup: http check setup with fields:
 * - uri: a resource URI to check
 * - statusCodes: an array of acceptable status codes, OK when result matches any of these codes
 * - texts: an array of texts that should exist in the response body, OK when all texts exist
 * - timeout: request timeout in milliseconds, if unspecified defaults to 30000ms
 * @param {Function} cb: standard cb(err, result) callback
 */
function check(setup, cb) {
    const method = setup.method || 'get';
    const timeout = setup.timeout || 30000; // Default 30 seconds
 
    // Create AbortController for timeout handling
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);
 
    // Make the request using fetch
    fetch(setup.uri, {
        method: method.toUpperCase(),
        signal: controller.signal
    })
        .then(response => {
            clearTimeout(timeoutId);
 
            // Get response body as text
            return response.text().then(body => {
                const result = new Result();
 
                // Check status codes
                checker.checkAttribute('statusCode', setup, _checkStatusCode(response.status), result);
 
                // Check response text
                checker.checkAttribute('text', setup, _checkText(body), result);
 
                // Add response info
                result.addInfo('headers', Object.fromEntries(response.headers.entries()));
                result.addInfo('body', body);
 
                result.setStatusByStats();
                cb(null, result);
            });
        })
        .catch(error => {
            clearTimeout(timeoutId);
 
            const result = new Result();
            result.addError(error.message);
            result.setStatusByStats();
            cb(null, result);
        });
}
 
function _checkStatusCode(actual) {
    return function (expected) {
        if (validator.matches(actual.toString(), new RegExp(expected))) {
            return 'Status code ' + expected + ' as expected';
        } else {
            throw new Error('Status code ' + actual + ' does not match the expected ' + expected);
        }
    };
}
 
function _checkText(actual) {
    return function (expected) {
        if (validator.matches(actual, new RegExp(expected))) {
            return 'Text ' + expected + ' exists in response body';
        } else {
            throw new Error('Text ' + expected + ' does not exist in response body');
        }
    };
}
 
exports.check = check;