Search code examples
wordpresswordpress-rest-apiheadless-cms

Headless Wordpress, Is there a way to access data in wp_options table as REST endpoint?


Wordpress has an awesome REST API interface. https://developer.wordpress.org/rest-api/reference/

But the content in wp_options table seems to be missing REST support. Is there a way to access the content in wp_otions table as REST endpoint via plugins?. Thanks.


Solution

  • There is the settings endpoint, but it only contains a surprisingly limited amount of them it seems.

    This is something you could very easily do yourself though. I'm not sure if any plugins do it, but I also wouldn't recommend a plugin for something that can be done with less than 20 lines of code.

    You just need to register a route using register_rest_route() on the rest_api_init hook, and pass it a callback function. You can drop code like this in your functions.php file or create a Must Use Plugin and drop the code in there, either way.

    add_action( 'rest_api_init', function () {
        register_rest_route( 'my-custom-route/v1', '/opt/', array(
            'methods' => 'GET',
            'callback' => 'get_rest_option',
            //'permission_callback' => function () {
            //  return current_user_can( 'administrator' );
            //}
        ) );
    } );
    
    function get_rest_option( $data ) {
        return get_option( $data['option_name'] );
    }
    

    The above will give you access to whatever option you want by accessing:

    /wp-json/my-custom-route/v1/opt/?option_name=siteurl
    

    I went ahead and dropped an example on a site of mine:

    https://xhynk.com/content-mask/wp-json/my-custom-route/v1/opt/?option_name=blogname https://xhynk.com/content-mask/wp-json/my-custom-route/v1/opt/?option_name=siteurl

    However, this will potentially expose anything in your options table. I went ahead and commented out the permission_callback so that any person, signed in or not, can access it. However, I also added a check like this:

    function get_rest_option( $data ) {
        if( $data['option_name'] === 'siteurl' || $data['option_name'] === 'blogname' ){
            return get_option( $data['option_name'] );
        } else {
            return 'Unauthorized. Use `siteurl` or `blogname`';
        }
    }
    

    You can see that home will fail: https://xhynk.com/content-mask/wp-json/my-custom-route/v1/opt/?option_name=home

    I would recommend adding in a valid array of options, or using the permission_callback in order to lock it down a bit. You could even have an access key instead, and keep that key secret. Either way, be aware of the security implications of exposing your entire wp_options table, and take some sort of preventative measure!