Validate rest-api call on create

WordPress Site A has an API, which is being used by another system/application (B). B is struggling to handle/controle/sanitize the posts being sent to the API, and often cause creation of duplicates. B is really struggling to solve this in their end, so I was wondering if I can add a validation-method to the endpoint in my end.

The problem is that it needs to be a validation on a create-endpoint.


Example

This is how I imagines it would look on an update endpoint (not tested):

I’m calling the endpoint: https://example.org/wp-json/wp/v2/foobar/100007?title=Test Title&meta[custom_var]=10

add_action( 'rest_api_init', function(){
  register_rest_route( 'wp/v2', '/foobar/(?P<id>d+)', [
    'methods'  => 'POST',
    'args'     => [
      'custom_var' => [
        'validate_callback' => function( $param, $request, $key ){
          if( $param > 5 ){
            return true
          }
          return false;
        },
      ],
    ],
  ] );
} );

But I can’t find anything in the rest documentation about validating the create endpoint.

I imagined it being something like this:

add_action( 'rest_api_init', function(){
  register_rest_route( 'wp/v2', '/foobar/', [
    'methods'  => 'POST',
    'validate_method' => function( ... ),
    ...
    ...
    ...
  ] );
} );

… But that doesn’t work.


I also considered doing the callback:

add_action( 'rest_api_init', function(){
  register_rest_route( 'wp/v2', '/foobar/', [
    'methods'  => 'POST',
    'callback' => function( ... ),
    ...
    ...
    ...
  ] );
} );

But that callback fires after the post is created (I assumed).

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

As I said in the comments, since it’s a custom endpoint, you could just cancel the post creation via the main callback, i.e. something like so:

'callback' => function () {
    if ( some condition ) {
        // create the post
    } else {
        // return existing post or something else
    }
}

And here’s an example where the POST endpoint creates a published post (of the post type), but only if there’s no existing published post having the same title as specified in a parameter named title:

Note: When registering custom REST routes, use your own namespace (e.g. my-namespace/v1) and not wp/v2.

add_action( 'rest_api_init', function() {
    register_rest_route( 'my-namespace/v1', '/foobar', array(
        'methods'             => 'POST',
        'callback'            => function ( $request ) {
            $posts = get_posts( array(
                'post_type' => 'post',
                'title'     => $request['title'],
                'fields'    => 'ids',
            ) );

            if ( ! empty( $posts ) ) {
                return new WP_Error(
                    'rest_post_exists',
                    'There is already a post with the same title.',
                    array( 'status' => 400 )
                );
            }

            return wp_insert_post( array(
                'post_type'   => 'post',
                'post_title'  => $request['title'],
                'post_status' => 'publish',
            ) );
        },
        'permission_callback' => function ( $request ) {
            return current_user_can( 'publish_posts' );
        },
        'args'                => array(
            'title' => array(
                'type'              => 'string',
                'required'          => true,
                'validate_callback' => function ( $param, $request ) {
                    if ( ! preg_match( '/[a-z0-9]+/', $param ) ) {
                        return new WP_Error(
                            'rest_invalid_title',
                            'Please enter a valid title for the post.',
                            array( 'status' => 400 )
                        );
                    }

                    return true;
                }
            ),
        ),
    ) );
} );

However, note that if foobar is actually a custom post type, then when registering the post type (see register_post_type()), you could actually set show_in_rest to true and then set rest_controller_class to the name of a custom REST controller class like the one here.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x