skip to Main Content

The following code pings an NGINX location block on my NGINX server to give you a health check status.

const ping = async () => {
  const url = `http://10.10.1.100/status`;
  const postData = {
    method: 'POST', // *GET, POST, PATCH, DELETE, etc.
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    headers: {
      'Content-Type': 'text/plain; charset=ASCII'
    },
    body: 'PING'
  }
    try {
      let factor = 1;
      let timeout = 3000; // ms
      let start = (new Date()).getTime();
      const request = await fetch(url, postData);
      let delta = new Date().getTime() - start;
      delta *= (factor || 1);
      if(delta > timeout) throw new Error(`PONG > ${timeout}ms. Server down?`);
      if(!request.ok) throw new Error(`${request.status} ${request.statusText}`);
      const response = await request.text();
      if(!response) throw new Error(`${response}`);
      document.getElementById('serverPongSpeed').innerText = `${delta.toFixed(0)}ms`;
      // Do Something...
      console.log(`%c${delta.toFixed(0)}ms ${response}`, "color: #c6ff00"); // Lime A400
    } catch (error) {
        console.log(error);
    }
}

The NGINX location block:

location = /status {
  access_log off;
  default_type text/plain;
  add_header "Access-Control-Allow-Methods" "POST";
  add_header "Content-Type" "text/plain";
  return 200 "PONG";
}

Right now I run it like this:

setInterval(ping, 3000); // Every 3 seconds

The problem is, during testing, when I turn off NGINX to see what happens the PING doesn’t break. It just keeps sending POST requests.

Maybe it’s an error I am not catching? Or maybe there is no error because the fetch has a greater timeout? Maybe setting a fetch timeout at 3 seconds would fire something for me to catch..

2

Answers


  1. Chosen as BEST ANSWER

    Below is a revised, complete example of the desired working solution.

    The javascript asynch await ping function:

    1. Ping function set to POST a request to NGINX /status location block.
    2. Ping function set to timeout at 300ms to indicate possible server down.
    3. Ping function set to indicate increased network latency using preset thresholds.
    4. Ping function set to catch network level error and any other unknown error.
    5. Ping function returns output to Console.

    ...

    window.onload = () => {
    
      let precision = 2; // decimals
      let pageLoadSpeed = ((window.performance.timing.domContentLoadedEventEnd - window.performance.timing.navigationStart) / 1000).toFixed(precision);
      document.getElementById('pageLoadSpeed').innerText = `${pageLoadSpeed}s`;
      console.log(`%cPage loaded in ${pageLoadSpeed} seconds.`, "color: #c6ff00"); // Lime A400
    
      let polling = null;
    
      // Network latency thresholds
      const settings = {
        pingInterval: 5000, // ms
        latency: {
          factor: 1.0, // Adjust latency to a percentage of its total
          high: 99, // ms
          moderate: 66, // ms
          low: 33, // ms
        },
        timeout: 300, // ms
        consoleLogLimit: 10,
        consoleLogCount: 0,
      };
    
      const ping = async() => {
    
        const url = `http://10.10.1.100/status`;
    
        const postData = {
          method: 'POST', // *GET, POST, PATCH, DELETE, etc.
          mode: 'cors', // no-cors, *cors, same-origin
          cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
          headers: {
            'Content-Type': 'text/plain; charset=ASCII'
          },
          body: 'PING'
        }
    
        try {
    
          const startWatch = (new Date()).getTime();
    
          const request = await fetch(url, postData);
    
          const stopWatch = (new Date().getTime() - startWatch) * (settings.latency.factor || 1);
    
          if (!request.ok) throw new Error(`${request.status} ${request.statusText}`);
    
          const response = await request.text();
    
          if (!response) throw new Error(`${response}`);
    
          if (stopWatch >= settings.timeout) {
            console.log(`%cPONG > ${settings.timeout}ms. Server down?`, "color: #d500f9"); // purple A400
          } else if (stopWatch >= settings.latency.high) {
            console.log(`%c${response}: ${stopWatch}ms High Latency`, "color: #ff1744"); // red A400
          } else if (stopWatch >= settings.latency.moderate) {
            console.log(`%c${response}: ${stopWatch}ms Moderate Latency`, "color: #ffc400"); // amber A400
          } else if (stopWatch <= settings.latency.low) {
            console.log(`%c${response}: ${stopWatch}ms Low Latency`, "color: #00e676"); // green A400
          }
    
          settings.consoleLogCount++;
    
          // Prevents browser from getting sluggish     
          if (settings.consoleLogCount == settings.consoleLogLimit + 1) {
            // Reset count
            settings.consoleLogCount = 0;
            // Clear console
            console.clear();
          }
    
        } catch (error) {
    
          // Catch network level error
          if (error instanceof TypeError && error.message == 'NetworkError when attempting to fetch resource.') {
    
            // Clear console
            // console.clear();
    
            console.error(`NGINX offline or Network cable unplugged?`);
    
            // Reset count
            settings.consoleLogCount = 0;
    
            // Stop polling
            clearInterval(polling);
    
          } else {
            // Catch any other error
            console.error(error);
          }
    
        }
    
      }
    
      polling = setInterval(ping, settings.pingInterval);
    
    }
    

    ...

    The NGINX server /status location block:

    1. End point set to accept POST only requests on /location end point.
    2. End point access log set to disabled because we don't really need to log this.
    3. End point set to respond with content type set to text/plain.
    4. End point set to accept POST requests from any origin.
    5. End point set to return a Content-Type of text/plain with a text "PONG" response on success.

    ...

    location = /status {
    
      access_log off;
    
      default_type text/plain;
    
      limit_except POST {
    
        deny all;
    
      }
    
      add_header Access-Control-Allow-Origin "*" always;
      add_header Access-Control-Allow-Methods "POST, OPTIONS" always;
      add_header Content-Type "text/plain" always;
    
      return 200 "PONG";
    
    }
    

  2. you can use ClearInterval() method like this:

      var interval = setInterval(ping, 3000);
      if(timeoutCounter > 3)
          clearInterval(interval)
    

    you need some more code to count the time outs/ errors.
    something like circuit breaker pattern

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search