diff --git a/app/rest.php b/app/rest.php index aea46162..34442742 100755 --- a/app/rest.php +++ b/app/rest.php @@ -1,3 +1,7 @@ getSetting('Api: REST Api Enabled') == '1') { + + \Utils\LogManager::getInstance()->info("Request: " . $_REQUEST); + + if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { + http_response_code(200); + exit(); + } + + define('REST_API_PATH', '/'); + + $echoRoute = \Classes\Macaw::get(REST_API_PATH . 'echo', function () { + echo "Echo " . rand(); + }); + + \Utils\LogManager::getInstance()->debug('Api registered URI: '.$echoRoute); + + $moduleManagers = \Classes\BaseService::getInstance()->getModuleManagers(); + + foreach ($moduleManagers as $moduleManagerObj) { + + $moduleManagerObj->setupRestEndPoints(); + } + $method = $_SERVER['REQUEST_METHOD']; + if (strtoupper($method) === 'GET') { + \Classes\IceRoute::dispatch($_GET['url'], $method); + } else { + $method = strtoupper($_REQUEST['method']); + \Classes\IceRoute::dispatch($_REQUEST['url'], $method); + } + + +}else{ + echo "REST Api is not enabled. Please set 'Api: REST Api Enabled' setting to true"; +} \ No newline at end of file diff --git a/core/src/Classes/IceRoute.php b/core/src/Classes/IceRoute.php new file mode 100755 index 00000000..3ffc2912 --- /dev/null +++ b/core/src/Classes/IceRoute.php @@ -0,0 +1,177 @@ + '[^/]+', + ':num' => '[0-9]+', + ':all' => '.*' + ); + + public static $error_callback; + + /** + * Defines a route w/ callback and method + */ + public static function __callstatic($method, $params) + { + + $uri = $params[0][0]; + $callback = $params[0][1]; + + array_push(self::$routes, $uri); + array_push(self::$methods, strtoupper($method)); + array_push(self::$callbacks, $callback); + + return $uri; + } + + /** + * Defines callback if route is not found + */ + public static function error($callback) + { + self::$error_callback = $callback; + } + + public static function haltOnMatch($flag = true) + { + self::$halts = $flag; + } + + /** + * Runs the callback for the given request + */ + public static function dispatch($uri, $method) + { + + $searches = array_keys(static::$patterns); + $replaces = array_values(static::$patterns); + + $found_route = false; + + self::$routes = str_replace('//', '/', self::$routes); + + // check if route is defined without regex + if (in_array($uri, self::$routes)) { + $route_pos = array_keys(self::$routes, $uri); + foreach ($route_pos as $route) { + //using an ANY option to match both GET and POST requests + if (self::$methods[$route] == $method || self::$methods[$route] == 'ANY') { + $found_route = true; + + //if route is not an object + if (!is_object(self::$callbacks[$route])) { + //grab all parts based on a / separator + $parts = explode('/', self::$callbacks[$route]); + + //collect the last index of the array + $last = end($parts); + + //grab the controller name and method call + $segments = explode('@', $last); + + //instanitate controller + $controller = new $segments[0](); + + //call method + $controller->$segments[1](); + + if (self::$halts) { + return; + } + } else { + //call closure + call_user_func(self::$callbacks[$route]); + + if (self::$halts) { + return; + } + } + } + } + } else { + // check if defined with regex + $pos = 0; + foreach (self::$routes as $route) { + if (strpos($route, ':') !== false) { + $route = str_replace($searches, $replaces, $route); + } + + if (preg_match('#^' . $route . '$#', $uri, $matched)) { + if (self::$methods[$pos] == $method) { + $found_route = true; + + array_shift($matched); //remove $matched[0] as [1] is the first parameter. + + + if (!is_object(self::$callbacks[$pos])) { + //grab all parts based on a / separator + $parts = explode('/', self::$callbacks[$pos]); + + //collect the last index of the array + $last = end($parts); + + //grab the controller name and method call + $segments = explode('@', $last); + + //instanitate controller + $controller = new $segments[0](); + + //fix multi parameters + if (!method_exists($controller, $segments[1])) { + echo "controller and action not found"; + } else { + call_user_func_array(array($controller, $segments[1]), $matched); + } + + //call method and pass any extra parameters to the method + // $controller->$segments[1](implode(",", $matched)); + + if (self::$halts) { + return; + } + } else { + call_user_func_array(self::$callbacks[$pos], $matched); + + if (self::$halts) { + return; + } + } + } + } + $pos++; + } + } + + // run the error callback if the route was not found + if ($found_route == false) { + if (!self::$error_callback) { + self::$error_callback = function () { + header($_SERVER['SERVER_PROTOCOL']." 404 Not Found"); + echo '404'; + }; + } + call_user_func(self::$error_callback); + } + } +} diff --git a/core/src/Classes/Macaw.php b/core/src/Classes/Macaw.php index 78995f5b..fab8ee3e 100755 --- a/core/src/Classes/Macaw.php +++ b/core/src/Classes/Macaw.php @@ -42,6 +42,8 @@ class Macaw array_push(self::$methods, strtoupper($method)); array_push(self::$callbacks, $callback); + call_user_func('\Classes\IceRoute::'.$method, $params); + return $uri; } diff --git a/core/src/Classes/RestEndPoint.php b/core/src/Classes/RestEndPoint.php index beb3daeb..340af0ea 100644 --- a/core/src/Classes/RestEndPoint.php +++ b/core/src/Classes/RestEndPoint.php @@ -420,6 +420,8 @@ class RestEndPoint if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) { $token = $matches[1]; } + } else { + $token = $_GET['token']; } if (strlen($token) > 32) { diff --git a/web/api/AdapterBase.js b/web/api/AdapterBase.js index 97faad2b..8a293e56 100644 --- a/web/api/AdapterBase.js +++ b/web/api/AdapterBase.js @@ -55,7 +55,7 @@ class AdapterBase extends ModuleBase { } setupApiClient(token) { - this.apiClient = new IceApiClient(this.apiUrl, token); + this.apiClient = new IceApiClient(this.apiUrl, token, window.CLIENT_BASE_URL, true); } setApiUrl(apiUrl) { diff --git a/web/api/IceApiClient.js b/web/api/IceApiClient.js index b18a19dd..a620877a 100644 --- a/web/api/IceApiClient.js +++ b/web/api/IceApiClient.js @@ -1,12 +1,19 @@ const axios = require('axios'); class IceApiClient { - constructor(baseUrl, token) { + constructor(baseUrl, token, clientBaseUrl, legacyApiWrapper = true) { this.baseUrl = baseUrl; this.token = token; + this.clientBaseUrl = clientBaseUrl; + this.legacyApiWrapper = legacyApiWrapper; } get(endpoint) { + if (this.legacyApiWrapper) { + const url = `${this.clientBaseUrl}rest.php?token=${this.token}&method=get&url=/${endpoint}`; + return axios.get(url); + } + return axios.get(this.baseUrl + endpoint, { headers: { Authorization: `Bearer ${this.token}`,