4

When you go to /wp-json or /wp-json/[namespace] on an API-enabled WordPress site, it shows all of the API routes and endpoints.

How can I disable this behaviour without disabling the REST API?

2
  • 1
    These are WP_REST_Server (wp-includes\rest-api\class-wp-rest-server.php) get_index() and get_namespace_index(). Worst case you can hook the two filters at the end of each, rest_index and rest_namespace_index, and just drop all the content (or maybe you can use WP_REST_RESPONSE to return 404), but there's hopefully a better way.
    – Rup
    Commented Dec 20, 2019 at 13:43
  • 2
    Can you tell us why you want to do this? It only shows the routes you're allowed to access, if there's an endpoint that requires administrator level priviledges, it will only be listed for administrators. It's not a list of every endpoint, it's a list of every endpoint you specifically have access to, so you gain nothing security-wise by hiding it
    – Tom J Nowell
    Commented Dec 20, 2019 at 14:01

3 Answers 3

4

Slightly modified function from @mirado (the filter has to return WP_REST_Response instance not an array)

    function hide_ns_and_routes( $response ) {
      $data = $response->get_data();
      $data['namespaces'] = [];
      $data['routes'] = [];
      $response->set_data( $data );

      return $response;
     }
     add_filter( 'rest_index', 'hide_ns_and_routes' );
2

You can use the filter hook 'rest_index' :

add_filter('rest_index', function ($response) {
  $data = $response->get_data();

  $data['namespaces'] = [];
  $data['routes'] = [];

  return $data;
}, 9999, 1);

It is possible to remove your route from $data['namespaces'] and $data['routes']

2

The previous answers can hide the index display for /wp-json, but it doesn't seem to work for /wp-json/[namespace].

In order to hide the index of a particular namespace, the rest_namespace_index hook needs to be used.

add_filter('rest_namespace_index', function ($response) {
    $data = $response->get_data();
    $data['namespaces'] = [];
    $data['routes'] = [];
    $response->set_data($data);

    return $response;
});

If someone wants to completely rewrite the routing output, or wants more flexible permissions control, a better approach would be to re-register the root routing path for that namespace

Unfortunately, register_rest_route is of little use at this point, as it will reject empty routing paths. Therefore, the rewrite needs to be done directly using the underlying WP_REST_Server::register_route.

rest_get_server()->register_route($namespace, "/$namespace", [
    'methods' => 'GET',
    'permission_callback' => fn () => current_user_can('import'),
    'callback' => fn ($r) => $this->representationBrowser($r),
], true);

Note that:

  1. The value of the route parameter should be /[namespace], not /.
  2. The override parameter may need to be true

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.