How to create a connectivity dashboard with AJAX
I will make a connectivity dashboard to check a server’s condition and port status in this post.
Part 1: Create an index.php file
First, create a main index.php file.
<?php
/*
echo sitestatus('https://cloud.gabrielkheisa.xyz');
echo sitestatus('https://iot.gabrielkheisa.xyz');
echo sitestatus('https://gabrielkheisa.xyz');
echo sitestatus('https://gaabrielkheisa.xyz');
echo sitecheck('https://cloud.gabrielkheisa.xyz');
echo sitecheck('https://iot.gabrielkheisa.xyz');
echo sitecheck('https://gabrielkheisa.xyz');
echo sitecheck('https://gaabrielkheisa.xyz');
*/
?>
<!DOCTYPE html>
<html>
<link rel="icon" type="image/png" href="pubsub_st.png">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<title>Online status external</title>
<style>
.center {
margin: auto;
width: 50%;
padding: 10px;
}
body {
transition: 0.5s;
}
@media only screen and (max-width: 1100px){
body {
font-size:4em;
}
h2 {
font-size:1.5em;
text-align: center;
}
h4 {
font-size:0.8em;
}
h5 {
font-size:0.8em;
}
input {
font-size:1em !important;
}
select {
font-size:0.8em !important;
}
.center {
margin: 5px;
width: 100%;
padding: 10px;
}
#tombol{
font-size:1em !important;
}
.progress {
height:50px !important;
}
}
</style>
<body>
<h2 class="d-flex justify-content-center mt-5">Server status</h2>
<div id="the_wrapper" class="center" style="max-width:1200px;">
<br>
<h5 class="d-flex m-3">Portofolio website : <p id="a">...</p></h5>
<h5 class="d-flex m-3">IoT server : <p id="b">...</p></h5>
<h5 class="d-flex m-3">File server : <p id="c">...</p></h5>
<h5 class="d-flex m-3">Blog server : <p id="d">...</p></h5>
<h5 class="d-flex m-3">Discontinued VPN : <p id="zzz">...</p></h5>
</div>
<h2 class="d-flex justify-content-center mt-5">Security check</h2>
<div id="the_wrapper" class="center" style="max-width:1200px;">
<br>
<h5 class="d-flex m-3">Remote SQL : <p id="aaa">...</p></h5>
<h5 class="d-flex m-3">Direct Control Panel : <p id="bbb">...</p></h5>
<h5 class="d-flex m-3">SSH : <p id="ccc">...</p></h5>
<h5 class="d-flex m-3">MQTT : <p id="ddd">...</p></h5>
</div>
<h2 class="d-flex justify-content-center mt-5">Other status</h2>
<div id="the_wrapper" class="center" style="max-width:1200px;">
<br>
<h5 class="d-flex m-3">Steam : <p id="aa">...</h5>
</div>
<script>
function modif(element){
if (element.innerHTML == "Offline" || element.innerHTML == "Exposed") {
element.classList.add("text-danger");
}
else {
element.classList.add("text-success");
}
}
function get_php(str, the_id) {
if (str.length == 0) {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById(the_id).innerHTML = this.responseText;
}
};
xmlhttp.open("GET", "check.php?q=" + str, true);
xmlhttp.send();
}
}
function timeout() {
setTimeout(function () {
modif(document.getElementById("a"));
modif(document.getElementById("b"));
modif(document.getElementById("c"));
modif(document.getElementById("d"));
modif(document.getElementById("zzz"));
modif(document.getElementById("aaa"));
modif(document.getElementById("bbb"));
modif(document.getElementById("ccc"));
modif(document.getElementById("ddd"));
modif(document.getElementById("aa"));
timeout();
}, 80);
}
function timeout2() {
setTimeout(function () {
get_php("1", "a");
get_php("2", "b");
get_php("3", "c");
get_php("4", "d");
get_php("5", "zzz");
get_php("111", "aaa");
get_php("222", "bbb");
get_php("333", "ccc");
get_php("444", "ddd");
get_php("11", "aa");
timeout2();
}, 10000);
}
timeout();
timeout2();
</script>
</body>
</html>
In this code, I use this AJAX method to get value from another file named check.php which we will discuss later. In this get_php(str, the_id) function, the str variable will work as a query parameter that will select what kind of data will be chosen from check.php and the_id is the id value of the div that has innerHTML property that will be modified from the output of responseText from check.php.
...
function get_php(str, the_id) {
if (str.length == 0) {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById(the_id).innerHTML = this.responseText;
}
};
xmlhttp.open("GET", "check.php?q=" + str, true);
xmlhttp.send();
}
}
...
In other words, this get_php() function will modify a div and display the output of check.php.
...
<h5 class="d-flex m-3">Portofolio website : <p id="a">OUTPUT FROM QUERY PARMETER "1" GOES HERE</p></h5>
...
...
get_php("1", "a");
...
Next, we have this part to get data every 10 seconds.
...
function timeout2() {
setTimeout(function () {
get_php("1", "a"); // query 1, data 1
get_php("2", "b"); // query 2, data 2
get_php("3", "c"); // query 3, data 3
get_php("4", "d"); // ...
get_php("5", "zzz");
get_php("111", "aaa");
get_php("222", "bbb");
get_php("333", "ccc");
get_php("444", "ddd");
get_php("11", "aa");
timeout2();
}, 10000);
}
...
...
timeout2();
...
Part 2: Create a check.php file
check.php
<?php
// Allow from any origin
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0);
}
//Query params
$q = $_REQUEST["q"];
function getsteamstatus(){
$content=file_get_contents("https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=*******&format=json&steamids=*****");
$array = json_decode ($content, true);
$steamstatus = $array['response']['players'][0]['personastate'];
$steamgame = $array['response']['players'][0]['gameextrainfo'];
if($steamstatus == "1"){
if($steamgame != "")
return "Online, playing " . $steamgame;
else {
return "Online";
}
}
else if($steamstatus == "3"){
if($steamgame != "")
return "Away, playing " . $steamgame;
else {
return "Away";
}
}
else {
return "Offline";
}
}
function sitestatus($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
curl_setopt($ch, CURLOPT_NOBODY, true); // we don't need body
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $url . ', HTTP code: ' . $httpcode . "<br>";
}
function sitecheck($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
curl_setopt($ch, CURLOPT_NOBODY, true); // we don't need body
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if(strval($httpcode) == "0" || strval($httpcode) == "408" || strval($httpcode) == "504") {
return "Offline";
}
return "Online";
}
function securecheck($url, $port) {
if(fsockopen($url,$port))
{
return "Exposed";
}
else
{
return "Ok";
}
}
switch($q){
case "1" :
echo sitecheck('https://gabrielkheisa.xyz');
break;
case "2" :
echo sitecheck('https://iot.gabrielkheisa.xyz');
break;
case "3" :
echo sitecheck('https://cloud.gabrielkheisa.xyz');
break;
case "4" :
echo sitecheck('https://blog.gabrielkheisa.xyz');
break;
case "5" :
echo sitecheck('https://gabrielkheisalwejfklergj.xyz');
break;
case "111" :
echo securecheck("theserver.gabrielkheisa.xyz", 3306);
break;
case "222" :
echo securecheck("theserver.gabrielkheisa.xyz", 10000);
break;
case "333" :
echo securecheck("theserver.gabrielkheisa.xyz", 22);
break;
case "444" :
echo securecheck("theserver.gabrielkheisa.xyz", 1883);
break;
case "11" :
echo getsteamstatus();
break;
}
?>
Let’s look at the switch($q) part. This switch-case receive input from $_REQUEST[“q”] from str parameter from get_php(str, the_id). For example, I execute this get_php(“2”, “b”) from previous index.php file. It will go to status.php with a parameter of “2”. The output from status.php because of the case “2” would be the return value of sitecheck(‘https://iot.gabrielkheisa.xyz’)
...
case "2" :
echo sitecheck('https://iot.gabrielkheisa.xyz');
break;
...
What will sitecheck() function do? It will initiate cURL and the output would be the HTTP code of that sent cURL.
...
if(strval($httpcode) == "0" || strval($httpcode) == "408" || strval($httpcode) == "504") {
return "Offline";
}
return "Online";
...
The most common successful HTTP response is HTTP 200. I’ll consider HTTP 2xx codes as a responding server (online). If the server is unreachable or server-error 5xx (I’ll consider this as offline), then it will return 0, 4xx, or 5xx.
How about securecheck() function? Basically, it just checks many ports that are open or at least have running services. fsockopen($url,$port), based on the server’s hostname, $url, and its $port, fsockopen() will return true if its port is open, meaning one of its services is accessible from the internet.
function securecheck($url, $port) {
if(fsockopen($url,$port))
{
return "Exposed"; // port open, accessible from the internet
}
else
{
return "Ok"; // port closed, not accessible from the internet
}
}
Part 3: Preview
Here’s the preview of my server’s status and another (optional) Steam status using API parsing.
Reference: