53

I'm trying to enable CORS in this very basic FastAPI example, however it doesn't seem to be working.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=['*']
)

@app.get('/')
def read_main():
    return {'message': 'Hello World!'}

This is the response I get:

curl -v http://127.0.0.1:8000
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< date: Fri, 08 Jan 2021 19:27:37 GMT
< server: uvicorn
< content-length: 26
< content-type: application/json
<
* Connection #0 to host 127.0.0.1 left intact
{"message":"Hello World!"}*
funnydman
  • 9,083
  • 4
  • 40
  • 55
user270199
  • 905
  • 1
  • 6
  • 12
  • It seems to be working. You are allowing requests from every origin – lsabi Jan 08 '21 at 20:59
  • 2
    @Isabi I don't get _Access-Control-Allow-Origin: *_ in my response though. – user270199 Jan 08 '21 at 21:05
  • Have you tried with a browser or an app? My guess is that curl is not sending the `Origin` in the headers because it has no well defined origin, so it cannot return it in the headers – lsabi Jan 08 '21 at 21:10
  • I tried with Chrome and Postman. The only headers I get in the response are: _content-length_, _content-type_, _date_ and _server_. – user270199 Jan 08 '21 at 21:13
  • That's strange. Have you tried with the full example? https://fastapi.tiangolo.com/tutorial/cors/?h=+cors#use-corsmiddleware – lsabi Jan 08 '21 at 21:25
  • I have tried that too. I've no idea what's going on unfortunately... – user270199 Jan 08 '21 at 21:40
  • I tested the sample code of the official docs and it does not show the CORS when requested from the terminal, but it shows them from javascript running within the browser (Chromium `Version 87.0.4280.88 (Official Build) snap (64-bit)`) – lsabi Jan 08 '21 at 22:17
  • If CORS is indeed enabled, should the _Access-Control-Allow-Origin: *_ header not be sent with the response? – user270199 Jan 08 '21 at 22:47
  • If it's in the browser in which `CORS` permissions are mandatory yes, but in the case of an API requests from different sources/domains will be performed, then no. `CORS` are mainly for security reasons (scripts that perform requests to external resources) – lsabi Jan 09 '21 at 13:48
  • @lsabi of what use is this CORS if it cant restrict at all times? looks to me like a useless feature as it can be bypassed pretty easily and just does not work, also if behind web server proxy...wont work except if proxy is setup to use CORS also – uberrebu Jun 16 '21 at 08:47
  • @uberrebu I don't understand your question. Goal of CORS is to support direct access of javascript to third party APIs – lsabi Jun 16 '21 at 08:52
  • or to restrict and only allow from certain origins/domains...yes or no? – uberrebu Jun 16 '21 at 09:01
  • @lsabi yes or no? CORS is to control access to endpoint based on origin/domain? yes or no? – uberrebu Jun 16 '21 at 09:13
  • @uberrebu No, CORS is for restricting access to the same domain. I want to be the only one accessing my API from the browser, thus I allow only my domain as origin (though direct API calls, not through browser, are allowed). This ensures more security for my users who navigate via browser – lsabi Jun 16 '21 at 10:28
  • you said No and then agree with what am saying, contradicting there...you just said for restricting access...so if this CORS can be bypassed, then is that security of illusion of security? – uberrebu Jun 16 '21 at 16:18
  • as here is written: https://stackoverflow.com/questions/65191061/fastapi-cors-middleware-not-working-with-get-method?rq=3 The reponse is only generated if the sender includes origin in the header. – user3680510 May 24 '23 at 18:15

3 Answers3

86

you can find answer from this:fastapi cors

then this is a very simple code to achieve it:

  1. create a python file and named it main.py.

  2. add code in this file.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = ["*"]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/")
async def main():
    return {"message": "Hello World"}

and run this app:

uvicorn main:app  --reload --host 0.0.0.0 --port 8000

if you computer ip is 192.12.12.12

you can check this link and just write a small javascript in html:

<script>
        fetch("http://192.12.12.12:8000/").then((Response) => {
            return Response.json()
        }).then((data) => {
            console.log(data);
        })
    </script>
yuanzz
  • 1,359
  • 12
  • 15
  • not working for me even restarted the server – Sunil Garg Aug 10 '21 at 11:58
  • 2
    @SunilGarg it shouldn't work. on the link given by yuanzz https://fastapi.tiangolo.com/tutorial/cors/?h=%20cors#use-corsmiddleware, it literally says "allow_origins cannot be set to ['*'] for credentials to be allowed" – motyzk Aug 25 '21 at 15:10
  • 4
    You can't use [*] as allowed origins while with_credentials is set to true – Kavindu Pasan Kavithilaka Sep 07 '21 at 13:39
  • 6
    Literal quote from the help page: *"Also, allow_origins cannot be set to `[*]` for credentials to be allowed, origins must be specified."* – NotAName Sep 15 '21 at 00:14
  • This solution is great – Sajjad Aemmi Jan 29 '22 at 08:25
  • 2
    As others have said REMOVE `allow_methods=["*"],` if the origin is a wildcard otherwise it WILL NOT WORK – Anm Aug 14 '22 at 13:00
  • As per the [documentation](https://fastapi.tiangolo.com/tutorial/cors/#wildcards), it is preferabe to explicitly specify the allowed origins, e.g., `origins = ['http://localhost:3000', 'http://127.0.0.1:3000']`, instead of using the `"*"` wildcard, which would allow **any** origin at the cost of excluding everything that involves credentials from the communication, such as cookies and Authorization headers. See [here](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#sending_a_request_with_credentials_included) and [here](https://stackoverflow.com/a/24689738) as well. – Chris Sep 03 '22 at 15:07
  • Please have a look at related answers [here](https://stackoverflow.com/a/73963905/17865804) and [here](https://stackoverflow.com/a/71805329/17865804) – Chris May 27 '23 at 05:51
  • Thanks a lot, this answer was invaluable and it helped us to get our demo ready ! – Sharath Chandran Jun 08 '23 at 02:32
  • The docs explicitly say: allow_credentials - Indicate that cookies should be supported for cross-origin requests. Defaults to False. Also, allow_origins cannot be set to ['*'] for credentials to be allowed, origins must be specified. I know FastAPI will quietly accept * origin and allow_credentials=True, but it will most likely not pass cookies. – yuranos Aug 29 '23 at 10:26
8

In my case, CORS not works when pydantic or type problems occured.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "http://localhost:3000",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# works well!
@app.get("/list")
async def main():
    return ["hi", "hello"]

# error cases
from typing import List
from app.nosql.model import Book

@app.get("/error")
async def main():
    # case 1
    ret = mongo_db.engine.find(Book, limit=10) # keyword "await" missing
    return ret  # CORS 500 error
    # case 2
    ret: List[Book] = await mongo_db.engine.find(Book, limit=10) # data was not fit with model Book
    return ret # CORS error
    # case 3
    return ["hi", "hello"] # works well...

Whats the server-side error says? It might be error occurs in server. How about test with new function. (has no error) If server works well.. humm.. sry about that.

noname2048
  • 81
  • 1
  • 2
3

I had a similar issue and just found the solution. Using lots of copypasted code, I was spinning up another FastAPI instance somewhere where CORS was not configured, like this:

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=['*']
)

... much later somewhere within lots of green code ...
app = FastAPI()
Joe
  • 6,758
  • 2
  • 26
  • 47