Veri Bilimi Okulu

FastAPI CORS
fastapi_cors_kapak

Loading

Eğer bir web uygulaması geliştirirken tarayıcı konsolunda şu hatayı gördüysen, muhtemelen tarayıcı CORS ayarlarına takıldın demektir.

Access to fetch at 'http://localhost:8000/api/items' from origin 'http://localhost:3000' 
has been blocked by CORS policy...

Geliştirici olarak bu sorunu nasıl çözersin?

Bu yazıda CORS’un ne olduğunu, neden var olduğunu ve FastAPI’de nasıl çözeceğimizi birlikte öğreneceğiz. İsmi Çekerek fırlatma rampasından Mars’a gönderdiğimiz uzay robotu adı gibi gelebilir ama merak etme, düşündüğün kadar karmaşık değil!

CORS Nedir ve Neden Var?

CORS (Cross-Origin Resource Sharing – Çapraz Kaynak Paylaşımı), modern tarayıcılarda bulunan bir güvenlik mekanizmasıdır [1]. Peki tam olarak ne işe yarıyor?

Diyelim ki http://localhost:3000 adresinde çalışan bir React uygulamanız var ve http://localhost:8000 adresindeki FastAPI backend’inize istek atmaya çalışıyorsunuz. İşte tam bu noktada tarayıcı devreye giriyor ve “Dur bakalım, bu iki adres farklı!” diyor [2].

Burada kritik kavram kaynak (origin) kavramıdır. Bir kaynak üç bileşenden oluşur:

  • Protokol (Protocol): http veya https
  • Alan adı (Domain): localhost, example.com
  • Port: 3000, 8000, 80

Bu üç bileşenden herhangi biri farklıysa, tarayıcı bunları farklı kaynaklar olarak değerlendirir [3]. Yani http://localhost:3000 ile http://localhost:8000 farklı kaynaklardır çünkü portları farklı!

Peki Neden Böyle Bir Kısıtlama Var?

Bu kısıtlama Aynı Kaynak Politikası (Same-Origin Policy) olarak adlandırılır ve aslında seni korumak için var [4]. Düşünsene: Kötü niyetli bir web sitesi, senin haberin olmadan bankacılık sitesine istek atabilseydi ne olurdu? İşte CORS, bu tür saldırıları önlemek için tasarlanmış bir güvenlik katmanı.

Önemli bir not: CORS tamamen tarayıcı tarafında uygulanan bir güvenliktir. Sunucudan sunucuya yapılan isteklerde CORS kısıtlaması yoktur [5]. Bu yüzden Postman veya cURL ile API’nize istek attığınızda sorun yaşamazsınız, ama tarayıcıdan attığınızda hata alırsınız.

Tarayıcı Güvenlik Politikası Nasıl Çalışır?

Tarayıcı, çapraz kaynak isteği yapılacağını anladığında şöyle bir süreç başlatır [6]:

  1. İstek Analizi: Tarayıcı, yapılacak isteğin “basit istek” mi yoksa “karmaşık istek” mi olduğuna karar verir.
  2. Basit İstekler (Simple Requests): GET veya POST gibi standart istekler, özel başlık (header) içermiyorsa doğrudan sunucuya gönderilir.
  3. Karmaşık İstekler: Özel başlıklar, PUT/DELETE metodları veya JSON içerik tipi içeren istekler için tarayıcı önce bir ön kontrol isteği (preflight request) gönderir.
  4. Sunucu Yanıtı: Sunucu, uygun CORS başlıklarını döndürürse istek gerçekleştirilir. Aksi halde tarayıcı isteği engeller.

Ön Kontrol İsteği (Preflight Request) Nedir?

Ön kontrol isteği, asıl isteğin güvenli olup olmadığını kontrol etmek için tarayıcının otomatik olarak gönderdiği bir OPTIONS isteğidir [7]. Bu işlem tamamen otomatiktir ve frontend geliştiricisi olarak kendiniz bu isteği oluşturmanız gerekmez [8].

Ne Zaman Tetiklenir?

Şu durumlarda tarayıcı ön kontrol isteği gönderir [9]:

  • PUT, DELETE, PATCH gibi HTTP metodları kullanıldığında
  • Authorization, Content-Type: application/json gibi özel başlıklar eklendiğinde
  • Standart dışı içerik tipleri kullanıldığında

Nasıl Çalışır?

Diyelim ki React uygulamanızdan bir DELETE isteği göndermek istiyorsunuz. Tarayıcı önce şöyle bir OPTIONS isteği gönderir [10]:

OPTIONS /api/resource HTTP/1.1
Host: api.example.com
Origin: https://frontend.example.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: Authorization

Sunucu uygun şekilde yapılandırılmışsa şöyle yanıt verir:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization

Bu yanıttan sonra tarayıcı asıl DELETE isteğini göndermesine izin verir [11].

FastAPI’de CORS Ayarları

Artık teoriyi anladık, hadi pratiğe geçelim! FastAPI’de CORS ayarlamak için CORSMiddleware kullanacağız [12]. Bu ara katman yazılımı (middleware), Starlette kütüphanesinden gelir ve FastAPI tarafından hazır olarak sunulur [13].

Temel Kurulum

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

app = FastAPI()

# İzin verilen kaynakları tanımlıyoruz
origins = [
    "http://localhost:3000",      # React development server
    "http://localhost:5173",      # Vite development server
    "https://myapp.com",          # Production frontend
]

# CORS middleware'i ekliyoruz
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/")
async def root():
    return {"message": "Merhaba Dünya!"}

Parametrelerin Açıklaması

Bu parametreleri tek tek inceleyelim [14]:

allow_origins: Hangi kaynakların API’nize erişebileceğini belirler. Spesifik URL’ler veya ["*"] (tüm kaynaklar) kullanabilirsiniz. Ancak production ortamında ["*"] kullanmaktan kaçının [15]!

allow_credentials: Çerezler (cookies) ve yetkilendirme başlıklarının (authorization headers) isteklerle birlikte gönderilip gönderilemeyeceğini belirler. True olarak ayarlandığında, allow_origins parametresinde ["*"] kullanamazsınız [16].

allow_methods: İzin verilen HTTP metodlarını belirler. ["*"] tüm metodlara izin verir veya spesifik olarak ["GET", "POST", "PUT", "DELETE"] şeklinde tanımlayabilirsiniz.

allow_headers: İsteklerde hangi başlıkların kabul edileceğini belirler. ["*"] genellikle yeterlidir.

max_age: Ön kontrol yanıtlarının tarayıcı tarafından ne kadar süre önbelleğe alınacağını belirler (saniye cinsinden). Varsayılan değer 600 saniyedir [17].

React + FastAPI: Gerçek Dünya Senaryosu

Şimdi tam bir örnek üzerinden gidelim. Bir React frontend’i ve FastAPI backend’i olan basit bir uygulama yapacağız.

FastAPI Backend (main.py)

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

app = FastAPI()

# CORS ayarları
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class Item(BaseModel):
    name: str
    description: str = None

items = []

@app.get("/api/items")
async def get_items():
    return items

@app.post("/api/items")
async def create_item(item: Item):
    items.append(item)
    return {"message": "Öğe oluşturuldu", "item": item}

React Frontend (App.jsx)

import { useState, useEffect } from 'react';

function App() {
  const [items, setItems] = useState([]);
  const [name, setName] = useState('');

  useEffect(() => {
    fetchItems();
  }, []);

  const fetchItems = async () => {
    const response = await fetch('http://localhost:8000/api/items');
    const data = await response.json();
    setItems(data);
  };

  const addItem = async () => {
    await fetch('http://localhost:8000/api/items', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name }),
    });
    fetchItems();
    setName('');
  };

  return (
    <div>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button onClick={addItem}>Ekle</button>
      <ul>
        {items.map((item, i) => <li key={i}>{item.name}</li>)}
      </ul>
    </div>
  );
}

export default App;

Bu yapılandırmayla React uygulamanız FastAPI backend’inizle sorunsuz iletişim kurabilecek [18].

Yaygın Hatalar ve Çözümleri

1. “No ‘Access-Control-Allow-Origin’ header” Hatası

Bu en sık karşılaşılan hatadır. Çözüm adımları [19]:

  • CORS middleware’in eklendiğinden emin olun
  • allow_origins listesinde frontend URL’inizin tam olarak yazıldığını kontrol edin (http/https, port dahil)
  • FastAPI sunucusunu yeniden başlatın

2. Middleware Sırası Sorunu

CORS middleware’i her zaman ilk middleware olarak eklenmelidir [20]. Aksi halde, diğer middleware’ler hata fırlattığında CORS başlıkları eklenmez ve tarayıcı gerçek hatayı görmek yerine CORS hatası gösterir.

# DOĞRU SIRA
app.add_middleware(CORSMiddleware, ...)  # Önce CORS
app.add_middleware(AuthMiddleware, ...)   # Sonra diğerleri

3. Credentials ile Wildcard Kullanımı

allow_credentials=True ayarladığınızda allow_origins=["*"] kullanamazsınız [21]. Bu bir güvenlik gereksinimidir:

# YANLIŞ - Çalışmaz!
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,  # Wildcard ile credentials çakışır
)

# DOĞRU
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000"],
    allow_credentials=True,
)

4. 500 Hatası CORS Hatası Gibi Görünüyor

FastAPI’de bir sunucu hatası (500) oluştuğunda, yanıt CORS middleware’e ulaşmadan önce kesilir [22]. Bu durumda tarayıcı CORS hatası gösterir ama asıl sorun backend kodunuzdadır. Sunucu loglarını kontrol edin!

Güvenlik Tavsiyeleri: Development vs Production

Development Ortamı

Geliştirme sırasında daha rahat ayarlar kullanabilirsiniz:

# Development için
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

Production Ortamı

Canlı ortamda mutlaka kısıtlayıcı olun [23]:

# Production için
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "https://myapp.com",
        "https://www.myapp.com",
    ],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
)

En İyi Uygulamalar

  1. Spesifik kaynaklar belirleyin: Production’da asla ["*"] kullanmayın [24]
  2. Sadece gerekli metodlara izin verin: Tüm metodlar yerine kullandıklarınızı belirtin
  3. Credentials’ı dikkatli kullanın: Sadece gerekliyse allow_credentials=True yapın [25]
  4. Düzenli gözden geçirin: CORS ayarlarınızı deployment değişikliklerine göre güncelleyin [26]

Alternatif Çözümler

Vite Proxy Kullanımı

React uygulamanız Vite kullanıyorsa, development ortamında proxy kullanarak CORS sorununu tamamen atlayabilirsiniz [27]:

// vite.config.js
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true,
      },
    },
  },
};

Bu yapılandırmayla /api/items isteği otomatik olarak http://localhost:8000/api/items adresine yönlendirilir ve tarayıcı bunu aynı kaynak olarak görür.

Static Dosya Sunumu

CORS’u tamamen ortadan kaldırmanın başka bir yolu da frontend’i FastAPI üzerinden sunmaktır [28]:

from fastapi.staticfiles import StaticFiles

app.mount("/", StaticFiles(directory="static", html=True), name="static")

Sonuç

CORS ilk başta korkutucu görünebilir ama aslında mantığını anladığınızda oldukça basit. Unutmayın:

  • CORS bir tarayıcı güvenlik özelliğidir
  • Farklı kaynaklardan gelen istekleri kontrol eder
  • FastAPI’de CORSMiddleware ile kolayca yapılandırılır
  • Production’da her zaman spesifik kaynaklar belirleyin

Artık React + FastAPI projelerinizde CORS hatalarıyla karşılaştığınızda ne yapacağınızı biliyorsunuz. Hadi kodlamaya devam!

Kaynaklar

[1] MDN Web Docs, “Cross-Origin Resource Sharing (CORS)”, https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS

[2] FastAPI Official Documentation, “CORS (Cross-Origin Resource Sharing)”, https://fastapi.tiangolo.com/tutorial/cors/

[3] Wikipedia, “Cross-origin resource sharing”, https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

[4] MDN Web Docs, “Preflight request”, https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

[5] Vinay, “Demystifying CORS in FastAPI & React: A Practical Guide”, https://medium.com/tech-learners-journal/demystifying-cors-in-fastapi-react-a-practical-guide-cd788e66eb92

[6] Baeldung, “Cross-Origin Resource Sharing and Why We Need Preflight Requests”, https://www.baeldung.com/cs/cors-preflight-requests

[7] MDN Web Docs, “Preflight request”, https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

[8] Aanchal Fatwani, “Preflight Requests: A Beginner’s Guide”, https://aanchalfatwani.hashnode.dev/preflight-requests-a-beginners-guide

[9] Bale, “Understanding CORS and Preflight Requests in APIs”, https://medium.com/@bloodturtle/understanding-cors-and-preflight-requests-in-apis-e088ae13b417

[10] Sensedia Documentation, “What are preflight requests and how do they work?”, https://docs.sensedia.com/en/faqs/Latest/apis/preflight.html

[11] Chrome for Developers, “Private Network Access: introducing preflights”, https://developer.chrome.com/blog/private-network-access-preflight

[12] FastAPI Official Documentation, “CORS (Cross-Origin Resource Sharing)”, https://fastapi.tiangolo.com/tutorial/cors/

[13] StackHawk, “FastAPI: Configuring CORS for Python’s ASGI Framework”, https://www.stackhawk.com/blog/configuring-cors-in-fastapi/

[14] Joël-Steve N., “Implementation of CORS in FastAPI”, https://jnikenoueba.medium.com/implementation-of-cors-in-fastapi-81510a9625cd

[15] Mahdi Jafari, “Understanding and Enabling CORS in FastAPI: A Quick Guide”, https://mahdijafaridev.medium.com/understanding-and-enabling-cors-in-fastapi-a-quick-guide-5dd1003300d9

[16] Sai Lokesh Reddy, “FastAPI CORS Middleware: How to Allow Cross-Domain Requests Safely”, https://sailokesh.hashnode.dev/enable-and-configure-cors-in-fastapi

[17] FastAPI Official Documentation, “Advanced Middleware”, https://fastapi.tiangolo.com/advanced/middleware/

[18] Compile N Run, “FastAPI CORS Middleware”, https://www.compilenrun.com/docs/framework/fastapi/fastapi-middleware/fastapi-cors-middleware/

[19] Sentry, “FastAPI error: No Access-Control-Allow-Origin header”, https://sentry.io/answers/fastapi-error-no-access-control-allow-origin-header-is-present-on-the-requested-resource/

[20] David Muraya, “Blocked by CORS in FastAPI? Here’s How to Fix It”, https://davidmuraya.com/blog/fastapi-cors-configuration/

[21] GeeksforGeeks, “Configuring CORS in FastAPI”, https://www.geeksforgeeks.org/python/configuring-cors-in-fastapi/

[22] GitHub FastAPI Discussions, “CORSMiddleware not work”, https://github.com/fastapi/fastapi/discussions/7319

[23] PyTutorial, “Add CORS Middleware to FastAPI Apps”, https://pytutorial.com/add-cors-middleware-to-fastapi-apps/

[24] KodeKloud Notes, “What Is CORS”, https://notes.kodekloud.com/docs/Python-API-Development-with-FastAPI/Deployment/What-Is-CORS

[25] Microsoft Q&A, “CORS Error in FastAPI Backend from React Frontend”, https://learn.microsoft.com/en-us/answers/questions/2115649/cors-error-in-fastapi-backend-from-react-frontend

[26] Vinay, “Demystifying CORS in FastAPI & React”, https://vinaysit.wordpress.com/2024/11/07/demystifying-cors-in-fastapi-react-a-practical-guide-🌐🚀/

[27] GitHub Community Discussions, “Help Needed: Still Getting CORS Error Despite Correct Setup”, https://github.com/orgs/community/discussions/167600

[28] Sentry, “FastAPI error: No Access-Control-Allow-Origin header”, https://sentry.io/answers/fastapi-error-no-access-control-allow-origin-header-is-present-on-the-requested-resource/

0

Bir yanıt yazın

Password Requirements:

  • At least 8 characters
  • At least 1 lowercase letter
  • At least 1 uppercase letter
  • At least 1 numerical number
  • At least 1 special character