Web Page Response Test With SMS Alert
This last week I encountered a challenge.
A client's domain accesses another website. Once in a while a page load times out with a gateway failure. It meant the remote website either was never reached or it did not respond before the browser gave up.
This happened intermittently, once or twice per day, at various times. The outage duration was from 1 to 20 minutes.
Intermittent errors are the toughest category of bug to find.
No matter how many ways duplicating the error is tried without the real error at hand, there is never full certainty that it was correctly addressed. Only when catching the error as it is happening can it be seen for what it actually is.
Nothing I tried duplicated the error in a way that I could use.
I had to catch the gateway failure while it was happening. And I did, with the PHP script I'm sharing with you today.
The PHP script tests the URL every number of minutes you specify. Each test is logged.
If the test results in a response other than HTTP 200, the script also logs additional information — all it has available at that point. And prints it in the browser window.
Further, to get your attention when a failure is occurring, the script also (each is optional):
Sends an SMS.
Sends an email.
Plays an MP3 sound.
Fades and restores a border color in the browser window every 3 seconds.
You can specify the optional responses depending on ways you want to be alerted when the script receives a non-200 HTML code from its test.
The PHP script repeatedly tests the URL you specify, every so many minutes. But when it encounters a non-200 HTTP code, any specified alerts are provided and the testing stops.
Here is the source code. Save it on your hard drive as 200tester.php
and then customize it as appropriate. Customization notes follow the source code.
<?php /* Web Page "200 OK" Tester October 10, 2021 Repeatedly text connection to HTTP url and, on failure, log and alert. Will Bontrager Software LLC */ /* Customization section */ $TestingURL = 'https://example.com/file.php'; $DataDumpDirectory = '/200test/URLtest.txt'; $MinutesBetweenTests = 4; $AudioURL = 'SoundFile.mp3'; // Optional $AlertFlashColor = 'red'; // Optional $EmailAddress = 'me@example.com'; // Optional $SMSemailAddress = '1234567890@sms.example.com'; // Optional $SMSfromAddress = 'me@example.com'; // Required only when $SMSemailAddress is specified. /* End of customization section */ mb_internal_encoding('UTF-8'); date_default_timezone_set('UTC'); ini_set('error_reporting', E_ALL); ini_set('display_errors', 1); $content = ''; $nowDate = date('r'); $dataSeparater = "\n==================\n\n"; $Info = GetWebPage($TestingURL,$content); $DataLine = "$nowDate-:-Code-:-{$Info['http_code']}-:-$TestingURL"; if( $Info['http_code'] == 200 ) { file_put_contents(__DIR__.$DataDumpDirectory,"$DataLine$dataSeparater",FILE_APPEND); ExitForReload($DataLine); } echo <<<DIV <div id="data-alert-container" style="margin:.5in; padding:.25in; border-width:.25in; border-style:solid; border-color:transparent; transition:border-color 2s; border-radius:.25in;"> DIV; if( (!empty($AudioURL)) ) { StartAudio($AudioURL); } if( (!empty($AlertFlashColor)) ) { StartAlertFlashColor($AlertFlashColor); } echo "<p>$DataLine</p>"; echo '<pre>'.print_r($Info,true).'</pre>'; $DataLine .= "\n" . print_r($Info,true); file_put_contents(__DIR__.$DataDumpDirectory,"$DataLine$dataSeparater",FILE_APPEND); if( (!empty($SMSemailAddress)) and strpos($SMSemailAddress,'@')>0 ) { if( strpos($SMSfromAddress,'@')===false ) { $SMSfromAddress = 'name@' . $_SERVER['SERVER_NAME']; } mail($SMSemailAddress,'','Non-200 response',"From: $SMSfromAddress"); } if( (!empty($EmailAddress)) and strpos($EmailAddress,'@')>0 ) { mail($EmailAddress,'Non-200 response',$DataLine,"From: $EmailAddress"); } echo '</div>'; exit; function GetWebPage( $url, &$content ) { $options = array( CURLOPT_RETURNTRANSFER => true, // Return web page CURLOPT_HEADER => true, // Return headers CURLOPT_CONNECTTIMEOUT => 120, // Timeout on connect CURLOPT_TIMEOUT => 120, // Timeout on response CURLOPT_FOLLOWLOCATION => true, // Follow redirects CURLOPT_MAXREDIRS => 10, // stop after 10 redirects CURLOPT_USERAGENT => 'Connection Testing/1.0', CURLOPT_VERBOSE => false ); $Info = array(); $ch = curl_init($url); curl_setopt_array($ch,$options); $content = curl_exec($ch); $err = curl_errno($ch); $errmsg = curl_error($ch) ; $Info = curl_getinfo($ch); curl_close($ch); $Info['errno'] = $err; $Info['errmsg'] = $errmsg; return $Info; } function StartAudio($url) { echo <<<AUDIO <audio id="audio-control" controls autoplay preload="auto" src="$url"></audio> AUDIO; } function StartAlertFlashColor($color) { echo <<<COLOR <script> function ColorChange() { var d = document.getElementById("data-alert-container"); if( d.style.borderColor=="transparent" ) { d.style.borderColor = "$color"; } else { d.style.borderColor = "transparent"; } } setInterval(ColorChange,3000); </script> COLOR; } function ExitForReload($s='') { global $MinutesBetweenTests; $pause = intval($MinutesBetweenTests*60); echo "<p>$s</p><span style='color:transparent;'>".str_repeat('X ',2222).'</span>'; flush(); sleep( $pause ); echo "<script>location.href='{$_SERVER['PHP_SELF']}'</script>"; exit; } ?>
Customization notes —
-
$TestingURL — Replace
https://example.com/file.php
with the URL of the web page you are testing. -
$DataDumpDirectory — Replace
/200test/URLtest.txt
with the location of the log file to be updated.Specify the location relative to document root (begins with a "/" character). Any subdirectories (
/200test
in this case) need to exist. -
$MinutesBetweenTests — Replace
4
with the number of minutes between tests. -
$AudioURL — Replace
SoundFile.mp3
with the server location or URL of your sound file if you want a sound to be played when the software experiences an HTTP non-200 response. Otherwise, removeSoundFile.mp3
so the sound file value is blank.Note that some browsers won't autoplay sound. If yours currently does not, you'll need to open your browser's preferences and specify that audio autoplay is allowed. Some browsers let you specify which domains the allowance is applied to so you don't open autoplay to all websites.
-
$AlertFlashColor — Replace
red
with any valid HTML color designation if you wish to see a border color fade in and fade out to attract your attention. Otherwise, removered
so the color value is blank.Examples of HTML color designations for blue are:
blue
,rgb(0,0,255)
,#0000ff
, andhsl(240,100%,50%)
-
$EmailAddress — Replace
me@example.com
with the email address where a non-200 alert shall be sent, if you wish to get an emailed alert. Otherwise, removeme@example.com
so the email address value is blank.The PHP function mail() is used to send the email. Some hosting companies disable mail() or have limits on how many emails may be sent per hour or day.
-
$SMSemailAddress — replace
1234567890@sms.example.com
with the SMS email address where a non-200 alert text message shall be sent, if you wish to get an SMS alert. Otherwise, remove1234567890@sms.example.com
so the email address value is blank.If you do not know your SMS email address, Send Text Message With PHP can help you with that. It requires that you know who your carrier is. If you're unsure, this free carrier lookup website can help.
The PHP function mail() is used to send the SMS text message. Some hosting companies disable mail() or have limits on how many emails (which includes SMS messages) may be sent per hour or day.
-
$SMSfromAddress — Replace
me@example.com
with the "From" email address indicating the source of the SMS text message, if $SMSemailAddress in the previous step has a value for sending a text message alert. Otherwise, removeme@example.com
so the "From" email address value is blank.
Those are the customizations.
Upload the php script to your server.
To run it, type its URL into your browser. You may wish to run it in a separate tab, a separate window, or even a separate browser so you can do other stuff while the script is doing its testing.
To see how the alerts work, you can specify a URL that doesn't exist (which will result in an HTML non-200 response). When done with alert testing, change the URL back to the valid one for automatic testing.
This script was very handy for me.
When the alert came, I was able to immediately access the servers and see what I could see. It provided clues that let me pursue the reason for the gateway timeout in an orderly way.
This article first appeared with an issue of the Possibilities newsletter.
Will Bontrager