$http_method, "permission_callback" => function ($request) use ($permission_callback, $path, $http_method) { $permission_result = $permission_callback(); if ($permission_result === "public") { return true; } $nonce_raw = $request->get_header("X-WP-Nonce") ?: $request->get_param("_wpnonce"); $nonce = is_string($nonce_raw) ? sanitize_text_field(wp_unslash($nonce_raw)) : ""; if (!wp_verify_nonce($nonce, "wp_rest")) { \NeoLibrary\NeoGlobal\global_warn_with_module_name("_global--endpoint", "Endpoint access failed for endpoint $path ($http_method): Invalid nonce"); return new \WP_Error("invalid_nonce", "Invalid nonce", ["status" => 401]); } if (!is_user_logged_in()) { \NeoLibrary\NeoGlobal\global_warn_with_module_name("_global--endpoint", "Endpoint access failed for endpoint $path ($http_method): Not logged in"); return new \WP_Error("not_logged_in", "You are not currently logged in.", ["status" => 401]); } if (!$permission_result) { \NeoLibrary\NeoGlobal\global_warn_with_module_name("_global--endpoint", "Endpoint access failed for endpoint $path ($http_method): No permission"); return new \WP_Error("permission_denied", "Your user role does not have permission to access this endpoint.", ["status" => 403]); } return true; }, "callback" => function ($request) use ($callback, $path, $http_method) { \NeoLibrary\NeoGlobal\performance_checkpoint("endpoint $http_method $path", is_start: true); $get_param = function ($key) use ($request) { if (sanitize_key($key) !== $key) { \NeoLibrary\NeoGlobal\throw_global_exception("WP only allows alphanumeric characters and underscores for the parameter name!"); } return $request->get_param($key) ?? ($request->get_json_params() ?: [])[$key] ?? ($request->get_file_params() ?: [])[$key] ?? null; }; try { if (count((new \ReflectionFunction($callback))->getParameters()) === 1) { $response = $callback($get_param); } else { $response = $callback(); } if (is_wp_error($response)) { return $response; } if (str_contains(wp_strip_all_tags(wp_unslash($_SERVER["HTTP_ACCEPT_ENCODING"] ?? "")), "gzip") && function_exists("gzencode") && !(headers_sent() || ob_get_length() > 0)) { $status = ($response instanceof \WP_REST_Response) ? $response->get_status() : 200; $data = ($response instanceof \WP_REST_Response) ? $response->get_data() : $response; $headers = ($response instanceof \WP_REST_Response) ? $response->get_headers() : ["Content-Type" => "application/json; charset=utf-8"]; $response = new \WP_REST_Response(gzencode(\NeoLibrary\NeoGlobal\json_encode_better($data), level: 1), status: $status, headers: array_merge($headers, ["Content-Encoding" => "gzip", "Vary" => "Accept-Encoding", "X-Neo-Raw-neo-library" => "gzip"])); } return $response; } catch (\Throwable $e) { $rest_status = $e instanceof \NeoLibrary\NeoGlobal\GlobalException ? $e->get_status_code() : 500; $message = $e instanceof \NeoLibrary\NeoGlobal\GlobalException ? $e->get_original_message() : $e->getMessage(); $debug_message = $e->getMessage(); if (WP_DEBUG) { $debug_message .= "\n\n" . $e->getTraceAsString(); } return new \WP_Error($e instanceof \NeoLibrary\NeoGlobal\GlobalException ? $e->get_error_code() : "neo_global__endpoint_error", $message, ["status" => $rest_status, "debugMessage" => $debug_message]); } finally { \NeoLibrary\NeoGlobal\performance_checkpoint("endpoint $http_method $path", is_end: true); } }, ]); } }); $register_rest_endpoint_for_js = function () use (&$path, &$permission_callback) { \NeoLibrary\NeoGlobal\val("neo_global__rest_endpoints")[$path] = $permission_callback() === "public"; }; if (did_action("init") || doing_action("init")) { $register_rest_endpoint_for_js(); } else { \NeoLibrary\NeoGlobal\add_action_hook("init", $register_rest_endpoint_for_js); } } function get_rest_endpoint_url($path) { if (!did_action("init")) { \NeoLibrary\NeoGlobal\throw_global_exception("WP is not initialized yet. Cannot use the WP function for rest_url(). Please call this function after the 'init' action."); } if (!str_starts_with($path, "/wp-json/neo/")) { \NeoLibrary\NeoGlobal\throw_global_exception("The endpoint path must start with '/wp-json/neo/'."); } $path = str_replace("/wp-json/", "", $path); return rest_url($path); } \NeoLibrary\NeoGlobal\add_action_hook("neo_init", function () { \NeoLibrary\NeoGlobal\callback_before_enqueue_js_variables_backend_or_frontend(function () { $rest_urls = []; foreach (\NeoLibrary\NeoGlobal\val("neo_global__rest_endpoints") as $path => $is_public) { $rest_urls[$path] = ["isPublic" => $is_public, "url" => get_rest_endpoint_url($path)]; } \NeoLibrary\NeoGlobal\enqueue_js_variable_backend_and_frontend("neoGlobalRestEndpoints", $rest_urls); \NeoLibrary\NeoGlobal\enqueue_js_variable_backend("neoGlobalRestEndpointAjaxUrl", admin_url("admin-ajax.php")); if (\NeoLibrary\NeoGlobal\current_user_can__global_endpoint__refresh_nonce()) { \NeoLibrary\NeoGlobal\enqueue_js_variable_backend_and_frontend("neoGlobalRestEndpointNonce", wp_create_nonce("wp_rest")); } }); }); // Output responses that require compression directly. This is safe because only structured JSON data is sent with proper headers (see above). \NeoLibrary\NeoGlobal\add_filter_hook("rest_pre_serve_request", function ($served, $result) { if (!($result instanceof \WP_HTTP_Response)) { return $served; } $headers_lowercase = array_change_key_case($result->get_headers(), CASE_LOWER); if (($headers_lowercase["x-neo-raw-neo-library"] ?? null) !== "gzip") { return $served; } foreach ($result->get_headers() as $name => $value) { header("{$name}: {$value}"); } echo $result->get_data(); /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ // The endpoint outputs gzipped data via echo for optimal performance and bandwidth efficiency. It returns structured data only (e.g., JSON) with proper headers (Content-Type: application/json, Content-Encoding: gzip). This approach ensures correct delivery, prevents code execution, and maintains full compatibility with gzip compression, which standard WordPress response handling would otherwise disrupt. return true; });