Skip to content

Commit 6de7ea4

Browse files
committed
Add compatibility layer for WP Cerber and WordPress REST API. Introduced filters to adjust REST URL prefix detection and handle API request authentication, ensuring proper functionality with custom URL structures.
1 parent 62a48c2 commit 6de7ea4

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

default-wp-cerber.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
/**
3+
* Plugin Name: Be API - Default WP Cerber
4+
* Plugin URI: https://github.com/BeAPI/bea-plugin-defaults
5+
* Description: Compatibility layer for WP Cerber and the WordPress REST API. Adjusts REST URL prefix detection so Cerber correctly identifies REST requests when the site uses a custom prefix or subfolder structure.
6+
* Version: 1.0.0
7+
* Requires at least: 5.9
8+
* Requires PHP: 7.4
9+
* Author: BeAPI Technical team
10+
* Author URI: https://beapi.fr
11+
* License: GPL-2.0-or-later
12+
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
13+
* Text Domain: bea-plugin-defaults
14+
*/
15+
16+
namespace BEAPI\Plugin_Defaults\Wp_Cerber;
17+
18+
if ( ! defined( 'ABSPATH' ) ) {
19+
die( 'Cannot access pages directly.' );
20+
}
21+
22+
add_filter( 'rest_url_prefix', __NAMESPACE__ . '\\fix_prefix_to_check' );
23+
add_filter( 'rest_request_before_callbacks', __NAMESPACE__ . '\\fix_prefix_endpoint' );
24+
add_filter( 'application_password_is_api_request', __NAMESPACE__ . '\\application_password_is_api_request' );
25+
26+
/**
27+
* Modifies the REST API prefix from `/wp-json/` to `/json` based on the requested URL on WP-Cerber cerber_is_rest_url() check
28+
*
29+
* This filter intercepts the default REST URL prefix via the `rest_url_prefix` hook
30+
* and applies a custom prefix if the current URL starts with `/wp-json/`.
31+
*
32+
* @param string $prefix The default REST API prefix.
33+
* @return string The modified REST API prefix (or unchanged if not applicable).
34+
*
35+
*/
36+
function fix_prefix_to_check( string $prefix ): string {
37+
// Retrieve the requested URL
38+
$url = $_SERVER['REQUEST_URI'] ?? '';
39+
40+
// If no URL is available, return the default prefix
41+
if ( empty( $url ) ) {
42+
return $prefix;
43+
}
44+
45+
// If the URL starts with `/wp-json/`, change the prefix to `json`. Because it consider current /wp like a subfolder
46+
if ( str_starts_with( $url, '/wp-json/' ) ) {
47+
return 'json';
48+
}
49+
50+
// Otherwise, keep the default prefix
51+
return $prefix;
52+
}
53+
54+
/**
55+
* Removes the REST prefix filter after a REST API request is processed.
56+
*
57+
* This function is hooked into the `rest_request_before_callbacks` filter
58+
* to ensure the prefix modification does not persist beyond its intended scope.
59+
*
60+
* @param mixed $response The current REST response or null.
61+
* @return mixed The original REST response, unchanged.
62+
*
63+
*/
64+
function fix_prefix_endpoint( $response ) {
65+
// Remove the custom prefix filter to avoid side effects
66+
remove_filter( 'rest_url_prefix', __NAMESPACE__ . '\\fix_prefix_to_check' );
67+
68+
return $response;
69+
}
70+
71+
72+
/**
73+
* Determines if the current request is an API request and fixes WP Cerber REST API blocking too early.
74+
*
75+
* This function checks if the request URI indicates a REST API route,
76+
* validates the request method against a set of allowed methods, and
77+
* ensures that authentication credentials are provided.
78+
*
79+
* @param bool $is_api_request The initial determination of whether the request is an API request.
80+
*
81+
* @return bool True if the request is a valid API request; otherwise, the original $is_api_request value.
82+
*/
83+
function application_password_is_api_request( $is_api_request ) {
84+
$request_uri = $_SERVER['REQUEST_URI'] ?? '';
85+
if ( empty( $request_uri ) ) {
86+
return $is_api_request;
87+
}
88+
// Check if it's an API route
89+
if ( ! str_contains( $request_uri, '/wp-json/' ) ) {
90+
return $is_api_request;
91+
}
92+
$request_method = $_SERVER['REQUEST_METHOD'] ?? '';
93+
$request_method_allowed = [ 'GET', 'POST', 'PUT', 'DELETE', 'PATCH' ];
94+
// Check if method REQUEST is allowed
95+
if ( ! in_array( $request_method, $request_method_allowed, true ) ) {
96+
return $is_api_request;
97+
}
98+
// Check if authentication is sent
99+
if ( ! isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) {
100+
return $is_api_request;
101+
}
102+
return true;
103+
}

0 commit comments

Comments
 (0)