Search code examples
symfonyecmascript-6corsfetch-apinelmiocorsbundle

Symfony3 / Nelmio cors / fetch api — 400 Bad Request


As the title says, I have a symfony3 Application with a rest api on a subdomain so that:

GET http://ajax.localhost.dev:10190/menus

returns a list of menus in JSON format.

Here is the configuration of the nelmio cors bundle (/app/config/nelmio/cors.yml)

nelmio_cors:
  paths:
    '^/':
      origin_regex: true
      allow_origin: ['^https?://%domain%:[0-9]+']
      allow_headers: ['X-Custom-Auth']
      allow_methods: ['POST', 'PUT', 'GET', 'DELETE', 'OPTIONS']
      max_age: 3600
      hosts: ['^ajax\.']
      allow_credentials: true

I have been using this code:

export default class AppRemote extends Remote {
  get host () { return `ajax.${super.host}`; }
  open(xhr, data) {
    if ("withCredentials" in xhr) { 
      xhr.open(data.method, this.url(data.url), true);
      xhr.withCredentials = true; }

    else if (typeof XDomainRequest != "undefined") {
      xhr = new XDomainRequest();
      xhr.open(data.method, this.url(data.url)); }

    else { this.app.error('cannot init CORS Request'); }

    return xhr;
  }
};

which was working fine. Now I am trying to port it to the new fetch API and I am using this code:

const init = (url, method = 'GET') => {
  return new Request(url, {
    headers: new Headers({
      'Access-Control-Allow-Credentials': true,
      //'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS'
    }),
    mode: 'cors',
    credentials: true,
    method });
}

const get = (url) => {
  return fetch(init(url));
}

It returns a 400 Bad Request, with Request Method: OPTIONS. If I just type the url in the browser, it works.

I guess there is some authentication issue, but just cannot figure out how to solve it. How can I do that?


Solution

  • After some research I finally found the mistake. Thanks to Firefox, which threw an error pointing me to the spot:

    return new Request(url, {
      //headers: new Headers({
        //'Access-Control-Allow-Credentials': true,
        //'Access-Control-Allow-Origin': '*',
        //'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS'
      //}), //<-- working without headers at all
      mode: 'cors',
      credentials: 'include', //<-- that is the right setting
      method });
    

    Docs on MDN