1

I have an app with fastapi (v0.88) backend that connect to an API built using flask (v2.2). The frontend is build using ReactJS (v18.2).

ReactJS    --------->   FastAPI   -------------->  Flask
(frontend)              (backend)                  (API Server)

Frontend: local Backend: Backend server (not local) API: API Server (not local)

The API (using Flask) is already deployed on the server with CORS enabled. For simplicity, the CORS is enabled the following way:

from flask_cors import CORS
def initialize_app(env=None):

    app = Flask(__name__,
                instance_path=dirname(realpath(__file__)),
                instance_relative_config=True)
    
    app.config.from_object(config_by_name[env])
    app.config['SWAGGER_UI_DOC_EXPANSION'] = 'list'
    
    CORS(app)
    
    with app.app_context():
        
        register_extensions(app)
        register_blueprints(app)  
        
    return app

In the fastapi, I've done the following:

from fastapi.middleware.cors import CORSMiddleware
# Set all CORS enabled origins
if cnf.BACKEND_CORS_ORIGINS:
    app.add_middleware(
        CORSMiddleware,
        # allow_origins=[str(origin)
                    #    for origin in cnf.BACKEND_CORS_ORIGINS],
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"]
    )

When I make the call from the front end, I simply do the following. This makes the call to the backed (FastAPI).

var headers: Headers = {
    'Content-Type': 'application/json; charset=utf-8'
}

export const GET = (url:string) => {


    return axios.get(`${url}`, { headers });

};


export const POST = (url:string, data:any) => {

    return axios.post(`${url}`, { 
        headers, 
        data
    });
};

And the backend server redirects to the API server to request the data.

from requests import request

from app.core.config import cnf


class CreateHTTPRequest:

    def __init__(self):
        self.base_url = cnf.API_SERVER_HOST
        self.headers = {
            cnf.API_KEY_NAME: cnf.API_KEY, 
            'Content-Type': 'application/json;charset=utf-8'
        }

    
    def get(self, path, params=None):

        url = self.base_url + path
        response = request("GET",url, headers=self.headers, params=params)
        response.raise_for_status()
        return response.json()

    

    def post(self, path, data=None, params=None):

        url = self.base_url + path
        response = request("POST", url, data=data, headers=self.headers, params=params)
        response.raise_for_status()
        return response.json()
        

I don't understand what is it that I'm doing wrong here. Initially, CORS blocked everything (including GET requests), but after I enabled CORS(app), I started to get response for the GET requests. It still doesn't work for the POST request even though all origins are allowed. How can I fix this and what am I overlooking?

ERROR

Access to XMLHttpRequest at 'http://api-server/group-classifier/' (redirected from 'https://backend-server/group-classifier') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

POST http://backend-server/group-classifier/ net::ERR_FAILED

Phil
  • 157,677
  • 23
  • 242
  • 245
user1828605
  • 1,723
  • 1
  • 24
  • 63
  • You're using `axios.post()` incorrectly. It should be `axios.post(url, data, { headers })`. See https://github.com/axios/axios#axiosposturl-data-config – Phil Apr 17 '23 at 01:49
  • @Phil I changed it to `return axios.post(`${url}`, data, { headers });` but I still get the same error – user1828605 Apr 17 '23 at 01:53
  • What is the actual error? You haven't mentioned it anywhere in your question so please [edit] it to include accurate details – Phil Apr 17 '23 at 01:53
  • Is the backend local? The cors error can happens because of redirects to an error page (cloudflare). look at the request in the network tab – pguardiario Apr 17 '23 at 01:54
  • FYI setting the content-type header in Axios is generally unnecessary. – Phil Apr 17 '23 at 01:54
  • @Phil, I updated the question. The backend is not local. The only local is the frontend. I also added the error I received in the question. – user1828605 Apr 17 '23 at 01:57
  • _"Redirect is not allowed for a preflight request"_ does that not tell you what you need to know? You're responding with a redirect to a preflight `OPTIONS` request. Generally, I'd say avoid redirects and AJAX requests at all costs. They never work how you expect them to – Phil Apr 17 '23 at 02:00
  • If you **must** use redirects, you'll need to configure your proxy to rewrite `Location` headers to replace the backend URL with the proxy URL – Phil Apr 17 '23 at 02:02
  • @Phil, I do not understand that. Could you please give me an example or a link from where I can read it? But my GET and POST requests are set similarly. Why does GET work but POST is blocked? – user1828605 Apr 17 '23 at 02:04
  • Because your POST request is non-simple and requires a pre-flight `OPTIONS` request which is being mishandled by your server. Why, no idea but I'd probably avoid double-handling CORS configuration in both your proxy and API – Phil Apr 17 '23 at 02:06
  • @Phil, so it seems like the Redirect doesn't like if the request is not sent as x-www-form-encoded. Is this true? My form sends the data as application/json. What do you suggest I do? – user1828605 Apr 17 '23 at 03:03
  • 1
    Sorry, I have no idea what any of that means. A _"redirect"_ is a response (30x status and `Location` header). The request body format is dictated by what your API expects. The only bearing it has on CORS is that `content-type: application/json` is considered non-simple and requires a preflight `OPTIONS` request. If you want to support CORS, you should support it fully and be able to handle these requests without redirecting or error – Phil Apr 17 '23 at 03:06
  • 1
    You've registered `/group-classifier/` as your endpoint, but are making the request against `/group-classifier` (i.e. without the trailing slash). A redirect will be issued to guide the client to the correct endpoint, but that will fail CORS. Either register the correct endpoint route name (`/group-classifier`), or make the request against the currently registered endpoint route (`/group-classifier/`). – MatsLindh Apr 17 '23 at 08:00
  • @MatsLindh, that was also a part of it. I was able to fix it by making sure all of the trailing slashes are the same. I actually ended up removing from all endpoints. But the biggest problem I think was the way headers were sent. I was posting as `application/json`. Based on Phil's answer and the link to the solution, I set it to `x-www-form-urlencoded` and that fixed the problem. The other reason was that I was sending request over http instead of https on local. Thanks to @Phil and you for guiding me. – user1828605 Apr 17 '23 at 17:58

0 Answers0