Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WordPress custom API endpoint POST request fails in React

I have a WordPress backend where I have added my own custom endpoints to the API:

// retrieve countries
register_rest_route( $namespace, '/countries',
    array(
        'methods'  => 'GET',
        'callback' => array( $this, 'get_countries' ),
    )
);

// check answer
register_rest_route( $namespace, '/check_answer',
    array(
        'methods'  => 'POST',
        'callback' => array( $this, 'check_answer' ),
    )
);

I have set up my environment like this: https://example.com is where the React application lives, and WordPress is in a subdirectory, on https://example.com/wp

My React application makes POST and GET requests to those endpoints above. I have a production environment variable where I set the base URL of the API, which is https://example.com/wp/wp-json/game ('game' is my namespace) and so I can make requests with Axios to https://example.com/wp/wp-json/game/countries and https://example.com/wp/wp-json/game/check_answer and here comes the issue.

My server is configured so that it serves the React application both with as without www. So https://example.com and https://www.example.com both serve the same application.

But this generates some interesting issue for my custom endpoints: the GET request always works. but the POST request only works if I am trying it from https://example.com, NOT from https://www.example.com . In case of the latter it just simply shows me a failed request. No response, nothing.

I have googled and it seems to be related to CORS, but I was unable to fix it. Any ideas here?

like image 342
Danny Hobo Avatar asked Oct 26 '22 22:10

Danny Hobo


1 Answers

First of all i would like to point out that your Get requests work because they belong to the category which does not trigger a preflight request. While your Post request is probably using some header which removes it from the category hence requiring preflight to pass. If you are interested in reading more, here is the documentation link.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests

Now, according to your comment, the error you are getting is

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The method you are using for setting headers, as you mentioned in a comment, does not work on rest requests. You can use below function in your functions.php or a plugin file to set the origin to *.

function sr_rest_send_cors_headers( $value ) 
{   
    header( 'Access-Control-Allow-Origin: *' );
    header( 'Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE' );
    header( 'Access-Control-Allow-Credentials: true' );
    header( 'Vary: Origin', false );

    return $value;
}
add_filter( 'rest_pre_serve_request', 'sr_rest_send_cors_headers', 11 );

Although i recommend what WordPress does by default. If you check wp-includes/rest-api.php you will find the original function which i have modified for your purpose. If you are interested in taking a look, here is the trac link.

https://core.trac.wordpress.org/browser/tags/5.4/src/wp-includes/rest-api.php#L574

like image 184
shazyriver Avatar answered Nov 15 '22 07:11

shazyriver