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.