* The REST related class.
defined('WPINC') || exit();
private $_internal_rest_status = false;
public function __construct()
// Hook to internal REST call
add_filter('rest_request_before_callbacks', array($this, 'set_internal_rest_on'));
add_filter('rest_request_after_callbacks', array($this, 'set_internal_rest_off'));
add_action('rest_api_init', array($this, 'rest_api_init'));
public function rest_api_init()
// Activate or deactivate a specific crawler callback
register_rest_route('litespeed/v1', '/toggle_crawler_state', array(
'callback' => array($this, 'toggle_crawler_state'),
'permission_callback' => function () {
return current_user_can('manage_network_options') || current_user_can('manage_options');
register_rest_route('litespeed/v1', '/tool/check_ip', array(
'callback' => array($this, 'check_ip'),
'permission_callback' => function () {
return current_user_can('manage_network_options') || current_user_can('manage_options');
register_rest_route('litespeed/v1', '/ip_validate', array(
'callback' => array($this, 'ip_validate'),
'permission_callback' => array($this, 'is_from_cloud'),
// Token callback validate
register_rest_route('litespeed/v1', '/token', array(
'callback' => array($this, 'token'),
'permission_callback' => array($this, 'is_from_cloud'),
register_rest_route('litespeed/v1', '/token', array(
'callback' => array($this, 'token_get'),
'permission_callback' => array($this, 'is_from_cloud'),
register_rest_route('litespeed/v1', '/ping', array(
'callback' => array($this, 'ping'),
'permission_callback' => '__return_true',
// API key callback notification
register_rest_route('litespeed/v1', '/apikey', array(
'callback' => array($this, 'apikey'),
'permission_callback' => array($this, 'is_from_cloud'),
// CDN setup callback notification
register_rest_route('litespeed/v1', '/cdn_status', array(
'callback' => array($this, 'cdn_status'),
'permission_callback' => array($this, 'is_from_cloud'),
register_rest_route('litespeed/v1', '/notify_img', array(
'callback' => array($this, 'notify_img'),
'permission_callback' => array($this, 'is_from_cloud'),
register_rest_route('litespeed/v1', '/notify_ucss', array(
'callback' => array($this, 'notify_ucss'),
'permission_callback' => array($this, 'is_from_cloud'),
register_rest_route('litespeed/v1', '/notify_vpi', array(
'callback' => array($this, 'notify_vpi'),
'permission_callback' => array($this, 'is_from_cloud'),
register_rest_route('litespeed/v1', '/err_domains', array(
'callback' => array($this, 'err_domains'),
'permission_callback' => array($this, 'is_from_cloud'),
register_rest_route('litespeed/v1', '/check_img', array(
'callback' => array($this, 'check_img'),
'permission_callback' => array($this, 'is_from_cloud'),
* Call to freeze or melt the crawler clicked
public function toggle_crawler_state()
if (isset($_POST['crawler_id'])) {
return $this->cls('Crawler')->toggle_activeness($_POST['crawler_id']) ? 1 : 0;
* Check if the request is from cloud nodes
* @since 4.4.7 As there is always token/api key validation, ip validation is redundant
public function is_from_cloud()
return $this->cls('Cloud')->is_from_cloud();
public function token_get()
return Cloud::ok(array('ver' => Core::VER));
public function check_ip()
return Tool::cls()->check_ip();
public function ip_validate()
return $this->cls('Cloud')->ip_validate();
return $this->cls('Cloud')->token_validate();
return $this->cls('Cloud')->save_apikey();
* Endpoint for QC to notify plugin of CDN setup status update.
public function cdn_status()
return $this->cls('Cdn_Setup')->update_cdn_status();
public function notify_img()
return Img_Optm::cls()->notify_img();
public function notify_ucss()
self::debug('notify_ucss');
return UCSS::cls()->notify();
public function notify_vpi()
self::debug('notify_vpi');
return VPI::cls()->notify();
public function err_domains()
self::debug('err_domains');
return $this->cls('Cloud')->rest_err_domains();
public function check_img()
$this->cls('Cloud')->validate_hash(4);
} catch (\Exception $e) {
return self::err($e->getMessage());
return Img_Optm::cls()->check_img();
public static function err($code)
return array('_res' => 'err', '_msg' => $code);
* Set internal REST tag to ON
public function set_internal_rest_on($not_used = null)
$this->_internal_rest_status = true;
Debug2::debug2('[REST] ✅ Internal REST ON [filter] rest_request_before_callbacks');
* Set internal REST tag to OFF
public function set_internal_rest_off($not_used = null)
$this->_internal_rest_status = false;
Debug2::debug2('[REST] ❎ Internal REST OFF [filter] rest_request_after_callbacks');
public function is_internal_rest()
return $this->_internal_rest_status;
* Check if an URL or current page is REST req or not
* @since 2.9.4 Moved here from Utility, dropped static
public function is_rest($url = false)
// For WP 4.4.0- compatibility
if (!function_exists('rest_get_url_prefix')) {
return defined('REST_REQUEST') && REST_REQUEST;
$prefix = rest_get_url_prefix();
// Case #1: After WP_REST_Request initialisation
if (defined('REST_REQUEST') && REST_REQUEST) {
// Case #2: Support "plain" permalink settings
if (isset($_GET['rest_route']) && strpos(trim($_GET['rest_route'], '\\/'), $prefix, 0) === 0) {
// Case #3: URL Path begins with wp-json/ (REST prefix) Safe for subfolder installation
$rest_url = wp_parse_url(site_url($prefix));
$current_url = wp_parse_url($url);
// Debug2::debug( '[Util] is_rest check [base] ', $rest_url );
// Debug2::debug( '[Util] is_rest check [curr] ', $current_url );
// Debug2::debug( '[Util] is_rest check [curr2] ', wp_parse_url( add_query_arg( array( ) ) ) );
if ($current_url !== false && !empty($current_url['path']) && $rest_url !== false && !empty($rest_url['path'])) {
return strpos($current_url['path'], $rest_url['path']) === 0;