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