From cd5869b897bf38282a6b989b07e7e2fbf0aa14a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 19 Mar 2026 19:12:26 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20for=20es?= =?UTF-8?q?=20(add-missing)=20(#15154)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/es/docs/advanced/json-base64-bytes.md | 63 ++++++++++ docs/es/docs/advanced/stream-data.md | 117 ++++++++++++++++++ docs/es/docs/advanced/strict-content-type.md | 88 ++++++++++++++ docs/es/docs/editor-support.md | 23 ++++ docs/es/docs/tutorial/server-sent-events.md | 120 +++++++++++++++++++ docs/es/docs/tutorial/stream-json-lines.md | 111 +++++++++++++++++ 6 files changed, 522 insertions(+) create mode 100644 docs/es/docs/advanced/json-base64-bytes.md create mode 100644 docs/es/docs/advanced/stream-data.md create mode 100644 docs/es/docs/advanced/strict-content-type.md create mode 100644 docs/es/docs/editor-support.md create mode 100644 docs/es/docs/tutorial/server-sent-events.md create mode 100644 docs/es/docs/tutorial/stream-json-lines.md diff --git a/docs/es/docs/advanced/json-base64-bytes.md b/docs/es/docs/advanced/json-base64-bytes.md new file mode 100644 index 0000000000..12936722c7 --- /dev/null +++ b/docs/es/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# JSON con Bytes como Base64 { #json-with-bytes-as-base64 } + +Si tu app necesita recibir y enviar datos JSON, pero necesitas incluir datos binarios en él, puedes codificarlos como base64. + +## Base64 vs Archivos { #base64-vs-files } + +Considera primero si puedes usar [Archivos en request](../tutorial/request-files.md) para subir datos binarios y [Response personalizada - FileResponse](./custom-response.md#fileresponse--fileresponse-) para enviar datos binarios, en lugar de codificarlos en JSON. + +JSON solo puede contener strings codificados en UTF-8, así que no puede contener bytes crudos. + +Base64 puede codificar datos binarios en strings, pero para hacerlo necesita usar más caracteres que los datos binarios originales, así que normalmente sería menos eficiente que los archivos normales. + +Usa base64 solo si definitivamente necesitas incluir datos binarios en JSON y no puedes usar archivos para eso. + +## Pydantic `bytes` { #pydantic-bytes } + +Puedes declarar un modelo de Pydantic con campos `bytes`, y luego usar `val_json_bytes` en la configuración del modelo para indicarle que use base64 para validar datos JSON de entrada; como parte de esa validación decodificará el string base64 en bytes. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +Si revisas `/docs`, verás que el campo `data` espera bytes codificados en base64: + +
+ +
+ +Podrías enviar un request como: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip | Consejo + +`aGVsbG8=` es la codificación base64 de `hello`. + +/// + +Y luego Pydantic decodificará el string base64 y te dará los bytes originales en el campo `data` del modelo. + +Recibirás una response como: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## Pydantic `bytes` para datos de salida { #pydantic-bytes-for-output-data } + +También puedes usar campos `bytes` con `ser_json_bytes` en la configuración del modelo para datos de salida, y Pydantic serializará los bytes como base64 al generar la response JSON. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## Pydantic `bytes` para datos de entrada y salida { #pydantic-bytes-for-input-and-output-data } + +Y por supuesto, puedes usar el mismo modelo configurado para usar base64 para manejar tanto la entrada (*validate*) con `val_json_bytes` como la salida (*serialize*) con `ser_json_bytes` al recibir y enviar datos JSON. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/es/docs/advanced/stream-data.md b/docs/es/docs/advanced/stream-data.md new file mode 100644 index 0000000000..964a9ed586 --- /dev/null +++ b/docs/es/docs/advanced/stream-data.md @@ -0,0 +1,117 @@ +# Transmitir datos { #stream-data } + +Si quieres transmitir datos que se puedan estructurar como JSON, deberías [Transmitir JSON Lines](../tutorial/stream-json-lines.md). + +Pero si quieres transmitir datos binarios puros o strings, aquí tienes cómo hacerlo. + +/// info | Información + +Añadido en FastAPI 0.134.0. + +/// + +## Casos de uso { #use-cases } + +Podrías usar esto si quieres transmitir strings puros, por ejemplo directamente de la salida de un servicio de AI LLM. + +También podrías usarlo para transmitir archivos binarios grandes, donde transmites cada bloque de datos a medida que lo lees, sin tener que leerlo todo en memoria de una sola vez. + +También podrías transmitir video o audio de esta manera; incluso podría generarse mientras lo procesas y lo envías. + +## Un `StreamingResponse` con `yield` { #a-streamingresponse-with-yield } + +Si declaras un `response_class=StreamingResponse` en tu *path operation function*, puedes usar `yield` para enviar cada bloque de datos a su vez. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} + +FastAPI entregará cada bloque de datos a `StreamingResponse` tal cual, no intentará convertirlo a JSON ni nada parecido. + +### *path operation functions* no async { #non-async-path-operation-functions } + +También puedes usar funciones `def` normales (sin `async`) y usar `yield` de la misma manera. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} + +### Sin anotación { #no-annotation } + +Realmente no necesitas declarar la anotación de tipo de retorno para transmitir datos binarios. + +Como FastAPI no intentará convertir los datos a JSON con Pydantic ni serializarlos de ninguna manera, en este caso la anotación de tipos es solo para que la use tu editor y tus herramientas; FastAPI no la usará. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} + +Esto también significa que con `StreamingResponse` tienes la libertad y la responsabilidad de producir y codificar los bytes de datos exactamente como necesites enviarlos, independientemente de las anotaciones de tipos. 🤓 + +### Transmitir bytes { #stream-bytes } + +Uno de los casos de uso principales sería transmitir `bytes` en lugar de strings; por supuesto puedes hacerlo. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} + +## Un `PNGStreamingResponse` personalizado { #a-custom-pngstreamingresponse } + +En los ejemplos anteriores, se transmitieron los bytes de datos, pero la response no tenía un header `Content-Type`, así que el cliente no sabía qué tipo de datos estaba recibiendo. + +Puedes crear una subclase personalizada de `StreamingResponse` que establezca el header `Content-Type` al tipo de datos que estás transmitiendo. + +Por ejemplo, puedes crear un `PNGStreamingResponse` que establezca el header `Content-Type` a `image/png` usando el atributo `media_type`: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} + +Luego puedes usar esta nueva clase en `response_class=PNGStreamingResponse` en tu *path operation function*: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} + +### Simular un archivo { #simulate-a-file } + +En este ejemplo estamos simulando un archivo con `io.BytesIO`, que es un objeto tipo archivo que vive solo en memoria, pero nos permite usar la misma interfaz. + +Por ejemplo, podemos iterarlo para consumir su contenido, como podríamos con un archivo. + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} + +/// note | Detalles técnicos + +Las otras dos variables, `image_base64` y `binary_image`, son una imagen codificada en Base64 y luego convertida a bytes, para después pasarla a `io.BytesIO`. + +Solo para que pueda vivir en el mismo archivo para este ejemplo y puedas copiarlo y ejecutarlo tal cual. 🥚 + +/// + +Al usar un bloque `with`, nos aseguramos de que el objeto tipo archivo se cierre cuando termine la función generadora (la función con `yield`). Es decir, después de que termine de enviar la response. + +No sería tan importante en este ejemplo específico porque es un archivo falso en memoria (con `io.BytesIO`), pero con un archivo real sí sería importante asegurarse de que el archivo se cierre al terminar de trabajar con él. + +### Archivos y async { #files-and-async } + +En la mayoría de los casos, los objetos tipo archivo no son compatibles con `async` y `await` por defecto. + +Por ejemplo, no tienen un `await file.read()`, ni un `async for chunk in file`. + +Y en muchos casos leerlos sería una operación bloqueante (que podría bloquear el event loop), porque se leen desde disco o desde la red. + +/// info | Información + +El ejemplo anterior es en realidad una excepción, porque el objeto `io.BytesIO` ya está en memoria, así que leerlo no bloqueará nada. + +Pero en muchos casos leer un archivo u objeto tipo archivo sí bloquearía. + +/// + +Para evitar bloquear el event loop, puedes simplemente declarar la *path operation function* con un `def` normal en lugar de `async def`; de esa forma FastAPI la ejecutará en un worker de threadpool para evitar bloquear el loop principal. + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} + +/// tip | Consejo + +Si necesitas llamar código bloqueante desde dentro de una función async, o una función async desde dentro de una función bloqueante, podrías usar [Asyncer](https://asyncer.tiangolo.com), un paquete hermano de FastAPI. + +/// + +### `yield from` { #yield-from } + +Cuando estés iterando sobre algo, como un objeto tipo archivo, y estés haciendo `yield` para cada elemento, también podrías usar `yield from` para hacer `yield` de cada elemento directamente y saltarte el `for`. + +Esto no es particular de FastAPI, es simplemente Python, pero es un truco útil que conviene conocer. 😎 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} diff --git a/docs/es/docs/advanced/strict-content-type.md b/docs/es/docs/advanced/strict-content-type.md new file mode 100644 index 0000000000..41615edf3b --- /dev/null +++ b/docs/es/docs/advanced/strict-content-type.md @@ -0,0 +1,88 @@ +# Chequeo estricto de Content-Type { #strict-content-type-checking } + +Por defecto, **FastAPI** usa un chequeo estricto del header `Content-Type` para request bodies JSON, esto significa que las requests JSON deben incluir un header `Content-Type` válido (p. ej. `application/json`) para que el request body se parse como JSON. + +## Riesgo de CSRF { #csrf-risk } + +Este comportamiento por defecto provee protección contra una clase de ataques de **Cross-Site Request Forgery (CSRF)** en un escenario muy específico. + +Estos ataques aprovechan que los navegadores permiten que los scripts envíen requests sin hacer un preflight de CORS cuando: + +* no tienen un header `Content-Type` (p. ej. usando `fetch()` con un body `Blob`) +* y no envían credenciales de autenticación. + +Este tipo de ataque es relevante principalmente cuando: + +* la aplicación corre localmente (p. ej. en `localhost`) o en una red interna +* y la aplicación no tiene ninguna autenticación, espera que cualquier request de la misma red sea confiable. + +## Ejemplo de ataque { #example-attack } + +Imagina que construyes una forma de ejecutar un agente de IA local. + +Provee un API en + +``` +http://localhost:8000/v1/agents/multivac +``` + +También hay un frontend en + +``` +http://localhost:8000 +``` + +/// tip | Consejo + +Ten en cuenta que ambos tienen el mismo host. + +/// + +Luego, usando el frontend, puedes hacer que el agente de IA haga cosas en tu nombre. + +Como está corriendo localmente y no en Internet abierta, decides no tener ninguna autenticación configurada, confiando simplemente en el acceso a la red local. + +Entonces, uno de tus usuarios podría instalarlo y ejecutarlo localmente. + +Después podría abrir un sitio web malicioso, por ejemplo algo como + +``` +https://evilhackers.example.com +``` + +Y ese sitio malicioso envía requests usando `fetch()` con un body `Blob` al API local en + +``` +http://localhost:8000/v1/agents/multivac +``` + +Aunque el host del sitio malicioso y el de la app local sea diferente, el navegador no disparará un preflight de CORS porque: + +* Está corriendo sin ninguna autenticación, no tiene que enviar credenciales. +* El navegador cree que no está enviando JSON (por la falta del header `Content-Type`). + +Entonces el sitio malicioso podría hacer que el agente de IA local envíe mensajes agresivos al exjefe del usuario... o peor. 😅 + +## Internet abierta { #open-internet } + +Si tu app está en Internet abierta, no “confiarías en la red” ni permitirías que cualquiera envíe requests privilegiadas sin autenticación. + +Los atacantes podrían simplemente ejecutar un script para enviar requests a tu API, sin necesidad de interacción del navegador, así que probablemente ya estás asegurando cualquier endpoint privilegiado. + +En ese caso, este ataque/riesgo no aplica a ti. + +Este riesgo y ataque es relevante principalmente cuando la app corre en la red local y esa es la única protección asumida. + +## Permitir requests sin Content-Type { #allowing-requests-without-content-type } + +Si necesitas soportar clientes que no envían un header `Content-Type`, puedes desactivar el chequeo estricto configurando `strict_content_type=False`: + +{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} + +Con esta configuración, las requests sin un header `Content-Type` tendrán su body parseado como JSON, que es el mismo comportamiento de versiones anteriores de FastAPI. + +/// info | Información + +Este comportamiento y configuración se añadieron en FastAPI 0.132.0. + +/// diff --git a/docs/es/docs/editor-support.md b/docs/es/docs/editor-support.md new file mode 100644 index 0000000000..fa552db23d --- /dev/null +++ b/docs/es/docs/editor-support.md @@ -0,0 +1,23 @@ +# Soporte del editor { #editor-support } + +La [Extensión de FastAPI](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) oficial mejora tu flujo de trabajo de desarrollo con FastAPI con descubrimiento de *path operation*, navegación, además de deployment a FastAPI Cloud y streaming en vivo de logs. + +Para más detalles sobre la extensión, consulta el README en el [repositorio de GitHub](https://github.com/fastapi/fastapi-vscode). + +## Configuración e instalación { #setup-and-installation } + +La **Extensión de FastAPI** está disponible tanto para [VS Code](https://code.visualstudio.com/) como para [Cursor](https://www.cursor.com/). Se puede instalar directamente desde el panel de Extensiones en cada editor buscando "FastAPI" y seleccionando la extensión publicada por **FastAPI Labs**. La extensión también funciona en editores basados en navegador como [vscode.dev](https://vscode.dev) y [github.dev](https://github.dev). + +### Descubrimiento de la aplicación { #application-discovery } + +Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que creen un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`). + +## Funcionalidades { #features } + +- **Explorador de Path Operations** - Una vista en árbol en la barra lateral de todas las *path operations* de tu aplicación. Haz clic para saltar a cualquier definición de ruta o de router. +- **Búsqueda de rutas** - Busca por path, método o nombre con Ctrl + Shift + E (en macOS: Cmd + Shift + E). +- **Navegación con CodeLens** - Enlaces clicables encima de llamadas del cliente de tests (p. ej. `client.get('/items')`) que saltan a la *path operation* correspondiente para navegar rápidamente entre tests e implementación. +- **Desplegar en FastAPI Cloud** - Deployment con un clic de tu app a [FastAPI Cloud](https://fastapicloud.com/). +- **Streaming de logs de la aplicación** - Streaming en tiempo real de logs desde tu aplicación desplegada en FastAPI Cloud, con filtrado por nivel y búsqueda de texto. + +Si quieres familiarizarte con las funcionalidades de la extensión, puedes revisar el recorrido guiado de la extensión abriendo la Paleta de Comandos (Ctrl + Shift + P o en macOS: Cmd + Shift + P) y seleccionando "Welcome: Open walkthrough..." y luego eligiendo el recorrido "Get started with FastAPI". diff --git a/docs/es/docs/tutorial/server-sent-events.md b/docs/es/docs/tutorial/server-sent-events.md new file mode 100644 index 0000000000..0a008c0de6 --- /dev/null +++ b/docs/es/docs/tutorial/server-sent-events.md @@ -0,0 +1,120 @@ +# Server-Sent Events (SSE) { #server-sent-events-sse } + +Puedes enviar datos en streaming al cliente usando **Server-Sent Events** (SSE). + +Esto es similar a [Stream JSON Lines](stream-json-lines.md), pero usa el formato `text/event-stream`, que los navegadores soportan de forma nativa con la [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource). + +/// info | Información + +Añadido en FastAPI 0.135.0. + +/// + +## ¿Qué son los Server-Sent Events? { #what-are-server-sent-events } + +SSE es un estándar para hacer streaming de datos desde el servidor al cliente sobre HTTP. + +Cada evento es un pequeño bloque de texto con “campos” como `data`, `event`, `id` y `retry`, separados por líneas en blanco. + +Se ve así: + +``` +data: {"name": "Portal Gun", "price": 999.99} + +data: {"name": "Plumbus", "price": 32.99} + +``` + +SSE se usa comúnmente para streaming de chat de IA, notificaciones en vivo, logs y observabilidad, y otros casos donde el servidor envía actualizaciones al cliente. + +/// tip | Consejo + +Si quieres hacer streaming de datos binarios, por ejemplo video o audio, Revisa la guía avanzada: [Stream Data](../advanced/stream-data.md). + +/// + +## Streaming de SSE con FastAPI { #stream-sse-with-fastapi } + +Para hacer streaming de SSE con FastAPI, usa `yield` en tu path operation function y establece `response_class=EventSourceResponse`. + +import `EventSourceResponse` de `fastapi.sse`: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *} + +Cada ítem producido con `yield` se codifica como JSON y se envía en el campo `data:` de un evento SSE. + +Si declaras el tipo de retorno como `AsyncIterable[Item]`, FastAPI lo usará para **validar**, **documentar** y **serializar** los datos usando Pydantic. + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *} + +/// tip | Consejo + +Como Pydantic lo serializará en el lado de **Rust**, obtendrás un **rendimiento** mucho mayor que si no declaras un tipo de retorno. + +/// + +### No async *path operation functions* { #non-async-path-operation-functions } + +También puedes usar funciones `def` normales (sin `async`), y usar `yield` de la misma manera. + +FastAPI se asegurará de ejecutarlo correctamente para que no bloquee el event loop. + +Como en este caso la función no es async, el tipo de retorno correcto sería `Iterable[Item]`: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *} + +### Sin tipo de retorno { #no-return-type } + +También puedes omitir el tipo de retorno. FastAPI usará el [`jsonable_encoder`](./encoder.md) para convertir los datos y enviarlos. + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *} + +## `ServerSentEvent` { #serversentevent } + +Si necesitas configurar campos SSE como `event`, `id`, `retry` o `comment`, puedes hacer `yield` de objetos `ServerSentEvent` en lugar de datos simples. + +import `ServerSentEvent` de `fastapi.sse`: + +{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *} + +El campo `data` siempre se codifica como JSON. Puedes pasar cualquier valor que pueda serializarse como JSON, incluidos modelos de Pydantic. + +## Datos sin procesar { #raw-data } + +Si necesitas enviar datos **sin** codificarlos a JSON, usa `raw_data` en lugar de `data`. + +Esto es útil para enviar texto preformateado, líneas de log, o valores especiales de "centinela" como `[DONE]`. + +{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *} + +/// note | Nota + +`data` y `raw_data` son mutuamente excluyentes. Solo puedes establecer uno de ellos en cada `ServerSentEvent`. + +/// + +## Reanudar con `Last-Event-ID` { #resuming-with-last-event-id } + +Cuando un navegador se reconecta después de una caída de la conexión, envía el último `id` recibido en el header `Last-Event-ID`. + +Puedes leerlo como un parámetro de header y usarlo para reanudar el stream desde donde el cliente se quedó: + +{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *} + +## SSE con `POST` { #sse-with-post } + +SSE funciona con **cualquier método HTTP**, no solo con `GET`. + +Esto es útil para protocolos como [MCP](https://modelcontextprotocol.io) que hacen streaming de SSE sobre `POST`: + +{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *} + +## Detalles técnicos { #technical-details } + +FastAPI implementa algunas mejores prácticas de SSE desde el primer momento. + +- Enviar un comentario de **"keep alive" `ping`** cada 15 segundos cuando no ha habido ningún mensaje, para evitar que algunos proxies cierren la conexión, como se sugiere en la [Especificación HTML: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes). +- Configurar el header `Cache-Control: no-cache` para **evitar el almacenamiento en caché** del stream. +- Configurar un header especial `X-Accel-Buffering: no` para **evitar el buffering** en algunos proxies como Nginx. + +No tienes que hacer nada, funciona tal cual viene. 🤓 diff --git a/docs/es/docs/tutorial/stream-json-lines.md b/docs/es/docs/tutorial/stream-json-lines.md new file mode 100644 index 0000000000..e7fe18f5ea --- /dev/null +++ b/docs/es/docs/tutorial/stream-json-lines.md @@ -0,0 +1,111 @@ +# Transmitir JSON Lines { #stream-json-lines } + +Podrías tener una secuencia de datos que quieras enviar en un "**stream**", podrías hacerlo con **JSON Lines**. + +/// info | Información + +Añadido en FastAPI 0.134.0. + +/// + +## ¿Qué es un Stream? { #what-is-a-stream } + +Hacer "**Streaming**" de datos significa que tu app empezará a enviar ítems de datos al cliente sin esperar a que toda la secuencia de ítems esté lista. + +Entonces, enviará el primer ítem, el cliente lo recibirá y empezará a procesarlo, y tú podrías seguir produciendo el siguiente ítem. + +```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... +``` + +Incluso podría ser un stream infinito, donde sigues enviando datos. + +## JSON Lines { #json-lines } + +En estos casos, es común enviar "**JSON Lines**", que es un formato donde envías un objeto JSON por línea. + +Una response tendría un tipo de contenido `application/jsonl` (en lugar de `application/json`) y el response body sería algo como: + +```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."} +``` + +Es muy similar a un array JSON (equivalente de una list de Python), pero en lugar de estar envuelto en `[]` y tener `,` entre los ítems, tiene **un objeto JSON por línea**, separados por un carácter de nueva línea. + +/// info | Información + +El punto importante es que tu app podrá producir cada línea a su turno, mientras el cliente consume las líneas anteriores. + +/// + +/// note | Detalles técnicos + +Como cada objeto JSON estará separado por una nueva línea, no pueden contener caracteres de nueva línea literales en su contenido, pero sí pueden contener nuevas líneas escapadas (`\n`), lo cual es parte del estándar JSON. + +Pero normalmente no tendrás que preocuparte por eso, se hace automáticamente, sigue leyendo. 🤓 + +/// + +## Casos de uso { #use-cases } + +Podrías usar esto para hacer stream de datos desde un servicio de **AI LLM**, desde **logs** o **telemetry**, o desde otros tipos de datos que puedan estructurarse en ítems **JSON**. + +/// tip | Consejo + +Si quieres hacer stream de datos binarios, por ejemplo video o audio, Revisa la guía avanzada: [Transmitir datos](../advanced/stream-data.md). + +/// + +## Transmitir JSON Lines con FastAPI { #stream-json-lines-with-fastapi } + +Para transmitir JSON Lines con FastAPI puedes, en lugar de usar `return` en tu *path operation function*, usar `yield` para producir cada ítem a su turno. + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *} + +Si cada ítem JSON que quieres enviar de vuelta es de tipo `Item` (un modelo de Pydantic) y es una función async, puedes declarar el tipo de retorno como `AsyncIterable[Item]`: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *} + +Si declaras el tipo de retorno, FastAPI lo usará para **validar** los datos, **documentarlos** en OpenAPI, **filtrarlos** y **serializarlos** usando Pydantic. + +/// tip | Consejo + +Como Pydantic lo serializará en el lado de **Rust**, obtendrás un **rendimiento** mucho mayor que si no declaras un tipo de retorno. + +/// + +### *path operation functions* no-async { #non-async-path-operation-functions } + +También puedes usar funciones `def` regulares (sin `async`), y usar `yield` de la misma forma. + +FastAPI se asegurará de que se ejecute correctamente para que no bloquee el event loop. + +Como en este caso la función no es async, el tipo de retorno correcto sería `Iterable[Item]`: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *} + +### Sin tipo de retorno { #no-return-type } + +También puedes omitir el tipo de retorno. Entonces FastAPI usará [`jsonable_encoder`](./encoder.md) para convertir los datos a algo que se pueda serializar a JSON y luego enviarlo como JSON Lines. + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *} + +## Server-Sent Events (SSE) { #server-sent-events-sse } + +FastAPI también tiene soporte de primera clase para Server-Sent Events (SSE), que son bastante similares pero con un par de detalles extra. Puedes aprender sobre ellos en el siguiente capítulo: [Eventos enviados por el servidor (SSE)](server-sent-events.md). 🤓