diff --git a/app/Jobs/Speedtests/ExecuteOoklaSpeedtest.php b/app/Jobs/Speedtests/ExecuteOoklaSpeedtest.php index 0fe898907..4c160de15 100644 --- a/app/Jobs/Speedtests/ExecuteOoklaSpeedtest.php +++ b/app/Jobs/Speedtests/ExecuteOoklaSpeedtest.php @@ -112,20 +112,19 @@ public function handle(): void /** * Check for internet connection. + * + * @throws \Exception */ protected function checkForInternetConnection(): bool { $url = config('speedtest.ping_url'); - // TODO: skip checking for internet connection, current validation does not take into account different host formats and ip addresses. - return true; - // Skip checking for internet connection if ping url isn't set (disabled) if (blank($url)) { return true; } - if (! URL::isValidUrl($url)) { + if (! $this->isValidPingUrl($url)) { $this->result->update([ 'data' => [ 'type' => 'log', @@ -165,4 +164,20 @@ protected function checkForInternetConnection(): bool return true; } + + /** + * Check if the given URL is a valid ping URL. + */ + public function isValidPingUrl(string $url): bool + { + $hasTLD = static function (string $url): bool { + // this also ensures the string ends with a TLD + return preg_match('/\.[a-z]{2,}$/i', $url); + }; + + return (filter_var($url, FILTER_VALIDATE_URL) && $hasTLD($url)) + // to check for things like `google.com`, we need to add the protocol + || (filter_var('https://'.$url, FILTER_VALIDATE_URL) && $hasTLD($url)) + || filter_var($url, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 || FILTER_FLAG_IPV6) !== false; + } } diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php deleted file mode 100644 index fff6e3c4c..000000000 --- a/tests/Unit/ExampleTest.php +++ /dev/null @@ -1,16 +0,0 @@ -assertTrue(true); - } -} diff --git a/tests/Unit/ExecuteOoklaSpeedtestTest.php b/tests/Unit/ExecuteOoklaSpeedtestTest.php new file mode 100644 index 000000000..9b321361e --- /dev/null +++ b/tests/Unit/ExecuteOoklaSpeedtestTest.php @@ -0,0 +1,68 @@ + ['ping_url' => 'google.com']]); + + $passingCases = [ + // ipv6 + '2a00:1450:4016:80c::200e', + // ipv4 + '1.1.1.1', + // hostname + 'google.com', + // hostname with subdomain + 'www.google.com', + // hostname with protocol + 'http://google.com', + 'https://google.com', + ]; + + foreach ($passingCases as $case) { + $this->assertTrue($job->isValidPingUrl($case), "$case is an invalid ping url"); + } + + $failingCases = [ + // invalid hostname + 'google', + // no tld + 'http://google', + 'https://google', + // invalid ipv4 + '1.1.1', + '1.1.1.1.', + '1.1.1.1.1', + '.1.1.1.1', + // invalid ipv6 + '2a00:1450:4016:80c::200e::', + '2a00:14504:4016:80c::200e', + '2a00:1450:401680c::200e', + '2v00:1450:4016:80c::200e', + '2::1:1450:4016:80c::200e', + // path included + 'https://google.com/test', + // path and query included + 'https://google.com/test?query=1', + // path, query and fragment included + 'https://www.google.com/test?query=1#fragment', + // path, query, fragment and port included + 'https://google.com:8080/test?query=1#fragment', + ]; + + foreach ($failingCases as $case) { + $this->assertFalse($job->isValidPingUrl($case), "$case is a valid ping url"); + } + } +}