문제 상황
프론트(https://aaa/bbb)에서 서버로 POST 요청을 보냈다. 그런데 아래 메시지를 받았다.
🚨 Access to fetch at 'https://aaa/bbb' from origin 'https://aaa' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
CORS는 Cross Origin Resource Sharing으로 다른 origin에서 서버 리소스를 사용할 수 있도록 공유하는 기술이다. 위 문제는 CORS를 하지 못하도록 막혔다는 뜻이다.
해결 방법
CORSMiddleware
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["https://aaa", "https://bbb"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
- add_middleware를 이용해 CORS를 허용한다.
- allow_origins에 허용할 origin을 입력한다.
- *는 모든 요청을 허용한다.
위 예시는 origin이 https://aaa와 https://bbb인 요청만 허용한다.
Origin
URL은 프로토콜, 도메인, 포트 등으로 이루어져 있다.
https://my-domain.com:8000/user/page
- https:: 프로토콜
- my-domain.com: 도메인
여기서 프로토콜과 도메인을 합친 부분이 origin이다. 위 예시의 경우, https://my-domain.com이 된다.
같은 Origin
allow_origins=["https://aaa.com"]
- https://aaa.com
- https://www.aaa.com
- https://www.aaa.com/path
- https://www.aaa.com/path?q=33
위 URL에서 접근한 요청은 정상적으로 처리된다.
다른 Origin
allow_origins=["https://aaa.com"]
- http://aaa.com
- https://bbb.com
- https://aaa.com:3000
위 URL은 접근이 허용되지 않는다. 참고로 allow_origins을 https://aaa.com/으로 작성하면 https://aaa.com에서 접근이 되지 않는다. 생각 없이 적은 / 때문에 한참 헤맸다.
에러 메시지를 보면 no-cors 모드를 사용하라는 부분이 있다.
const result = await fetch('...', {
method: 'POST',
mode: 'no-cors',
headers: {...},
body: {...},
});
이 방식은 응답을 받아 올 수는 있지만, 비어있는 응답을 받게 된다. 즉, 정상적인 요청-응답이 아니니 주의해야 한다.