Skip to content

Commit

Permalink
cleaner localhost detection
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnRDOrazio committed Nov 16, 2024
1 parent 4ff3eae commit 5bd5214
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 11 deletions.
34 changes: 23 additions & 11 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
ini_set('date.timezone', 'Europe/Vatican');
require_once 'vendor/autoload.php';

$apiVersion = 'dev';
if (preg_match('/^\/api\/(.*?)\/index.php$/', $_SERVER['SCRIPT_NAME'], $matches)) {
$apiVersion = $matches[1];
}

/**
* Detect server Request Scheme
*/
if (
(isset($_SERVER['REQUEST_SCHEME']) && !empty($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https') ||
(isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
Expand All @@ -33,22 +31,36 @@
$server_request_scheme = 'http';
}

/**
* Detect server name
*/
$server_name = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost';
if ('localhost' === $server_name) {
if (Router::isLocalhost()) {
$server_name .= ':' . $_SERVER['SERVER_PORT'];
$concurrentServiceWorkers = getenv('PHP_CLI_SERVER_WORKERS');
if (false === $concurrentServiceWorkers || (int)$concurrentServiceWorkers < 2) {
die("We detected that there are not enough concurrent service workers. Perhaps set the `PHP_CLI_SERVER_WORKERS` environment variable to a value greater than 1? E.g. `PHP_CLI_SERVER_WORKERS=2 php -S $server_name`.");
$pre1 = '<pre style="color:red;background-color:#EFEFEF;display:inline-block;padding: 5px;">PHP_CLI_SERVER_WORKERS</pre>';
$pre2 = sprintf('<pre style="color:red;background-color:#EFEFEF;display:inline-block;padding:5px;">PHP_CLI_SERVER_WORKERS=2 php -S %1$s</pre>', $server_name);
die("Not enough concurrent service workers.<br>Perhaps set the {$pre1} environment variable to a value greater than 1? E.g. {$pre2}.");
}
} else {
$apiVersion = 'dev';
if (preg_match('/^\/api\/(.*?)\/index.php$/', $_SERVER['SCRIPT_NAME'], $matches)) {
$apiVersion = $matches[1];
}
$server_name = "{$_SERVER['SERVER_NAME']}/api/{$apiVersion}";
}

// !!IMPORTANT!! There are classes that depend on this! Do NOT remove
// Perhaps we could find a better way to set this in a class such as Core ...
/**
* Define the API_BASE_PATH constant based on the server request scheme and the server name
* !!IMPORTANT!! There are classes that depend on this !!DO NOT REMOVE!!
* Perhaps we could find a better way to set this in a class such as Core ...
*/
define('API_BASE_PATH', "{$server_request_scheme}://{$server_name}");

Router::setAllowedOrigins('allowedOrigins.php');
Router::route();
if (false === Router::isLocalhost()) {
Router::setAllowedOrigins('allowedOrigins.php');
}

Router::route();
die();
34 changes: 34 additions & 0 deletions src/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@ class Router
{
public static array $allowedOrigins = [];

/**
* Set the allowed origins for Cross-Origin Resource Sharing (CORS).
*
* This function can read the allowed origins from a file that defines the
* ALLOWED_ORIGINS constant as an array of strings. If the file is not
* provided, the function will use the provided array of origins.
*
* If the file is provided, the function will merge the provided array of
* origins with the ones defined in the file. If the provided array is null,
* the function will use the array from the file.
*
* @param string|null $originsFile The path to the file that defines the allowed origins.
* @param array|null $origins The array of allowed origins.
* @return void
*/
public static function setAllowedOrigins(?string $originsFile = null, ?array $origins = null): void
{
if ($originsFile !== null && file_exists($originsFile)) {
Expand All @@ -42,6 +57,16 @@ public static function setAllowedOrigins(?string $originsFile = null, ?array $or
}
}

/**
* @return array an array of strings where each string is a path segment of the request path
*
* Takes the REQUEST_URI and SCRIPT_NAME and parses out the request path segments
* by removing the API base path and any trailing slashes.
*
* For example, if the REQUEST_URI is '/api/dev/calendar/IT/2021' and the
* SCRIPT_NAME is '/api/dev/index.php', then this method will return
* ['calendar', 'IT', '2021']
*/
private static function buildRequestPathParts(): array
{
// 1) The script name will actually include the base path of the API (e.g. /api/{apiVersion}/index.php),
Expand All @@ -56,6 +81,15 @@ private static function buildRequestPathParts(): array
return explode('/', $requestPath);
}

public static function isLocalhost(): bool
{
$localhostAddresses = ['127.0.0.1', '::1'];
$localhostNames = ['localhost', '127.0.0.1', '::1'];
return in_array($_SERVER['SERVER_ADDR'] ?? '', $localhostAddresses) ||
in_array($_SERVER['REMOTE_ADDR'] ?? '', $localhostAddresses) ||
in_array($_SERVER['SERVER_NAME'] ?? '', $localhostNames);
}

/**
* This is the main entry point of the API. It takes care of determining which
* endpoint is being requested and delegates the request to the appropriate
Expand Down

0 comments on commit 5bd5214

Please sign in to comment.