Search code examples
javascriptlaravelreactjslumencreate-react-app

Lumen API returns 422 error when passing body as JSON


I'm trying to post from react application to php backend (Lumen 5.3) via fetch api.

My POST is as follows:

function login(userData, onError, cb) {
  return fetch('/v1/auth/login', {
    method: 'post',
    body: JSON.stringify(userData),
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
  }).then(checkStatus)
    .then(parseJSON)
    .then(cb)
    .catch(onError);
}

where userData is:

const userData = {
  email: this.state.fields.username,
  password: this.state.fields.password,
};

However I am receiving an error:

422 error

Which would indicate that my body is incorrect? I suspect this because when I test an equivalent request in postman and do not pass password in the body I will receive a 422 error:

422 error in postman

This leads me to believe that the body is maybe not formatted correctly?

One part that is sort of suspicious is that if I log my response from the php backend there is no body returned. In theory if my body is formatted incorrectly I should receive the following from the backend:

{
    "email": [
        "The email field is required."
    ],
    "password": [
        "The password field is required."
    ]
}

Solution

  • It turns out my Lumen API does not accept JSON as the body.

    The fix for now is to modify my request as follows:

    function login(userData, onError, cb) {
      return fetch('/v1/auth/login', {
        method: 'post',
        body: serialize(userData), // no longer passing json
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/x-www-form-urlencoded' // no longer passing json
        },
      }).then(checkStatus)
        .then(parseJSON)
        .then(cb)
        .catch(onError);
    }
    
    function serialize(obj) {
      let str = [];
      for(let p in obj)
        if (obj.hasOwnProperty(p)) {
          str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        }
      return str.join("&");
    }
    

    Where userData is:

    const userData = {
      email: this.state.fields.username,
      password: this.state.fields.password,
    };
    

    And now everyone is happy :) Hope this helps!