26
votes

I have this wordpress site with a plugin called JSON API. This plugin provides a JSON format for the content that is in the wordpress. I was able to enable CORS on the wordpress by adding header("Access-Control-Allow-Origin: *"); on the php header. But when I tried the url that the JSON API plugin provides the CORS does not work anymore.

This is the wordpress site were I'm doing the tests... I used the test cors website to check if it was working and it is... http://kiwa-app.loading.net/

But when I try with the url that the JSON api provides me, is not working anymore. I'm still have the error No 'Access-Control-Allow-Origin' http://kiwa-app.loading.net/?json=info

I will apreciate some help thanks!!!

11

11 Answers

39
votes

I've used a few different WordPress API's - but for those of you using the 'official' WP-API, I had much trouble with this CORS --- and what I found was that between the .htaccess approach and a few others I stumbled upon... adding this to your theme functions.php worked best.

function add_cors_http_header(){
    header("Access-Control-Allow-Origin: *");
}
add_action('init','add_cors_http_header');

Be sure not to use any combinations of these ( .htaccess, header.php, api.php, functions.php ) as it will be angry at you.

15
votes

Ok I finally figured out an easy way...

You just have to add:

     <? header("Access-Control-Allow-Origin: *"); ?>

On the file api.php, this file is located in wp-content/plugins/json-api/singletons/api.php

I hope it helps more people with the same problem!

9
votes

Before the response is sent to the browser, we can run two action hooks and insert a new header():

do_action("json_api", $controller, $method);
do_action("json_api-{$controller}-$method");

The first one runs on every method, and the second one is to target specific methods. Here's an implementation of the first one, with a commented way to find the second:

add_action( 'json_api', function( $controller, $method )
{
    # DEBUG
    // wp_die( "To target only this method use <pre><code>add_action('$controller-$method', function(){ /*YOUR-STUFF*/ });</code></pre>" );

    header( "Access-Control-Allow-Origin: *" );
}, 10, 2 );
7
votes

Using Wordpress 5.2.3 - whilst using GET and POST externally, the following finally opened sesame for me. I tried all of the answers above (to no avail) before finding this solution that worked for my case.

add_action( 'rest_api_init', function () {
    add_action( 'rest_pre_serve_request', function () {
        header( 'Access-Control-Allow-Headers: Authorization, Content-Type, X-WP-Wpml-Language', true );
        header("Access-Control-Allow-Origin: *");
    } );
}, 15 );

Hopefully WordPress will have an official doggy door-flap for CORS control in the future.

6
votes

Now that REST API is merged with core, we can use the rest_api_init action.

add_action( 'rest_api_init', function()
{
    header( "Access-Control-Allow-Origin: *" );
} );
3
votes

WordPress 5 (4.4+ actually) can handle it via WP Headers:

Try this:

add_filter( 'wp_headers', 'send_cors_headers', 11, 1 );
function send_cors_headers( $headers ) {
    $headers['Access-Control-Allow-Origin'] = $_SERVER[ 'HTTP_ORIGIN' ];
    return $headers;
}

Note that this will allow access from ANY source. For security you should try to do something like set an array of allowed domains that can make the request to your WordPress site and short-circuit the allow CORS if the domain making the request is not in the allowed list:

add_filter( 'wp_headers', 'send_cors_headers', 11, 1 );
function send_cors_headers( $headers ) {
    $allowed_domains = array( 'https://my.okdomain.com' , 'http://anothergoodone.com');
    if ( ! in_array( $_SERVER[ 'HTTP_ORIGIN' ] , $allowed_domains ) ) return $headers;
    $headers['Access-Control-Allow-Origin'] = $_SERVER[ 'HTTP_ORIGIN' ];
    return $headers;
}
2
votes

In wordpress goto plugins > JSON API > Edit

From the right hand file selection select

json-api/singletons/api.php

You will need to add the following line

header("Access-Control-Allow-Origin: *");

Your code should look similar to this once done. Adding this line anywhere else might not work as expected.

<?php
header("Access-Control-Allow-Origin: *"); 
class JSON_API {

  function __construct() {
    $this->query = new JSON_API_Query();
    $this->introspector = new JSON_API_Introspector();
    $this->response = new JSON_API_Response();
    add_action('template_redirect', array(&$this, 'template_redirect'));
    add_action('admin_menu', array(&$this, 'admin_menu'));
    add_action('update_option_json_api_base', array(&$this, 'flush_rewrite_rules'));
    add_action('pre_update_option_json_api_controllers', array(&$this, 'update_controllers'));
  }

  function template_redirect() {
0
votes

If anyone is still facing any issue after trying all of the above code(making changes in funtions.php in your theme) / .htaccess way, then probably this problem is with your hosting service provider.

I have tried all the possible things and wasted my two days on this problem and came to know that the problem is due to infinityfree . com (free hosting service provider).

Reference: https://wordpress.org/support/topic/wordpress-api-blocks-post-by-cors-policy/ https://wordpress.org/support/topic/wordpress-api-blocks-post-by-cors-policy-2/

-1
votes

For anyone who is having this issue with multiple origins

In your server hosting your wordpress site, navigate to ../wp-content/plugins/json-rest-api and from here open the plugin.php file.

In this function

function json_send_cors_headers( $value ) {..}

Change the header

header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );

To

header( 'Access-Control-Allow-Origin: *' );

Hope this helps anyone who was incurring the same issues as I.

-3
votes

The solution works with WordPress 5.1.1 and Gutenberg

add_filter('rest_url', function($url) {
    $url = str_replace(home_url(), site_url(), $url);
    return $url;
});
-4
votes

In WordPress project go to following file and do like this:

In wp-includes/rest-api.php change:

header( 'Access-Control-Allow-Origin: ' . $origin );

to:

header( 'Access-Control-Allow-Origin: *' );

In wp-includes/http.php change:

header( 'Access-Control-Allow-Origin: ' . $origin );

to:

header( 'Access-Control-Allow-Origin: *' );