Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't send a post request when the 'Content-Type' is set to 'application/json'

I am working on a React application and I am using fetch to send a request. I have made a Sign Up form recently and now I am integrating it with it's API. Previously the API accepted url encoded data and it was all working fine. but now that the requirement has changed and the API accepts data in JSON, I had to change the content-type header from 'application/x-www-form-urlencoded' to 'application/json'. But I get the following error:

Fetch API cannot load http://local.moberries.com/api/v1/candidate. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I have even set the 'Access-Control-Allow-Headers' in the API but it still doesn't work. Here is the relevant code for the client side:

sendFormData() {
    let {user} = this.props;

    var formData = {
      first_name: ReactDOM.findDOMNode(this.refs.firstName).value,
      last_name: ReactDOM.findDOMNode(this.refs.lastName).value,
      city: ReactDOM.findDOMNode(this.refs.currentCity).value,
      country: ReactDOM.findDOMNode(this.refs.currentCountry).value,
      is_willing_to_relocate: user.selectedOption,
      cities: relocateTo,
      professions: opportunity,
      skills: skills,
      languages: language,
      min_gross_salary: minSal,
      max_gross_salary: maxSal,
      email: ReactDOM.findDOMNode(this.refs.email).value,
      password: ReactDOM.findDOMNode(this.refs.password).value
    };

    var request = new Request('http://local.moberries.com/api/v1/candidate', {
      method: 'POST',
      mode: 'cors',
      headers: new Headers({
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      })
    });

    var requestBody = JSON.stringify(formData);

    console.log(requestBody);

    fetch(request, {body: requestBody})
      .then(
        function (response) {
          if (response.status == 200 || response.status == 201) {
            return response.json();
          } else {
            console.log('Failure!', response.status);
          }
        }).then(function (json) {

      var responseBody = json;

      console.log(typeof responseBody, responseBody);
    });

  }

And here is the relevant API code:

class Cors
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request)
            ->header('Access-Control-Allow-Origin', '*')
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
            ->header('Access-Control-Allow-Headers: Origin, Content-Type, application/json');
    }
}

I really can't figure out the problem. Any kind of help will be appreciated.

like image 446
Arslan Tariq Avatar asked Aug 17 '16 13:08

Arslan Tariq


Video Answer


1 Answers

It turns out that CORS only allows some specific content types.

The only allowed values for the Content-Type header are:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

To set the content type to be 'application/json', I had to set a custom content type header in the API. Just removed the last header and added this one:

->header('Access-Control-Allow-Headers', 'Content-Type');

and it is working all good.

like image 123
Arslan Tariq Avatar answered Oct 17 '22 06:10

Arslan Tariq