Browse Source
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>pull/15167/head
committed by
GitHub
6 changed files with 522 additions and 0 deletions
@ -0,0 +1,63 @@ |
|||||
|
# JSON'da Bytes'i Base64 Olarak Kullanma { #json-with-bytes-as-base64 } |
||||
|
|
||||
|
Uygulamanız JSON veri alıp gönderiyorsa ve bunun içine ikili (binary) veri eklemeniz gerekiyorsa, veriyi base64 olarak encode edebilirsiniz. |
||||
|
|
||||
|
## Base64 ve Dosyalar { #base64-vs-files } |
||||
|
|
||||
|
İkili veriyi JSON içinde encode etmek yerine, yükleme için [Request Files](../tutorial/request-files.md) ve gönderim için [Custom Response - FileResponse](./custom-response.md#fileresponse--fileresponse-) kullanıp kullanamayacağınıza önce bir bakın. |
||||
|
|
||||
|
JSON sadece UTF-8 ile encode edilmiş string'ler içerebilir, dolayısıyla ham bytes içeremez. |
||||
|
|
||||
|
Base64 ikili veriyi string olarak encode edebilir, ancak bunu yapmak için orijinal ikili veriden daha fazla karakter kullanır; bu yüzden genellikle normal dosyalardan daha verimsiz olur. |
||||
|
|
||||
|
Base64'ü sadece gerçekten JSON içine ikili veri koymanız gerekiyorsa ve bunun için dosya kullanamıyorsanız tercih edin. |
||||
|
|
||||
|
## Pydantic `bytes` { #pydantic-bytes } |
||||
|
|
||||
|
`bytes` alanları olan bir Pydantic model tanımlayabilir, ardından model config'inde `val_json_bytes` kullanarak giriş JSON verisini base64 ile doğrulamasını (validate) söyleyebilirsiniz; bu doğrulamanın bir parçası olarak base64 string'i bytes'a decode eder. |
||||
|
|
||||
|
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} |
||||
|
|
||||
|
`/docs`'a bakarsanız, `data` alanının base64 ile encode edilmiş bytes beklediğini görürsünüz: |
||||
|
|
||||
|
<div class="screenshot"> |
||||
|
<img src="/img/tutorial/json-base64-bytes/image01.png"> |
||||
|
</div> |
||||
|
|
||||
|
Şöyle bir request gönderebilirsiniz: |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"description": "Some data", |
||||
|
"data": "aGVsbG8=" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
/// tip | İpucu |
||||
|
|
||||
|
`aGVsbG8=` değeri, `hello` kelimesinin base64 encoding'idir. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Sonrasında Pydantic base64 string'ini decode eder ve modelin `data` alanında size orijinal bytes'ı verir. |
||||
|
|
||||
|
Şöyle bir response alırsınız: |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"description": "Some data", |
||||
|
"content": "hello" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## Çıkış Verisi için Pydantic `bytes` { #pydantic-bytes-for-output-data } |
||||
|
|
||||
|
Çıkış verisi için de model config'inde `ser_json_bytes` ile `bytes` alanları kullanabilirsiniz; Pydantic JSON response üretirken bytes'ı base64 olarak serialize eder. |
||||
|
|
||||
|
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} |
||||
|
|
||||
|
## Giriş ve Çıkış Verisi için Pydantic `bytes` { #pydantic-bytes-for-input-and-output-data } |
||||
|
|
||||
|
Elbette, aynı modeli base64 kullanacak şekilde yapılandırıp hem girişte (*validate*) `val_json_bytes` ile hem de çıkışta (*serialize*) `ser_json_bytes` ile JSON veri alıp gönderirken kullanabilirsiniz. |
||||
|
|
||||
|
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} |
||||
@ -0,0 +1,117 @@ |
|||||
|
# Veri Akışı { #stream-data } |
||||
|
|
||||
|
Veriyi JSON olarak yapılandırabiliyorsanız, [JSON Lines Akışı](../tutorial/stream-json-lines.md) kullanın. |
||||
|
|
||||
|
Ancak saf ikili (binary) veri ya da string akıtmak istiyorsanız, bunu şöyle yapabilirsiniz. |
||||
|
|
||||
|
/// info | Bilgi |
||||
|
|
||||
|
FastAPI 0.134.0 ile eklendi. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Kullanım Senaryoları { #use-cases } |
||||
|
|
||||
|
Doğrudan bir AI LLM (Büyük Dil Modeli) servisinin çıktısından saf string'leri akıtmak istediğinizde kullanabilirsiniz. |
||||
|
|
||||
|
Ayrıca **büyük ikili (binary) dosyaları** akıtmak için de kullanabilirsiniz; veriyi okurken her parçayı (chunk) sırayla gönderirsiniz, tamamını belleğe almak zorunda kalmazsınız. |
||||
|
|
||||
|
Bu şekilde **video** veya **ses** de akıtabilirsiniz; hatta işledikçe üretilip gönderilebilir. |
||||
|
|
||||
|
## `yield` ile bir `StreamingResponse` { #a-streamingresponse-with-yield } |
||||
|
|
||||
|
*Path operation function* içinde `response_class=StreamingResponse` belirtirseniz, her veri parçasını sırayla göndermek için `yield` kullanabilirsiniz. |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} |
||||
|
|
||||
|
FastAPI her veri parçasını olduğu gibi `StreamingResponse`'a verir; JSON'a ya da benzeri bir formata dönüştürmeye çalışmaz. |
||||
|
|
||||
|
### Async Olmayan Path Operation Function'lar { #non-async-path-operation-functions } |
||||
|
|
||||
|
Normal `def` fonksiyonlarını (yani `async` olmadan) da kullanabilir ve aynı şekilde `yield` yazabilirsiniz. |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} |
||||
|
|
||||
|
### Tip Annotasyonu Yok { #no-annotation } |
||||
|
|
||||
|
İkili (binary) veri akıtıyorsanız dönüş tipi annotasyonu belirtmeniz şart değildir. |
||||
|
|
||||
|
FastAPI veriyi Pydantic ile JSON'a çevirmeye veya herhangi bir şekilde serileştirmeye çalışmayacağı için, bu durumda tip annotasyonu sadece editörünüz ve araçlarınız içindir; FastAPI tarafından kullanılmaz. |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} |
||||
|
|
||||
|
Bu aynı zamanda `StreamingResponse` ile veriyi tam olarak ihtiyaç duyduğunuz biçimde üretme ve encode etme konusunda hem bir özgürlük hem de bir sorumluluk verdiği anlamına gelir; tip annotasyonlarından bağımsızdır. 🤓 |
||||
|
|
||||
|
### Bytes Akışı { #stream-bytes } |
||||
|
|
||||
|
Başlıca kullanım senaryolarından biri string yerine `bytes` akıtmaktır; elbette bunu yapabilirsiniz. |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} |
||||
|
|
||||
|
## Özel bir `PNGStreamingResponse` { #a-custom-pngstreamingresponse } |
||||
|
|
||||
|
Yukarıdaki örneklerde veri baytları akıtıldı, ancak response'ta bir `Content-Type` header'ı yoktu; bu nedenle istemci hangi tür veriyi aldığını bilmiyordu. |
||||
|
|
||||
|
Akıttığınız veri türüne uygun `Content-Type` header'ını ayarlayan, `StreamingResponse`'tan türetilmiş özel bir alt sınıf (subclass) oluşturabilirsiniz. |
||||
|
|
||||
|
Örneğin, `media_type` özniteliğini kullanarak `Content-Type` header'ını `image/png` olarak ayarlayan bir `PNGStreamingResponse` oluşturabilirsiniz: |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} |
||||
|
|
||||
|
Ardından bu yeni sınıfı *path operation function* içinde `response_class=PNGStreamingResponse` olarak kullanabilirsiniz: |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} |
||||
|
|
||||
|
### Bir Dosyayı Simüle Etme { #simulate-a-file } |
||||
|
|
||||
|
Bu örnekte, yalnızca bellekte yaşayan ama aynı arayüzü kullanmamıza izin veren, dosya benzeri bir nesne olan `io.BytesIO` ile bir dosyayı simüle ediyoruz. |
||||
|
|
||||
|
Örneğin, bir dosyada yapabileceğimiz gibi, içeriğini tüketmek için üzerinde iterate edebiliriz. |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} |
||||
|
|
||||
|
/// note | Teknik Detaylar |
||||
|
|
||||
|
Diğer iki değişken olan `image_base64` ve `binary_image`, Base64 ile encode edilmiş bir görüntüdür; daha sonra bayt'lara çevrilip `io.BytesIO`'ya aktarılır. |
||||
|
|
||||
|
Sadece bu örnek aynı dosyada yaşayabilsin, kopyalayıp olduğu gibi çalıştırabilesiniz diye. 🥚 |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
`with` bloğu kullanarak, jeneratör fonksiyonu (içinde `yield` olan fonksiyon) tamamlandığında dosya benzeri nesnenin kapandığından emin oluruz. Yani response gönderimi bittikten sonra. |
||||
|
|
||||
|
Bu özel örnekte o kadar da önemli değil, çünkü sahte ve bellekte (yani `io.BytesIO` ile). Ancak gerçek bir dosyada, onunla işiniz bittiğinde dosyanın kapandığından emin olmak önemlidir. |
||||
|
|
||||
|
### Dosyalar ve Async { #files-and-async } |
||||
|
|
||||
|
Çoğu durumda dosya benzeri nesneler, varsayılan olarak async ve await ile uyumlu değildir. |
||||
|
|
||||
|
Örneğin, `await file.read()` ya da `async for chunk in file` gibi şeyler yoktur. |
||||
|
|
||||
|
Ve birçok durumda, diskte ya da ağda okundukları için, okumak engelleyici (event loop'u bloke edebilen) bir işlem olabilir. |
||||
|
|
||||
|
/// info | Bilgi |
||||
|
|
||||
|
Yukarıdaki örnek aslında bir istisna; çünkü `io.BytesIO` nesnesi zaten bellekte, dolayısıyla onu okumak hiçbir şeyi bloke etmez. |
||||
|
|
||||
|
Ancak çoğu durumda bir dosyayı veya dosya benzeri bir nesneyi okumak bloke edicidir. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Event loop'u bloke etmemek için, *path operation function*'ı `async def` yerine normal `def` ile tanımlayabilirsiniz; böylece FastAPI ana döngüyü bloke etmemek için bunu bir thread pool worker (iş parçacığı havuzu çalışanı) üzerinde çalıştırır. |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} |
||||
|
|
||||
|
/// tip | İpucu |
||||
|
|
||||
|
Async bir fonksiyonun içinden bloklayıcı kod çağırmanız ya da bloklayıcı bir fonksiyonun içinden async bir fonksiyon çağırmanız gerekirse, FastAPI'nin kardeş kütüphanesi olan [Asyncer](https://asyncer.tiangolo.com)'ı kullanabilirsiniz. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
### `yield from` { #yield-from } |
||||
|
|
||||
|
Bir şeyin (ör. dosya benzeri bir nesne) üzerinde iterate ederken, her öğe için `yield` yapıyorsanız, `for` döngüsünü yazmak yerine `yield from` ile her öğeyi doğrudan yield edebilirsiniz. |
||||
|
|
||||
|
Bu FastAPI'ye özgü değildir, tamamen Python'dur, ama bilinmesi güzel bir püf noktasıdır. 😎 |
||||
|
|
||||
|
{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} |
||||
@ -0,0 +1,88 @@ |
|||||
|
# Sıkı Content-Type Kontrolü { #strict-content-type-checking } |
||||
|
|
||||
|
Varsayılan olarak FastAPI, JSON request body'leri için sıkı Content-Type header kontrolü uygular. Bu, JSON request'lerin body'lerinin JSON olarak parse edilebilmesi için geçerli bir Content-Type header'ı (örn. application/json) içermesi gerektiği anlamına gelir. |
||||
|
|
||||
|
## CSRF Riski { #csrf-risk } |
||||
|
|
||||
|
Bu varsayılan davranış, çok belirli bir senaryoda bir sınıf Cross-Site Request Forgery (CSRF) saldırılarına karşı koruma sağlar. |
||||
|
|
||||
|
Bu saldırılar, tarayıcıların aşağıdaki durumlarda herhangi bir CORS preflight kontrolü yapmadan script’lerin request göndermesine izin vermesinden faydalanır: |
||||
|
|
||||
|
- bir Content-Type header’ı yoksa (örn. body olarak Blob ile fetch() kullanıldığında) |
||||
|
- ve herhangi bir kimlik doğrulama bilgisi gönderilmiyorsa. |
||||
|
|
||||
|
Bu tür saldırılar özellikle şu durumlarda önemlidir: |
||||
|
|
||||
|
- uygulama yerelde (örn. localhost’ta) veya dahili bir ağda çalışıyorsa |
||||
|
- ve uygulamada hiç kimlik doğrulama yoksa, aynı ağdan gelen her request’in güvenilir olduğu varsayılıyorsa. |
||||
|
|
||||
|
## Örnek Saldırı { #example-attack } |
||||
|
|
||||
|
Yerelde çalışan bir AI agent’ı (yapay zeka ajanı) çalıştırmanın bir yolunu geliştirdiğinizi düşünün. |
||||
|
|
||||
|
Bir API sunuyor: |
||||
|
|
||||
|
``` |
||||
|
http://localhost:8000/v1/agents/multivac |
||||
|
``` |
||||
|
|
||||
|
Ayrıca bir frontend var: |
||||
|
|
||||
|
``` |
||||
|
http://localhost:8000 |
||||
|
``` |
||||
|
|
||||
|
/// tip | İpucu |
||||
|
|
||||
|
İkisinin de host’u aynıdır. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Frontend’i kullanarak AI agent’a sizin adınıza işler yaptırabiliyorsunuz. |
||||
|
|
||||
|
Uygulama yerelde çalıştığı ve açık internette olmadığı için, sadece yerel ağa güvenip herhangi bir kimlik doğrulama kurmamaya karar verdiniz. |
||||
|
|
||||
|
Kullanıcılarınızdan biri de bunu indirip yerelde çalıştırabilir. |
||||
|
|
||||
|
Sonra kötü niyetli bir web sitesini açabilir, örneğin: |
||||
|
|
||||
|
``` |
||||
|
https://evilhackers.example.com |
||||
|
``` |
||||
|
|
||||
|
Ve bu kötü niyetli site, body olarak Blob kullanan fetch() ile yerel API’ye request’ler gönderebilir: |
||||
|
|
||||
|
``` |
||||
|
http://localhost:8000/v1/agents/multivac |
||||
|
``` |
||||
|
|
||||
|
Kötü niyetli sitenin host’u ile yerel uygulamanın host’u farklı olsa bile, tarayıcı şu nedenlerle bir CORS preflight isteği tetiklemez: |
||||
|
|
||||
|
- Herhangi bir kimlik doğrulama yoktur, bu nedenle credential göndermesi gerekmez. |
||||
|
- Tarayıcı, Content-Type header’ı eksik olduğundan JSON gönderildiğini düşünmez. |
||||
|
|
||||
|
Böylece kötü niyetli site, yerel AI agent’ın kullanıcının eski patronuna sinirli mesajlar göndermesini sağlayabilir... ya da daha kötüsü. 😅 |
||||
|
|
||||
|
## Açık İnternet { #open-internet } |
||||
|
|
||||
|
Uygulamanız açık internetteyse “ağa güvenmez” ve kimlik doğrulama olmadan kimsenin ayrıcalıklı request’ler göndermesine izin vermezsiniz. |
||||
|
|
||||
|
Saldırganlar tarayıcı etkileşimine ihtiyaç duymadan basitçe bir script çalıştırıp API’nize request gönderebilir, bu yüzden muhtemelen ayrıcalıklı endpoint’leri zaten güvenceye almışsınızdır. |
||||
|
|
||||
|
Bu durumda bu saldırı/riski sizler için geçerli değildir. |
||||
|
|
||||
|
Bu risk ve saldırı, esasen uygulama sadece yerel ağda çalıştığında ve tek koruma varsayımının bu olduğu durumlarda önemlidir. |
||||
|
|
||||
|
## Content-Type Olmadan Gelen Request’lere İzin Vermek { #allowing-requests-without-content-type } |
||||
|
|
||||
|
Content-Type header’ı göndermeyen client’ları desteklemeniz gerekiyorsa, strict kontrolü strict_content_type=False ayarıyla kapatabilirsiniz: |
||||
|
|
||||
|
{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} |
||||
|
|
||||
|
Bu ayarla, Content-Type header’ı olmayan request’lerin body’si JSON olarak parse edilir. Bu, FastAPI’nin eski sürümlerindeki davranışla aynıdır. |
||||
|
|
||||
|
/// info | Bilgi |
||||
|
|
||||
|
Bu davranış ve yapılandırma FastAPI 0.132.0’da eklendi. |
||||
|
|
||||
|
/// |
||||
@ -0,0 +1,23 @@ |
|||||
|
# Editör Desteği { #editor-support } |
||||
|
|
||||
|
Resmi [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode), FastAPI geliştirme akışınızı iyileştirir: *path operation* keşfi, gezinme, FastAPI Cloud’a deploy ve canlı log akışı. |
||||
|
|
||||
|
Daha fazla ayrıntı için, GitHub deposundaki README’ye bakın: [GitHub repository](https://github.com/fastapi/fastapi-vscode). |
||||
|
|
||||
|
## Kurulum ve Yükleme { #setup-and-installation } |
||||
|
|
||||
|
**FastAPI Extension**, hem [VS Code](https://code.visualstudio.com/) hem de [Cursor](https://www.cursor.com/) için mevcuttur. Her editörde Extensions panelinden "FastAPI" aratıp **FastAPI Labs** tarafından yayımlanan eklentiyi seçerek doğrudan kurabilirsiniz. Eklenti [vscode.dev](https://vscode.dev) ve [github.dev](https://github.dev) gibi tarayıcı tabanlı editörlerde de çalışır. |
||||
|
|
||||
|
### Uygulama Keşfi { #application-discovery } |
||||
|
|
||||
|
Varsayılan olarak, eklenti çalışma alanınızda `FastAPI()` örnekleyen dosyaları tarayarak FastAPI uygulamalarını otomatik olarak keşfeder. Proje yapınız nedeniyle otomatik algılama çalışmazsa, `pyproject.toml` içindeki `[tool.fastapi]` ile veya VS Code ayarı `fastapi.entryPoint` üzerinden modül gösterimiyle (ör. `myapp.main:app`) bir entrypoint belirtebilirsiniz. |
||||
|
|
||||
|
## Özellikler { #features } |
||||
|
|
||||
|
- **Path Operation Explorer** - Uygulamanızdaki tüm <dfn title="route'lar, endpoint'ler">*path operation*'lar</dfn> için yan panelde bir ağaç görünümü. Herhangi bir route veya router tanımına tıklayarak atlayın. |
||||
|
- **Route Search** - <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd> (macOS: <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd>) ile path, method veya ada göre arama. |
||||
|
- **CodeLens Navigation** - Test client çağrılarının (ör. `client.get('/items')`) üzerinde, ilgili *path operation*’a atlayan tıklanabilir bağlantılar; testlerle implementasyon arasında hızlı gezinme sağlar. |
||||
|
- **Deploy to FastAPI Cloud** - Uygulamanızı tek tıkla [FastAPI Cloud](https://fastapicloud.com/)'a deploy edin. |
||||
|
- **Stream Application Logs** - FastAPI Cloud’a deploy ettiğiniz uygulamadan, seviye filtreleme ve metin arama ile gerçek zamanlı log akışı. |
||||
|
|
||||
|
Eklentinin özelliklerine hızlıca aşina olmak isterseniz, Komut Paleti’ni açın (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> veya macOS: <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>), "Welcome: Open walkthrough..." öğesini seçin ve ardından "Get started with FastAPI" walkthrough’unu açın. |
||||
@ -0,0 +1,120 @@ |
|||||
|
# Server-Sent Events (SSE) { #server-sent-events-sse } |
||||
|
|
||||
|
İstemciye veri akışını **Server-Sent Events** (SSE) ile sağlayabilirsiniz. |
||||
|
|
||||
|
Bu, [JSON Lines Akışı](stream-json-lines.md) ile benzerdir ancak tarayıcılar tarafından yerel olarak desteklenen [`EventSource` API'si](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) ile `text/event-stream` formatını kullanır. |
||||
|
|
||||
|
/// info | Bilgi |
||||
|
|
||||
|
FastAPI 0.135.0'da eklendi. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Server-Sent Events Nedir? { #what-are-server-sent-events } |
||||
|
|
||||
|
SSE, HTTP üzerinden sunucudan istemciye veri akışı için bir standarttır. |
||||
|
|
||||
|
Her olay, aralarında boş satırlar bulunan ve `data`, `event`, `id` ve `retry` gibi "alanlar" içeren küçük bir metin bloğudur. |
||||
|
|
||||
|
Şuna benzer: |
||||
|
|
||||
|
``` |
||||
|
data: {"name": "Portal Gun", "price": 999.99} |
||||
|
|
||||
|
data: {"name": "Plumbus", "price": 32.99} |
||||
|
|
||||
|
``` |
||||
|
|
||||
|
SSE; yapay zekâ sohbet akışı, canlı bildirimler, log ve gözlemlenebilirlik (observability) gibi senaryolarda ve sunucunun istemciye güncellemeleri ittiği diğer durumlarda yaygın olarak kullanılır. |
||||
|
|
||||
|
/// tip | İpucu |
||||
|
|
||||
|
İkili (binary) veri akışı yapmak istiyorsanız, gelişmiş kılavuza bakın: [Veri Akışı](../advanced/stream-data.md). |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## FastAPI ile SSE Akışı { #stream-sse-with-fastapi } |
||||
|
|
||||
|
FastAPI ile SSE akışı yapmak için, *path operation function* içinde `yield` kullanın ve `response_class=EventSourceResponse` olarak ayarlayın. |
||||
|
|
||||
|
`EventSourceResponse`'u `fastapi.sse` içinden içe aktarın: |
||||
|
|
||||
|
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *} |
||||
|
|
||||
|
Yield edilen her öğe JSON olarak kodlanır ve bir SSE olayının `data:` alanında gönderilir. |
||||
|
|
||||
|
Dönüş tipini `AsyncIterable[Item]` olarak bildirirseniz, FastAPI bunu Pydantic ile veriyi **doğrulamak**, **belgelemek** ve **serileştirmek** için kullanır. |
||||
|
|
||||
|
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *} |
||||
|
|
||||
|
/// tip | İpucu |
||||
|
|
||||
|
Pydantic serileştirmeyi **Rust** tarafında yapacağından, dönüş tipi bildirmediğiniz duruma göre çok daha yüksek **performans** elde edersiniz. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
### Async Olmayan Path Operation Fonksiyonları { #non-async-path-operation-functions } |
||||
|
|
||||
|
Normal `def` fonksiyonlarını (yani `async` olmadan) da kullanabilir ve aynı şekilde `yield` kullanabilirsiniz. |
||||
|
|
||||
|
FastAPI, event loop'u bloke etmeyecek şekilde doğru biçimde çalışmasını sağlar. |
||||
|
|
||||
|
Bu örnekte fonksiyon async olmadığı için doğru dönüş tipi `Iterable[Item]` olur: |
||||
|
|
||||
|
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *} |
||||
|
|
||||
|
### Dönüş Tipi Olmadan { #no-return-type } |
||||
|
|
||||
|
Dönüş tipini belirtmeyebilirsiniz. FastAPI, veriyi dönüştürmek ve göndermek için [`jsonable_encoder`](./encoder.md) kullanır. |
||||
|
|
||||
|
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *} |
||||
|
|
||||
|
## `ServerSentEvent` { #serversentevent } |
||||
|
|
||||
|
`event`, `id`, `retry` veya `comment` gibi SSE alanlarını ayarlamanız gerekirse, düz veri yerine `ServerSentEvent` nesneleri yield edebilirsiniz. |
||||
|
|
||||
|
`ServerSentEvent`'i `fastapi.sse` içinden içe aktarın: |
||||
|
|
||||
|
{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *} |
||||
|
|
||||
|
`data` alanı her zaman JSON olarak kodlanır. Pydantic modelleri dâhil, JSON olarak serileştirilebilen herhangi bir değeri geçebilirsiniz. |
||||
|
|
||||
|
## Ham Veri { #raw-data } |
||||
|
|
||||
|
Veriyi JSON kodlaması olmadan göndermeniz gerekiyorsa, `data` yerine `raw_data` kullanın. |
||||
|
|
||||
|
Bu, önceden biçimlendirilmiş metin, log satırları veya `[DONE]` gibi özel <dfn title="Özel bir koşulu veya durumu belirtmek için kullanılan değer">"işaretçi"</dfn> değerleri göndermek için kullanışlıdır. |
||||
|
|
||||
|
{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *} |
||||
|
|
||||
|
/// note | Not |
||||
|
|
||||
|
`data` ve `raw_data` birbirini dışlar. Her `ServerSentEvent` için bunlardan yalnızca birini ayarlayabilirsiniz. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## `Last-Event-ID` ile Devam Etme { #resuming-with-last-event-id } |
||||
|
|
||||
|
Bir tarayıcı bağlantı koptuktan sonra yeniden bağlandığında, son aldığı `id`'yi `Last-Event-ID` header'ında gönderir. |
||||
|
|
||||
|
Bunu bir header parametresi olarak okuyup, istemcinin kaldığı yerden akışı sürdürmek için kullanabilirsiniz: |
||||
|
|
||||
|
{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *} |
||||
|
|
||||
|
## POST ile SSE { #sse-with-post } |
||||
|
|
||||
|
SSE, sadece `GET` değil, **tüm HTTP metodlarıyla** çalışır. |
||||
|
|
||||
|
Bu, SSE'yi `POST` üzerinden akıtan [MCP](https://modelcontextprotocol.io) gibi protokoller için kullanışlıdır: |
||||
|
|
||||
|
{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *} |
||||
|
|
||||
|
## Teknik Detaylar { #technical-details } |
||||
|
|
||||
|
FastAPI, bazı SSE en iyi uygulamalarını kutudan çıktığı gibi uygular. |
||||
|
|
||||
|
- [HTML spesifikasyonu: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes) önerisine uygun olarak, bazı proxy'lerin bağlantıyı kapatmasını önlemek için, 15 saniye boyunca hiç mesaj gelmezse **"keep alive" `ping` yorumu** gönderir. |
||||
|
- Akışın **cache'lenmesini önlemek** için `Cache-Control: no-cache` header'ını ayarlar. |
||||
|
- Nginx gibi bazı proxy'lerde **buffering'i önlemek** için özel `X-Accel-Buffering: no` header'ını ayarlar. |
||||
|
|
||||
|
Bunun için ekstra bir şey yapmanız gerekmez, doğrudan çalışır. 🤓 |
||||
@ -0,0 +1,111 @@ |
|||||
|
# JSON Lines Akışı { #stream-json-lines } |
||||
|
|
||||
|
Bir veri dizisini “akış” olarak göndermek istediğiniz durumlar olabilir; bunu **JSON Lines** ile yapabilirsiniz. |
||||
|
|
||||
|
/// info | Bilgi |
||||
|
|
||||
|
FastAPI 0.134.0 ile eklendi. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Akış (Stream) Nedir? { #what-is-a-stream } |
||||
|
|
||||
|
Verileri “streaming” olarak göndermek, uygulamanızın tüm öğe dizisi hazır olmasını beklemeden, öğeleri istemciye göndermeye başlaması demektir. |
||||
|
|
||||
|
Yani ilk öğeyi gönderirsiniz, istemci onu alıp işlemeye başlar, bu sırada siz bir sonraki öğeyi üretmeye devam edebilirsiniz. |
||||
|
|
||||
|
```mermaid |
||||
|
sequenceDiagram |
||||
|
participant App |
||||
|
participant Client |
||||
|
|
||||
|
App->>App: Produce Item 1 |
||||
|
App->>Client: Send Item 1 |
||||
|
App->>App: Produce Item 2 |
||||
|
Client->>Client: Process Item 1 |
||||
|
App->>Client: Send Item 2 |
||||
|
App->>App: Produce Item 3 |
||||
|
Client->>Client: Process Item 2 |
||||
|
App->>Client: Send Item 3 |
||||
|
Client->>Client: Process Item 3 |
||||
|
Note over App: Keeps producing... |
||||
|
Note over Client: Keeps consuming... |
||||
|
``` |
||||
|
|
||||
|
Hatta, sürekli veri gönderdiğiniz sonsuz bir akış da olabilir. |
||||
|
|
||||
|
## JSON Lines { #json-lines } |
||||
|
|
||||
|
Bu tür durumlarda, her satıra bir JSON nesnesi gönderdiğiniz bir biçim olan “**JSON Lines**” kullanmak yaygındır. |
||||
|
|
||||
|
Response’un `application/json` yerine `application/jsonl` içerik türü (Content-Type) olur ve body aşağıdaki gibi görünür: |
||||
|
|
||||
|
```json |
||||
|
{"name": "Plumbus", "description": "A multi-purpose household device."} |
||||
|
{"name": "Portal Gun", "description": "A portal opening device."} |
||||
|
{"name": "Meeseeks Box", "description": "A box that summons a Meeseeks."} |
||||
|
``` |
||||
|
|
||||
|
Bir JSON dizisine (Python list eşdeğeri) çok benzer; ancak öğeler `[]` içine alınmak ve araya `,` konmak yerine, her satırda **bir JSON nesnesi** vardır; bunlar yeni satır karakteri ile ayrılır. |
||||
|
|
||||
|
/// info | Bilgi |
||||
|
|
||||
|
Önemli nokta, uygulamanız her satırı sırayla üretebilirken, istemcinin de önceki satırları tüketmeye devam edebilmesidir. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// note | Teknik Detaylar |
||||
|
|
||||
|
Her JSON nesnesi yeni bir satırla ayrıldığı için, içeriklerinde gerçek yeni satır karakterleri bulunamaz; ancak JSON standardının bir parçası olan kaçışlı yeni satırlar (`\n`) bulunabilir. |
||||
|
|
||||
|
Genelde bununla sizin uğraşmanız gerekmez, otomatik olarak halledilir, okumaya devam edin. 🤓 |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Kullanım Senaryoları { #use-cases } |
||||
|
|
||||
|
Bunu bir **AI LLM** servisinden, **loglar**dan veya **telemetri**den ya da **JSON** öğeleri halinde yapılandırılabilen başka tür verilerden akış yapmak için kullanabilirsiniz. |
||||
|
|
||||
|
/// tip | İpucu |
||||
|
|
||||
|
İkili (binary) veri akışı yapmak istiyorsanız, örneğin video veya ses, gelişmiş kılavuza bakın: [Veri Akışı](../advanced/stream-data.md). |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## FastAPI ile JSON Lines Akışı { #stream-json-lines-with-fastapi } |
||||
|
|
||||
|
FastAPI ile JSON Lines akışı yapmak için, *path operation function* içinde `return` kullanmak yerine, her öğeyi sırayla üretmek için `yield` kullanabilirsiniz. |
||||
|
|
||||
|
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *} |
||||
|
|
||||
|
Göndermek istediğiniz her JSON öğesi `Item` tipindeyse (bir Pydantic modeli) ve fonksiyon async ise, dönüş tipini `AsyncIterable[Item]` olarak belirtebilirsiniz: |
||||
|
|
||||
|
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *} |
||||
|
|
||||
|
Dönüş tipini belirtirseniz, FastAPI bu tipi kullanarak veriyi **doğrular**, OpenAPI’de **dokümante** eder, **filtreler** ve Pydantic ile **serileştirir**. |
||||
|
|
||||
|
/// tip | İpucu |
||||
|
|
||||
|
Pydantic serileştirmeyi **Rust** tarafında yapacağı için, dönüş tipi belirtmediğiniz duruma göre çok daha yüksek **performans** elde edersiniz. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
### Async Olmayan path operation function'lar { #non-async-path-operation-functions } |
||||
|
|
||||
|
`async` olmadan normal `def` fonksiyonları da kullanabilir ve aynı şekilde `yield` yazabilirsiniz. |
||||
|
|
||||
|
FastAPI, event loop’u bloklamayacak şekilde doğru çalışmasını garanti eder. |
||||
|
|
||||
|
Bu durumda fonksiyon async olmadığı için doğru dönüş tipi `Iterable[Item]` olur: |
||||
|
|
||||
|
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *} |
||||
|
|
||||
|
### Dönüş Tipi Olmadan { #no-return-type } |
||||
|
|
||||
|
Dönüş tipini belirtmeyebilirsiniz de. Bu durumda FastAPI, veriyi JSON’a serileştirilebilir bir yapıya dönüştürmek için [`jsonable_encoder`](./encoder.md)’ı kullanır ve ardından JSON Lines olarak gönderir. |
||||
|
|
||||
|
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *} |
||||
|
|
||||
|
## Server-Sent Events (SSE) { #server-sent-events-sse } |
||||
|
|
||||
|
FastAPI, Server-Sent Events (SSE) için de birinci sınıf destek sağlar; benzerlerdir ancak birkaç ekstra ayrıntı vardır. Bir sonraki bölümden öğrenebilirsiniz: [Server-Sent Events (SSE)](server-sent-events.md). 🤓 |
||||
Loading…
Reference in new issue