lwcolton / falcon-cors

CORS support for Falcon: http://falconframework.org
Apache License 2.0
74 stars 15 forks source link

CRA + Falcon CORS: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response #12

Closed koddr closed 5 years ago

koddr commented 5 years ago

Hello! Thanks for your work.

I build SPA with React.js and Falcon. Frontend created by create-react-app CLI.

Here is my ./api/__init__.py:

import falcon
from falcon_cors import CORS
from api.views import UserResource

cors = CORS(
    allow_all_origins=True,
    allow_credentials_all_origins=True,
    allow_all_headers=True,
    log_level='DEBUG'
)

# Init app
app = falcon.API(middleware=[cors.middleware])

# API routes
app.add_route('/api/user', UserResource())

...and my ./api/views.py is:

import json, datetime
from falcon import HTTP_404
from peewee import IntegrityError
from playhouse.shortcuts import model_to_dict
from api.models import Users
from api.utils import str_converter

class UserResource(object):
    """
    User endpoint
    Methods: GET
    """

    # Show User by UUID
    def on_get(self, req, resp):
        try:
            # Build user query
            user = Users.get(Users.uuid == req.media.get('uuid'))
            # Return JSON with user object
            resp.body = json.dumps({
                "data": model_to_dict(user),
                "status": "success",
                "description": None
            }, default=str_converter)
        except Users.DoesNotExist:
            # Return JSON with error (404)
            resp.status = HTTP_404
            resp.body = json.dumps({
                "data": None,
                "status": "error",
                "description": "User does not exists!"
            })

./frontend/src/App.js:

import React, {Component} from 'react';
import axios from 'axios';

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      users: []
    };
  }

  componentDidMount() {
    axios.get('http://127.0.0.1:8000/api/user', {
      data: {
        id: 1
      }
    }).then(
      (result) => {
        this.setState({
          isLoaded: true,
          users: result.data.data
        });
      },
      (error) => {
        this.setState({
          isLoaded: true,
          error
        });
      });
  }

  render() {
    const {error, isLoaded, users} = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <div className="App">
          <ul>
            {users.map(user => (<li key={user.uuid}>{user.first_name} {user.last_name}</li>))}
          </ul>
        </div>
      );
    }
  }
};

When I run this application (front and back):

$ gunicorn --reload api:app
$ npm start

On Google Chrome console I see this error:

Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/user' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

Why? What I did wrong way? Please help me...