Bud dev - CORS Error

Hello all,

as soon as I start the dev-mode and want to execute an ajax-call, for example, I get a cors-error from the browser. I have already tried all variants with the proxy URL and the development environment, but unfortunately I always get this error.

package.json:

  "devDependencies": {
    "@roots/bud": "^6.3.5",
    "@roots/bud-eslint": "^6.3.5",
    "@roots/bud-postcss": "^6.3.5",
    "@roots/bud-prettier": "^6.3.5",
    "@roots/bud-sass": "^6.3.5",
    "@roots/bud-stylelint": "^6.3.5",
    "@roots/bud-tailwindcss": "6.3.5",
    "@roots/eslint-config": "^6.3.5",
    "@roots/sage": "6.3.5",
    "stylelint-config-standard-scss": "^5.0.0"
  },

bud.config.ms:

// @ts-check

/**
 * Build configuration
 *
 * @see {@link https://bud.js.org/guides/getting-started/configure}
 * @param {import('@roots/bud').Bud} app
 */
export default async (app) => {
  app
    /**
     * Application entrypoints
     */
    .entry({
      app: ['@scripts/app', '@styles/common/app'],
      editor: ['@scripts/editor', '@styles/common/app'],
    })

    /**
     * Directory contents to be included in the compilation
     */
    .assets(['images'])

    /**
     * Matched files trigger a page reload when modified
     */
    .watch(['resources/views/**/*', 'app/**/*'])

    /**
     * Proxy origin (`WP_HOME`)
     */
    .proxy('http://local.devurll.de/')

    /**
     * Development origin
     */
    .serve('http://0.0.0.0:3000')

    /**
     * URI of the `public` directory
     */
    .setPublicPath('/app/themes/themename/public/');
};

What is the text of the error?

I’ve tested in Chrome and FF, both have different errors:

Chrome

Access to XMLHttpRequest at 'http://local.websitename.de/wp/wp-admin/admin-ajax.php?test=test' from origin 'http://0.0.0.0:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Firefox

Quellübergreifende (Cross-Origin) Anfrage blockiert: Die Gleiche-Quelle-Regel verbietet das Lesen der externen Ressource auf http://local.websitename.de/wp/wp-admin/admin-ajax.php?test=test. (Grund: CORS-Anfrage schlug fehl). Statuscode: (null)

What is the calling code? I use axios mostly, or fetch (i guess). this is what a network request for wp looks like using that library:

import axios, { AxiosInstance } from "axios";

export const api: AxiosInstance = axios.create({
  // @ts-ignore
  baseURL: wp_localize_data.api_url,
  headers: {
    "content-type": "application/json",
    // @ts-ignore
    "X-WP-Nonce": wp_localize_data.nonce,
  },
});

export const fetch = (url: string) =>
  api.request({ url }).then(({ data, error }) => {
    if (error) throw new Error(error)
    return data;
  });

with wp_localize_data() providing the nonce value and the base URL.

Usage example:

import * as api from './api' // above module
const results = api.fetch('/namespace/v1/endpoint/example');

I think the problem is that you’re requesting the actual site URL.

You want to make a request for localhost:3000/wp-json, because the request is being made from localhost. But, you’re requesting http://local.websitename.de/wp-json. That’s the crux of the problem.

My suggestion is to conditionally use localhost:3000 when in development. There are a great number of ways to do this, but my suggestion is to listen for 'HTTP_REFERER':

$is_dev_request = $_SERVER['HTTP_REFERER'] && strpos($_SERVER['HTTP_REFERER'], 'localhost');
$rest_url = $is_dev_request ? 'http://localhost:3000/wp-json/' : rest_url();

// give this to wp_localize_script
$api_url = esc_url_raw($rest_url)})

You might also try leaving off the base url entirely so that you end up making your requests against /wp-json/... and the browser/lib fills in localhost:3000 for you (or the real URL, in production). I don’t know how your setup will fare with that, but it’s a simple solution if it works.

Out of curiosity - were you using Valet to serve your sites as opposed to a Virtual Box Instance?

I had issues until I added a cors.conf file in the `~/.config/valet/Nginx/’ folder. Sorry to bump an old thread, but thought it may help someone as this was one of the few results that came up when i searched my issues.

1 Like

No, i’m not using Valet…
I’ve solved the problem by disabling access-constrol-origin for local-evns:

/**
 * Disabled Access-Control-Allow for Dev-Env (prevent CORS Errors on localhost)
 *
 */

add_action('init', function () {
    if (env('WP_ENV') !== 'development') :
        return;
    endif;

    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
    header('Access-Control-Allow-Credentials: true');
}, 1);
1 Like

Had same problem recently, it is in: web/wp/wp-includes/rest-api.php rest_send_cors_headers, it happens automatically, when you use rest endpoints. :slight_smile:, because of add_filter( ‘rest_pre_serve_request’, ‘rest_send_cors_headers’ );

It took almost half a year to spot this, had this earlier, but changed the way I work because of it. My nginx headers were always overriden by this this. But anyway, you can fix it, by adding:

rest_api_init('rest_api_init',  function () {
      remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
});

or overriding it and setting your own cors headers.

1 Like