Para ver exactamente qué puedes incluir en los responses, puedes revisar estas secciones en la especificación OpenAPI:
* <ahref="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object"class="external-link"target="_blank">Objeto de Responses de OpenAPI</a>, incluye el `Response Object`.
* <ahref="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object"class="external-link"target="_blank">Objeto de Response de OpenAPI</a>, puedes incluir cualquier cosa de esto directamente en cada response dentro de tu parámetro `responses`. Incluyendo `description`, `headers`, `content` (dentro de este es que declaras diferentes media types y JSON Schemas), y `links`.
* [Objeto de Responses de OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object), incluye el `Response Object`.
* [Objeto de Response de OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object), puedes incluir cualquier cosa de esto directamente en cada response dentro de tu parámetro `responses`. Incluyendo `description`, `headers`, `content` (dentro de este es que declaras diferentes media types y JSON Schemas), y `links`.
Si devuelves códigos de estado adicionales y responses directamente, no se incluirán en el esquema de OpenAPI (la documentación de la API), porque FastAPI no tiene una forma de saber de antemano qué vas a devolver.
Pero puedes documentarlo en tu código, usando: [Responses Adicionales](additional-responses.md){.internal-link target=_blank}.
Pero puedes documentarlo en tu código, usando: [Responses Adicionales](additional-responses.md).
@ -132,7 +132,7 @@ Si tienes este caso de uso específico usando SQLModel (o SQLAlchemy), podrías
De esa manera la sesión liberaría la conexión a la base de datos, para que otras requests puedan usarla.
Si tienes un caso de uso diferente que necesite salir temprano desde una dependencia con `yield`, por favor crea una <ahref="https://github.com/fastapi/fastapi/discussions/new?category=questions"class="external-link"target="_blank">Pregunta de Discusión en GitHub</a> con tu caso de uso específico y por qué te beneficiaría tener cierre temprano para dependencias con `yield`.
Si tienes un caso de uso diferente que necesite salir temprano desde una dependencia con `yield`, por favor crea una [Pregunta de Discusión en GitHub](https://github.com/fastapi/fastapi/discussions/new?category=questions) con tu caso de uso específico y por qué te beneficiaría tener cierre temprano para dependencias con `yield`.
Si hay casos de uso convincentes para el cierre temprano en dependencias con `yield`, consideraría agregar una nueva forma de optar por el cierre temprano.
@ -144,7 +144,7 @@ Esto cambió en la versión 0.110.0 para arreglar consumo de memoria no manejado
### Tareas en segundo plano y dependencias con `yield`, detalles técnicos { #background-tasks-and-dependencies-with-yield-technical-details }
Antes de FastAPI 0.106.0, elevar excepciones después de `yield` no era posible, el código de salida en dependencias con `yield` se ejecutaba después de que la response era enviada, por lo que [Manejadores de Excepciones](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} ya habrían corrido.
Antes de FastAPI 0.106.0, elevar excepciones después de `yield` no era posible, el código de salida en dependencias con `yield` se ejecutaba después de que la response era enviada, por lo que [Manejadores de Excepciones](../tutorial/handling-errors.md#install-custom-exception-handlers) ya habrían corrido.
Esto se diseñó así principalmente para permitir usar los mismos objetos devueltos con `yield` por las dependencias dentro de tareas en segundo plano, porque el código de salida se ejecutaría después de que las tareas en segundo plano terminaran.
Si quieres aprender más sobre HTTPS, revisa la guía [Acerca de HTTPS](../deployment/https.md){.internal-link target=_blank}.
Si quieres aprender más sobre HTTPS, revisa la guía [Acerca de HTTPS](../deployment/https.md).
///
@ -228,7 +228,7 @@ Pasar el `root_path` a `FastAPI` sería el equivalente a pasar la opción de lí
Ten en cuenta que el servidor (Uvicorn) no usará ese `root_path` para nada, a excepción de pasárselo a la app.
Pero si vas con tu navegador a <ahref="http://127.0.0.1:8000/app"class="external-link"target="_blank">http://127.0.0.1:8000/app</a> verás el response normal:
Pero si vas con tu navegador a [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app) verás el response normal:
```JSON
{
@ -251,9 +251,9 @@ En un caso así (sin un prefijo de path eliminado), el proxy escucharía algo co
## Probando localmente con Traefik { #testing-locally-with-traefik }
Puedes ejecutar fácilmente el experimento localmente con un prefijo de path eliminado usando <ahref="https://docs.traefik.io/"class="external-link"target="_blank">Traefik</a>.
Puedes ejecutar fácilmente el experimento localmente con un prefijo de path eliminado usando [Traefik](https://docs.traefik.io/).
<ahref="https://github.com/containous/traefik/releases"class="external-link"target="_blank">Descarga Traefik</a>, es un archivo binario único, puedes extraer el archivo comprimido y ejecutarlo directamente desde la terminal.
[Descarga Traefik](https://github.com/containous/traefik/releases), es un archivo binario único, puedes extraer el archivo comprimido y ejecutarlo directamente desde la terminal.
Ahora, si vas a la URL con el puerto para Uvicorn: <ahref="http://127.0.0.1:8000/app"class="external-link"target="_blank">http://127.0.0.1:8000/app</a>, verás el response normal:
Ahora, si vas a la URL con el puerto para Uvicorn: [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app), verás el response normal:
```JSON
{
@ -345,7 +345,7 @@ Nota que incluso aunque estés accediendo en `http://127.0.0.1:8000/app`, muestr
///
Y ahora abre la URL con el puerto para Traefik, incluyendo el prefijo de path: <ahref="http://127.0.0.1:9999/api/v1/app"class="external-link"target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
Y ahora abre la URL con el puerto para Traefik, incluyendo el prefijo de path: [http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app).
Obtenemos el mismo response:
@ -370,13 +370,13 @@ Pero aquí está la parte divertida. ✨
La forma "oficial" de acceder a la app sería a través del proxy con el prefijo de path que definimos. Así que, como esperaríamos, si intentas usar la UI de los docs servida por Uvicorn directamente, sin el prefijo de path en la URL, no funcionará, porque espera ser accedida a través del proxy.
Puedes verificarlo en <ahref="http://127.0.0.1:8000/docs"class="external-link"target="_blank">http://127.0.0.1:8000/docs</a>:
Puedes verificarlo en [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs):
@ -433,7 +433,7 @@ Observa el server auto-generado con un valor `url` de `/api/v1`, tomado del `roo
///
En la UI de los docs en <ahref="http://127.0.0.1:9999/api/v1/docs"class="external-link"target="_blank">http://127.0.0.1:9999/api/v1/docs</a> se vería como:
En la UI de los docs en [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) se vería como:
@ -461,6 +461,6 @@ y entonces no lo incluirá en el esquema de OpenAPI.
## Montando una sub-aplicación { #mounting-a-sub-application }
Si necesitas montar una sub-aplicación (como se describe en [Aplicaciones secundarias - Monturas](sub-applications.md){.internal-link target=_blank}) mientras usas un proxy con `root_path`, puedes hacerlo normalmente, como esperarías.
Si necesitas montar una sub-aplicación (como se describe en [Aplicaciones secundarias - Monturas](sub-applications.md)) mientras usas un proxy con `root_path`, puedes hacerlo normalmente, como esperarías.
FastAPI usará internamente el `root_path` de manera inteligente, así que simplemente funcionará. ✨
Por defecto, **FastAPI** devolverá los responses usando `JSONResponse`.
Por defecto, **FastAPI** devolverá responses JSON.
Puedes sobrescribirlo devolviendo un `Response` directamente como se ve en [Devolver una Response directamente](response-directly.md){.internal-link target=_blank}.
Puedes sobrescribirlo devolviendo un `Response` directamente como se ve en [Devolver una Response directamente](response-directly.md).
Pero si devuelves un `Response` directamente (o cualquier subclase, como `JSONResponse`), los datos no se convertirán automáticamente (incluso si declaras un `response_model`), y la documentación no se generará automáticamente (por ejemplo, incluyendo el "media type" específico, en el HTTP header `Content-Type` como parte del OpenAPI generado).
@ -10,43 +10,27 @@ Pero también puedes declarar el `Response` que quieres usar (por ejemplo, cualq
Los contenidos que devuelvas desde tu *path operation function* se colocarán dentro de esa `Response`.
Y si ese `Response` tiene un media type JSON (`application/json`), como es el caso con `JSONResponse` y `UJSONResponse`, los datos que devuelvas se convertirán automáticamente (y serán filtrados) con cualquier `response_model` de Pydantic que hayas declarado en el *path operation decorator*.
/// note | Nota
Si usas una clase de response sin media type, FastAPI esperará que tu response no tenga contenido, por lo que no documentará el formato del response en su OpenAPI generado.
///
## Usa `ORJSONResponse` { #use-orjsonresponse }
Por ejemplo, si estás exprimendo el rendimiento, puedes instalar y usar <ahref="https://github.com/ijl/orjson"class="external-link"target="_blank">`orjson`</a> y establecer el response como `ORJSONResponse`.
Importa la clase `Response` (sub-clase) que quieras usar y declárala en el *path operation decorator*.
Para responses grandes, devolver una `Response` directamente es mucho más rápido que devolver un diccionario.
Esto se debe a que, por defecto, FastAPI inspeccionará cada elemento dentro y se asegurará de que sea serializable como JSON, usando el mismo [Codificador Compatible con JSON](../tutorial/encoder.md){.internal-link target=_blank} explicado en el tutorial. Esto es lo que te permite devolver **objetos arbitrarios**, por ejemplo, modelos de bases de datos.
Pero si estás seguro de que el contenido que estás devolviendo es **serializable con JSON**, puedes pasarlo directamente a la clase de response y evitar la sobrecarga extra que FastAPI tendría al pasar tu contenido de retorno a través de `jsonable_encoder` antes de pasarlo a la clase de response.
El parámetro `response_class` también se utilizará para definir el "media type" del response.
Si declaras un [Response Model](../tutorial/response-model.md) FastAPI lo usará para serializar los datos a JSON, usando Pydantic.
En este caso, el HTTP header `Content-Type` se establecerá en `application/json`.
Si no declaras un response model, FastAPI usará el `jsonable_encoder` explicado en [Codificador Compatible con JSON](../tutorial/encoder.md) y lo pondrá en un `JSONResponse`.
Y se documentará así en OpenAPI.
Si declaras un `response_class` con un media type JSON (`application/json`), como es el caso con `JSONResponse`, los datos que devuelvas se convertirán automáticamente (y serán filtrados) con cualquier `response_model` de Pydantic que hayas declarado en el *path operation decorator*. Pero los datos no se serializarán a bytes JSON con Pydantic, en su lugar se convertirán con el `jsonable_encoder` y luego se pasarán a la clase `JSONResponse`, que los serializará a bytes usando la librería JSON estándar de Python.
///
### Rendimiento JSON { #json-performance }
/// tip | Consejo
En resumen, si quieres el máximo rendimiento, usa un [Response Model](../tutorial/response-model.md) y no declares un `response_class` en el *path operation decorator*.
El `ORJSONResponse` solo está disponible en FastAPI, no en Starlette.
### Devuelve una `Response` { #return-a-response }
Como se ve en [Devolver una Response directamente](response-directly.md){.internal-link target=_blank}, también puedes sobrescribir el response directamente en tu *path operation*, devolviéndolo.
Como se ve en [Devolver una Response directamente](response-directly.md), también puedes sobrescribir el response directamente en tu *path operation*, devolviéndolo.
El mismo ejemplo de arriba, devolviendo una `HTMLResponse`, podría verse así:
@ -154,37 +138,11 @@ Toma algunos datos y devuelve un response codificado como `application/json`.
Este es el response usado por defecto en **FastAPI**, como leíste arriba.
### `ORJSONResponse` { #orjsonresponse }
Un response JSON rápido alternativo usando <ahref="https://github.com/ijl/orjson"class="external-link"target="_blank">`orjson`</a>, como leíste arriba.
/// info | Información
Esto requiere instalar `orjson`, por ejemplo, con `pip install orjson`.
///
### `UJSONResponse` { #ujsonresponse }
Un response JSON alternativo usando <ahref="https://github.com/ultrajson/ultrajson"class="external-link"target="_blank">`ujson`</a>.
/// info | Información
Esto requiere instalar `ujson`, por ejemplo, con `pip install ujson`.
///
/// warning | Advertencia
`ujson` es menos cuidadoso que la implementación integrada de Python en cómo maneja algunos casos extremos.
Pero si declaras un response model o un tipo de retorno, eso se usará directamente para serializar los datos a JSON, y se devolverá directamente un response con el media type correcto para JSON, sin usar la clase `JSONResponse`.
Es posible que `ORJSONResponse` sea una alternativa más rápida.
Esta es la forma ideal de obtener el mejor rendimiento.
///
@ -200,6 +158,7 @@ Puedes devolver un `RedirectResponse` directamente:
#### Usando `StreamingResponse` con objetos similares a archivos { #using-streamingresponse-with-file-like-objects }
Toma un generador `async` o un generador/iterador normal (una función con `yield`) y transmite el cuerpo del response.
Si tienes un <ahref="https://docs.python.org/3/glossary.html#term-file-like-object"class="external-link"target="_blank">objeto similar a un archivo</a> (por ejemplo, el objeto devuelto por `open()`), puedes crear una función generadora para iterar sobre ese objeto similar a un archivo.
Una tarea `async` solo puede cancelarse cuando llega a un `await`. Si no hay `await`, el generador (función con `yield`) no se puede cancelar correctamente y puede seguir ejecutándose incluso después de solicitar la cancelación.
1. Esta es la función generadora. Es una "función generadora" porque contiene declaraciones `yield` dentro.
2. Al usar un bloque `with`, nos aseguramos de que el objeto similar a un archivo se cierre después de que la función generadora termine. Así, después de que termina de enviar el response.
3. Este `yield from` le dice a la función que itere sobre esa cosa llamada `file_like`. Y luego, para cada parte iterada, yield esa parte como proveniente de esta función generadora (`iterfile`).
Como este pequeño ejemplo no necesita ninguna sentencia `await`, añadimos un `await anyio.sleep(0)` para darle al loop de eventos la oportunidad de manejar la cancelación.
Entonces, es una función generadora que transfiere el trabajo de "generar" a algo más internamente.
Esto sería aún más importante con streams grandes o infinitos.
Al hacerlo de esta manera, podemos ponerlo en un bloque `with`, y de esa manera, asegurarnos de que el objeto similar a un archivo se cierre después de finalizar.
///
/// tip | Consejo
Nota que aquí como estamos usando `open()` estándar que no admite `async` y `await`, declaramos el path operation con `def` normal.
En lugar de devolver un `StreamingResponse` directamente, probablemente deberías seguir el estilo en [Stream Data](./stream-data.md), es mucho más conveniente y maneja la cancelación por detrás de escena por ti.
Si estás transmitiendo JSON Lines, sigue el tutorial [Stream JSON Lines](../tutorial/stream-json-lines.md).
///
@ -267,7 +220,7 @@ En este caso, puedes devolver la path del archivo directamente desde tu *path op
Puedes crear tu propia clase de response personalizada, heredando de `Response` y usándola.
Por ejemplo, digamos que quieres usar <ahref="https://github.com/ijl/orjson"class="external-link"target="_blank">`orjson`</a>, pero con algunas configuraciones personalizadas no utilizadas en la clase `ORJSONResponse` incluida.
Por ejemplo, digamos que quieres usar [`orjson`](https://github.com/ijl/orjson) con algunas configuraciones.
Digamos que quieres que devuelva JSON con sangría y formato, por lo que quieres usar la opción de orjson `orjson.OPT_INDENT_2`.
@ -291,13 +244,21 @@ Ahora en lugar de devolver:
Por supuesto, probablemente encontrarás formas mucho mejores de aprovechar esto que formatear JSON. 😉
### `orjson` o Response Model { #orjson-or-response-model }
Si lo que buscas es rendimiento, probablemente te convenga más usar un [Response Model](../tutorial/response-model.md) que un response con `orjson`.
Con un response model, FastAPI usará Pydantic para serializar los datos a JSON, sin pasos intermedios, como convertirlos con `jsonable_encoder`, que ocurriría en cualquier otro caso.
Y por debajo, Pydantic usa los mismos mecanismos en Rust que `orjson` para serializar a JSON, así que ya obtendrás el mejor rendimiento con un response model.
## Clase de response por defecto { #default-response-class }
Al crear una instance de la clase **FastAPI** o un `APIRouter`, puedes especificar qué clase de response usar por defecto.
El parámetro que define esto es `default_response_class`.
En el ejemplo a continuación, **FastAPI** usará `ORJSONResponse` por defecto, en todas las *path operations*, en lugar de `JSONResponse`.
En el ejemplo a continuación, **FastAPI** usará `HTMLResponse` por defecto, en todas las *path operations*, en lugar de JSON.
También puedes declarar el media type y muchos otros detalles en OpenAPI usando `responses`: [Responses Adicionales en OpenAPI](additional-responses.md){.internal-link target=_blank}.
También puedes declarar el media type y muchos otros detalles en OpenAPI usando `responses`: [Responses Adicionales en OpenAPI](additional-responses.md).
FastAPI está construido sobre **Pydantic**, y te he estado mostrando cómo usar modelos de Pydantic para declarar requests y responses.
Pero FastAPI también soporta el uso de <ahref="https://docs.python.org/3/library/dataclasses.html"class="external-link"target="_blank">`dataclasses`</a> de la misma manera:
Pero FastAPI también soporta el uso de [`dataclasses`](https://docs.python.org/3/library/dataclasses.html) de la misma manera:
Esto sigue siendo soportado gracias a **Pydantic**, ya que tiene <ahref="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel"class="external-link"target="_blank">soporte interno para `dataclasses`</a>.
Esto sigue siendo soportado gracias a **Pydantic**, ya que tiene [soporte interno para `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel).
Así que, incluso con el código anterior que no usa Pydantic explícitamente, FastAPI está usando Pydantic para convertir esos dataclasses estándar en su propia versión de dataclasses de Pydantic.
@ -74,7 +74,7 @@ En ese caso, simplemente puedes intercambiar los `dataclasses` estándar con `py
Como siempre, en FastAPI puedes combinar `def` y `async def` según sea necesario.
Si necesitas un repaso sobre cuándo usar cuál, revisa la sección _"¿Con prisa?"_ en la documentación sobre [`async` y `await`](../async.md#in-a-hurry){.internal-link target=_blank}.
Si necesitas un repaso sobre cuándo usar cuál, revisa la sección _"¿Con prisa?"_ en la documentación sobre [`async` y `await`](../async.md#in-a-hurry).
9. Esta *path operation function* no está devolviendo dataclasses (aunque podría), sino una lista de diccionarios con datos internos.
@ -88,7 +88,7 @@ Revisa las anotaciones en el código arriba para ver más detalles específicos.
También puedes combinar `dataclasses` con otros modelos de Pydantic, heredar de ellos, incluirlos en tus propios modelos, etc.
Para saber más, revisa la <ahref="https://docs.pydantic.dev/latest/concepts/dataclasses/"class="external-link"target="_blank">documentación de Pydantic sobre dataclasses</a>.
Para saber más, revisa la [documentación de Pydantic sobre dataclasses](https://docs.pydantic.dev/latest/concepts/dataclasses/).
@ -8,11 +8,11 @@ En esta guía, aprenderás a generar un **SDK de TypeScript** para tu backend co
## Generadores de SDKs de código abierto { #open-source-sdk-generators }
Una opción versátil es el <ahref="https://openapi-generator.tech/"class="external-link"target="_blank">OpenAPI Generator</a>, que soporta **muchos lenguajes de programación** y puede generar SDKs a partir de tu especificación OpenAPI.
Una opción versátil es el [OpenAPI Generator](https://openapi-generator.tech/), que soporta **muchos lenguajes de programación** y puede generar SDKs a partir de tu especificación OpenAPI.
Para **clientes de TypeScript**, <ahref="https://heyapi.dev/"class="external-link"target="_blank">Hey API</a> es una solución diseñada específicamente, que ofrece una experiencia optimizada para el ecosistema de TypeScript.
Para **clientes de TypeScript**, [Hey API](https://heyapi.dev/) es una solución diseñada específicamente, que ofrece una experiencia optimizada para el ecosistema de TypeScript.
Puedes descubrir más generadores de SDK en <ahref="https://openapi.tools/#sdk"class="external-link"target="_blank">OpenAPI.Tools</a>.
Puedes descubrir más generadores de SDK en [OpenAPI.Tools](https://openapi.tools/#sdk).
/// tip | Consejo
@ -24,15 +24,15 @@ FastAPI genera automáticamente especificaciones **OpenAPI 3.1**, así que cualq
Esta sección destaca soluciones **respaldadas por empresas** y **venture-backed** de compañías que sponsorean FastAPI. Estos productos ofrecen **funcionalidades adicionales** e **integraciones** además de SDKs generados de alta calidad.
Al ✨ [**sponsorear FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, estas compañías ayudan a asegurar que el framework y su **ecosistema** se mantengan saludables y **sustentables**.
Al ✨ [**sponsorear FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, estas compañías ayudan a asegurar que el framework y su **ecosistema** se mantengan saludables y **sustentables**.
Su sponsorship también demuestra un fuerte compromiso con la **comunidad** de FastAPI (tú), mostrando que no solo les importa ofrecer un **gran servicio**, sino también apoyar un **framework robusto y próspero**, FastAPI. 🙇
Algunas de estas soluciones también pueden ser open source u ofrecer niveles gratuitos, así que puedes probarlas sin un compromiso financiero. Hay otros generadores de SDK comerciales disponibles y se pueden encontrar en línea. 🤓
Esto generará un SDK de TypeScript en `./src/client`.
Puedes aprender cómo <ahref="https://heyapi.dev/openapi-ts/get-started"class="external-link"target="_blank">instalar `@hey-api/openapi-ts`</a> y leer sobre el <ahref="https://heyapi.dev/openapi-ts/output"class="external-link"target="_blank">output generado</a> en su sitio web.
Puedes aprender cómo [instalar `@hey-api/openapi-ts`](https://heyapi.dev/openapi-ts/get-started) y leer sobre el [output generado](https://heyapi.dev/openapi-ts/output) en su sitio web.
El [Tutorial - Guía del usuario](../tutorial/index.md){.internal-link target=_blank} principal debería ser suficiente para darte un recorrido por todas las funcionalidades principales de **FastAPI**.
El [Tutorial - Guía del usuario](../tutorial/index.md) principal debería ser suficiente para darte un recorrido por todas las funcionalidades principales de **FastAPI**.
En las siguientes secciones verás otras opciones, configuraciones y funcionalidades adicionales.
@ -16,6 +16,6 @@ Y es posible que para tu caso de uso, la solución esté en una de ellas.
## Lee primero el Tutorial { #read-the-tutorial-first }
Aún podrías usar la mayoría de las funcionalidades en **FastAPI** con el conocimiento del [Tutorial - Guía del usuario](../tutorial/index.md){.internal-link target=_blank} principal.
Aún podrías usar la mayoría de las funcionalidades en **FastAPI** con el conocimiento del [Tutorial - Guía del usuario](../tutorial/index.md) principal.
Y las siguientes secciones asumen que ya lo leíste y que conoces esas ideas principales.
@ -35,7 +35,7 @@ Esta parte es bastante normal, probablemente ya estés familiarizado con la mayo
/// tip | Consejo
El parámetro de query `callback_url` utiliza un tipo <ahref="https://docs.pydantic.dev/latest/api/networks/"class="external-link"target="_blank">Url</a> de Pydantic.
El parámetro de query `callback_url` utiliza un tipo [Url](https://docs.pydantic.dev/latest/api/networks/) de Pydantic.
///
@ -66,7 +66,7 @@ Este ejemplo no implementa el callback en sí (eso podría ser solo una línea d
El callback real es solo un request HTTP.
Cuando implementes el callback tú mismo, podrías usar algo como <ahref="https://www.python-httpx.org"class="external-link"target="_blank">HTTPX</a> o <ahref="https://requests.readthedocs.io/"class="external-link"target="_blank">Requests</a>.
Cuando implementes el callback tú mismo, podrías usar algo como [HTTPX](https://www.python-httpx.org) o [Requests](https://requests.readthedocs.io/).
///
@ -106,11 +106,11 @@ Debería verse como una *path operation* normal de FastAPI:
Hay 2 diferencias principales respecto a una *path operation* normal:
* No necesita tener ningún código real, porque tu aplicación nunca llamará a este código. Solo se usa para documentar la *API externa*. Así que, la función podría simplemente tener `pass`.
* El *path* puede contener una <ahref="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression"class="external-link"target="_blank">expresión OpenAPI 3</a> (ver más abajo) donde puede usar variables con parámetros y partes del request original enviado a *tu API*.
* El *path* puede contener una [expresión OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (ver más abajo) donde puede usar variables con parámetros y partes del request original enviado a *tu API*.
### La expresión del path del callback { #the-callback-path-expression }
El *path* del callback puede tener una <ahref="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression"class="external-link"target="_blank">expresión OpenAPI 3</a> que puede contener partes del request original enviado a *tu API*.
El *path* del callback puede tener una [expresión OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) que puede contener partes del request original enviado a *tu API*.
En este caso, es el `str`:
@ -179,7 +179,7 @@ Observa que no estás pasando el router en sí (`invoices_callback_router`) a `c
### Revisa la documentación { #check-the-docs }
Ahora puedes iniciar tu aplicación e ir a <ahref="http://127.0.0.1:8000/docs"class="external-link"target="_blank">http://127.0.0.1:8000/docs</a>.
Ahora puedes iniciar tu aplicación e ir a [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs).
Verás tu documentación incluyendo una sección de "Callbacks" para tu *path operation* que muestra cómo debería verse la *API externa*:
# Response - Cambiar Código de Estado { #response-change-status-code }
Probablemente leíste antes que puedes establecer un [Código de Estado de Response](../tutorial/response-status-code.md){.internal-link target=_blank} por defecto.
Probablemente leíste antes que puedes establecer un [Código de Estado de Response](../tutorial/response-status-code.md) por defecto.
Pero en algunos casos necesitas devolver un código de estado diferente al predeterminado.
@ -20,7 +20,7 @@ También puedes declarar el parámetro `Response` en las dependencias, y estable
También puedes crear cookies al devolver una `Response` directamente en tu código.
Para hacer eso, puedes crear un response como se describe en [Devolver un Response Directamente](response-directly.md){.internal-link target=_blank}.
Para hacer eso, puedes crear un response como se describe en [Devolver un Response Directamente](response-directly.md).
Luego establece Cookies en ella, y luego devuélvela:
@ -48,4 +48,4 @@ Y como el `Response` se puede usar frecuentemente para establecer headers y cook
///
Para ver todos los parámetros y opciones disponibles, revisa la <ahref="https://www.starlette.dev/responses/#set-cookie"class="external-link"target="_blank">documentación en Starlette</a>.
Para ver todos los parámetros y opciones disponibles, revisa la [documentación en Starlette](https://www.starlette.dev/responses/#set-cookie).
Cuando creas una *path operation* en **FastAPI**, normalmente puedes devolver cualquier dato desde ella: un `dict`, una `list`, un modelo de Pydantic, un modelo de base de datos, etc.
Por defecto, **FastAPI** convertiría automáticamente ese valor de retorno a JSON usando el `jsonable_encoder` explicado en [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
Si declaras un [Response Model](../tutorial/response-model.md) FastAPI lo usará para serializar los datos a JSON, usando Pydantic.
Luego, detrás de escena, pondría esos datos compatibles con JSON (por ejemplo, un `dict`) dentro de un `JSONResponse` que se usaría para enviar el response al cliente.
Si no declaras un response model, FastAPI usará el `jsonable_encoder` explicado en [JSON Compatible Encoder](../tutorial/encoder.md) y lo pondrá en un `JSONResponse`.
Pero puedes devolver un `JSONResponse` directamente desde tus *path operations*.
También podrías crear un `JSONResponse` directamente y devolverlo.
Esto podría ser útil, por ejemplo, para devolver headers o cookies personalizados.
/// tip | Consejo
Normalmente tendrás mucho mejor rendimiento usando un [Response Model](../tutorial/response-model.md) que devolviendo un `JSONResponse` directamente, ya que de esa forma serializa los datos usando Pydantic, en Rust.
///
## Devolver una `Response` { #return-a-response }
De hecho, puedes devolver cualquier `Response` o cualquier subclase de ella.
/// tip | Consejo
/// info | Información
`JSONResponse` en sí misma es una subclase de `Response`.
@ -26,6 +30,8 @@ No hará ninguna conversión de datos con los modelos de Pydantic, no convertir
Esto te da mucha flexibilidad. Puedes devolver cualquier tipo de datos, sobrescribir cualquier declaración o validación de datos, etc.
También te da mucha responsabilidad. Tienes que asegurarte de que los datos que devuelves sean correctos, en el formato correcto, que se puedan serializar, etc.
## Usar el `jsonable_encoder` en una `Response` { #using-the-jsonable-encoder-in-a-response }
Como **FastAPI** no realiza cambios en una `Response` que devuelves, tienes que asegurarte de que sus contenidos estén listos para ello.
@ -50,16 +56,28 @@ El ejemplo anterior muestra todas las partes que necesitas, pero aún no es muy
Ahora, veamos cómo podrías usar eso para devolver un response personalizado.
Digamos que quieres devolver un response en <ahref="https://en.wikipedia.org/wiki/XML"class="external-link"target="_blank">XML</a>.
Digamos que quieres devolver un response en [XML](https://en.wikipedia.org/wiki/XML).
Podrías poner tu contenido XML en un string, poner eso en un `Response`, y devolverlo:
## Cómo funciona un Response Model { #how-a-response-model-works }
Cuando declaras un [Response Model - Return Type](../tutorial/response-model.md) en una *path operation*, **FastAPI** lo usará para serializar los datos a JSON, usando Pydantic.
Como eso sucederá del lado de Rust, el rendimiento será mucho mejor que si se hiciera con Python normal y la clase `JSONResponse`.
Al usar un `response_model` o tipo de retorno, FastAPI no usará el `jsonable_encoder` para convertir los datos (lo cual sería más lento) ni la clase `JSONResponse`.
En su lugar, toma los bytes JSON generados con Pydantic usando el response model (o tipo de retorno) y devuelve una `Response` con el media type correcto para JSON directamente (`application/json`).
## Notas { #notes }
Cuando devuelves una `Response` directamente, sus datos no son validados, convertidos (serializados), ni documentados automáticamente.
Pero aún puedes documentarlo como se describe en [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
Pero aún puedes documentarlo como se describe en [Additional Responses in OpenAPI](additional-responses.md).
Puedes ver en secciones posteriores cómo usar/declarar estas `Response`s personalizadas mientras todavía tienes conversión automática de datos, documentación, etc.
@ -20,7 +20,7 @@ También puedes declarar el parámetro `Response` en dependencias y establecer h
También puedes agregar headers cuando devuelves un `Response` directamente.
Crea un response como se describe en [Retorna un Response Directamente](response-directly.md){.internal-link target=_blank} y pasa los headers como un parámetro adicional:
Crea un response como se describe en [Retorna un Response Directamente](response-directly.md) y pasa los headers como un parámetro adicional:
@ -36,6 +36,6 @@ Y como el `Response` se puede usar frecuentemente para establecer headers y cook
## Headers Personalizados { #custom-headers }
Ten en cuenta que los headers propietarios personalizados se pueden agregar <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers"class="external-link"target="_blank">usando el prefijo `X-`</a>.
Ten en cuenta que los headers propietarios personalizados se pueden agregar [usando el prefijo `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers).
Pero si tienes headers personalizados que quieres que un cliente en un navegador pueda ver, necesitas agregarlos a tus configuraciones de CORS (leer más en [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando el parámetro `expose_headers` documentado en <ahref="https://www.starlette.dev/middleware/#corsmiddleware"class="external-link"target="_blank">la documentación CORS de Starlette</a>.
Pero si tienes headers personalizados que quieres que un cliente en un navegador pueda ver, necesitas agregarlos a tus configuraciones de CORS (leer más en [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), usando el parámetro `expose_headers` documentado en [la documentación CORS de Starlette](https://www.starlette.dev/middleware/#corsmiddleware).
@ -32,7 +32,7 @@ Aquí hay un ejemplo más completo.
Usa una dependencia para comprobar si el nombre de usuario y la contraseña son correctos.
Para esto, usa el módulo estándar de Python <ahref="https://docs.python.org/3/library/secrets.html"class="external-link"target="_blank">`secrets`</a> para verificar el nombre de usuario y la contraseña.
Para esto, usa el módulo estándar de Python [`secrets`](https://docs.python.org/3/library/secrets.html) para verificar el nombre de usuario y la contraseña.
`secrets.compare_digest()` necesita tomar `bytes` o un `str` que solo contenga caracteres ASCII (los carácteres en inglés), esto significa que no funcionaría con caracteres como `á`, como en `Sebastián`.
Hay algunas funcionalidades extra para manejar la seguridad aparte de las cubiertas en el [Tutorial - Guía del Usuario: Seguridad](../../tutorial/security/index.md){.internal-link target=_blank}.
Hay algunas funcionalidades extra para manejar la seguridad aparte de las cubiertas en el [Tutorial - Guía del Usuario: Seguridad](../../tutorial/security/index.md).
/// tip | Consejo
Las siguientes secciones **no son necesariamente "avanzadas"**.
Las siguientes secciones no son necesariamente "avanzadas".
Y es posible que para tu caso de uso, la solución esté en una de ellas.
@ -14,6 +14,6 @@ Y es posible que para tu caso de uso, la solución esté en una de ellas.
## Lee primero el Tutorial { #read-the-tutorial-first }
Las siguientes secciones asumen que ya leíste el [Tutorial - Guía del Usuario: Seguridad](../../tutorial/security/index.md){.internal-link target=_blank} principal.
Las siguientes secciones asumen que ya leíste el [Tutorial - Guía del Usuario: Seguridad](../../tutorial/security/index.md) principal.
Todas están basadas en los mismos conceptos, pero permiten algunas funcionalidades adicionales.
Primero, echemos un vistazo rápido a las partes que cambian desde los ejemplos en el **Tutorial - User Guide** principal para [OAuth2 con Password (y hashing), Bearer con tokens JWT](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Ahora usando scopes de OAuth2:
Primero, echemos un vistazo rápido a las partes que cambian desde los ejemplos en el **Tutorial - User Guide** principal para [OAuth2 con Password (y hashing), Bearer con tokens JWT](../../tutorial/security/oauth2-jwt.md). Ahora usando scopes de OAuth2:
@ -271,4 +271,4 @@ Pero al final, están implementando el mismo estándar OAuth2.
## `Security` en `dependencies` del decorador { #security-in-decorator-dependencies }
De la misma manera que puedes definir una `list` de `Depends` en el parámetro `dependencies` del decorador (como se explica en [Dependencias en decoradores de path operation](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), también podrías usar `Security` con `scopes` allí.
De la misma manera que puedes definir una `list` de `Depends` en el parámetro `dependencies` del decorador (como se explica en [Dependencias en decoradores de path operation](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md)), también podrías usar `Security` con `scopes` allí.
Y luego, abre la documentación para la sub-aplicación, en <ahref="http://127.0.0.1:8000/subapi/docs"class="external-link"target="_blank">http://127.0.0.1:8000/subapi/docs</a>.
Y luego, abre la documentación para la sub-aplicación, en [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs).
Verás la documentación automática de la API para la sub-aplicación, incluyendo solo sus propias _path operations_, todas bajo el prefijo correcto del sub-path `/subapi`:
@ -64,4 +64,4 @@ De esa manera, la sub-aplicación sabrá usar ese prefijo de path para la interf
Y la sub-aplicación también podría tener sus propias sub-aplicaciones montadas y todo funcionaría correctamente, porque FastAPI maneja todos estos `root_path`s automáticamente.
Aprenderás más sobre el `root_path` y cómo usarlo explícitamente en la sección sobre [Detrás de un Proxy](behind-a-proxy.md){.internal-link target=_blank}.
Aprenderás más sobre el `root_path` y cómo usarlo explícitamente en la sección sobre [Detrás de un Proxy](behind-a-proxy.md).
@ -15,7 +15,7 @@ Pero hay situaciones donde podrías necesitar acceder al objeto `Request` direct
## Detalles sobre el objeto `Request` { #details-about-the-request-object }
Como **FastAPI** es en realidad **Starlette** por debajo, con una capa de varias herramientas encima, puedes usar el objeto <ahref="https://www.starlette.dev/requests/"class="external-link"target="_blank">`Request`</a> de Starlette directamente cuando lo necesites.
Como **FastAPI** es en realidad **Starlette** por debajo, con una capa de varias herramientas encima, puedes usar el objeto de Starlette [`Request`](https://www.starlette.dev/requests/) directamente cuando lo necesites.
También significa que si obtienes datos del objeto `Request` directamente (por ejemplo, leyendo el cuerpo) no serán validados, convertidos o documentados (con OpenAPI, para la interfaz automática de usuario de la API) por FastAPI.
@ -45,7 +45,7 @@ De la misma manera, puedes declarar cualquier otro parámetro como normalmente,
## Documentación de `Request` { #request-documentation }
Puedes leer más detalles sobre el <ahref="https://www.starlette.dev/requests/"class="external-link"target="_blank">objeto `Request` en el sitio de documentación oficial de Starlette</a>.
Puedes leer más detalles sobre el [objeto `Request` en el sitio de documentación oficial de Starlette](https://www.starlette.dev/requests/).
@ -6,7 +6,7 @@ En la mayoría de los casos, los principales proveedores de nube tienen guías p
## FastAPI Cloud { #fastapi-cloud }
**<ahref="https://fastapicloud.com"class="external-link"target="_blank">FastAPI Cloud</a>** está construido por el mismo autor y equipo detrás de **FastAPI**.
**[FastAPI Cloud](https://fastapicloud.com)** está construido por el mismo autor y equipo detrás de **FastAPI**.
Simplifica el proceso de **construir**, **desplegar** y **acceder** a una API con un esfuerzo mínimo.
@ -16,9 +16,9 @@ FastAPI Cloud es el sponsor principal y proveedor de financiamiento de los proye
## Proveedores de Nube - Sponsors { #cloud-providers-sponsors }
Otros proveedores de nube ✨ [**son sponsors de FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ también. 🙇
Otros proveedores de nube ✨ [**son sponsors de FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ también. 🙇
También podrías considerarlos para seguir sus guías y probar sus servicios:
@ -25,7 +25,7 @@ Pero por ahora, revisemos estas importantes **ideas conceptuales**. Estos concep
## Seguridad - HTTPS { #security-https }
En el [capítulo anterior sobre HTTPS](https.md){.internal-link target=_blank} aprendimos sobre cómo HTTPS proporciona cifrado para tu API.
En el [capítulo anterior sobre HTTPS](https.md) aprendimos sobre cómo HTTPS proporciona cifrado para tu API.
También vimos que HTTPS es normalmente proporcionado por un componente **externo** a tu servidor de aplicaciones, un **Proxy de Terminación TLS**.
@ -190,7 +190,7 @@ Cuando ejecutas **múltiples procesos** del mismo programa de API, comúnmente s
### Worker Processes y Puertos { #worker-processes-and-ports }
Recuerda de la documentación [Sobre HTTPS](https.md){.internal-link target=_blank} que solo un proceso puede estar escuchando en una combinación de puerto y dirección IP en un servidor.
Recuerda de la documentación [Sobre HTTPS](https.md) que solo un proceso puede estar escuchando en una combinación de puerto y dirección IP en un servidor.
Esto sigue siendo cierto.
@ -243,7 +243,7 @@ Aquí hay algunas combinaciones y estrategias posibles:
No te preocupes si algunos de estos elementos sobre **contenedores**, Docker, o Kubernetes no tienen mucho sentido todavía.
Te contaré más sobre imágenes de contenedores, Docker, Kubernetes, etc. en un capítulo futuro: [FastAPI en Contenedores - Docker](docker.md){.internal-link target=_blank}.
Te contaré más sobre imágenes de contenedores, Docker, Kubernetes, etc. en un capítulo futuro: [FastAPI en Contenedores - Docker](docker.md).
///
@ -281,7 +281,7 @@ Aquí hay algunas ideas posibles:
/// tip | Consejo
Te daré más ejemplos concretos para hacer esto con contenedores en un capítulo futuro: [FastAPI en Contenedores - Docker](docker.md){.internal-link target=_blank}.
Te daré más ejemplos concretos para hacer esto con contenedores en un capítulo futuro: [FastAPI en Contenedores - Docker](docker.md).
# FastAPI en Contenedores - Docker { #fastapi-in-containers-docker }
Al desplegar aplicaciones de FastAPI, un enfoque común es construir una **imagen de contenedor de Linux**. Normalmente se realiza usando <ahref="https://www.docker.com/"class="external-link"target="_blank">**Docker**</a>. Luego puedes desplegar esa imagen de contenedor de varias formas.
Al desplegar aplicaciones de FastAPI, un enfoque común es construir una **imagen de contenedor de Linux**. Normalmente se realiza usando [**Docker**](https://www.docker.com/). Luego puedes desplegar esa imagen de contenedor de varias formas.
Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **replicabilidad**, **simplicidad**, y otras.
@ -60,16 +60,16 @@ Y el **contenedor** en sí (en contraste con la **imagen de contenedor**) es la
Docker ha sido una de las herramientas principales para crear y gestionar **imágenes de contenedor** y **contenedores**.
Y hay un <ahref="https://hub.docker.com/"class="external-link"target="_blank">Docker Hub</a> público con **imágenes de contenedores oficiales** pre-hechas para muchas herramientas, entornos, bases de datos y aplicaciones.
Y hay un [Docker Hub](https://hub.docker.com/) público con **imágenes de contenedores oficiales** pre-hechas para muchas herramientas, entornos, bases de datos y aplicaciones.
Por ejemplo, hay una <ahref="https://hub.docker.com/_/python"class="external-link"target="_blank">Imagen de Python</a> oficial.
Por ejemplo, hay una [Imagen de Python](https://hub.docker.com/_/python) oficial.
Y hay muchas otras imágenes para diferentes cosas como bases de datos, por ejemplo para:
* <ahref="https://hub.docker.com/_/redis"class="external-link"target="_blank">Redis</a>, etc.
* [PostgreSQL](https://hub.docker.com/_/postgres)
* [MySQL](https://hub.docker.com/_/mysql)
* [MongoDB](https://hub.docker.com/_/mongo)
* [Redis](https://hub.docker.com/_/redis), etc.
Usando una imagen de contenedor pre-hecha es muy fácil **combinar** y utilizar diferentes herramientas. Por ejemplo, para probar una nueva base de datos. En la mayoría de los casos, puedes usar las **imágenes oficiales**, y simplemente configurarlas con variables de entorno.
@ -111,7 +111,7 @@ Dependería principalmente de la herramienta que uses para **instalar** esos req
La forma más común de hacerlo es tener un archivo `requirements.txt` con los nombres de los paquetes y sus versiones, uno por línea.
Por supuesto, usarías las mismas ideas que leíste en [Acerca de las versiones de FastAPI](versions.md){.internal-link target=_blank} para establecer los rangos de versiones.
Por supuesto, usarías las mismas ideas que leíste en [Acerca de las versiones de FastAPI](versions.md) para establecer los rangos de versiones.
Por ejemplo, tu `requirements.txt` podría verse así:
@ -238,7 +238,7 @@ Asegúrate de **siempre** usar la **forma exec** de la instrucción `CMD`, como
#### Usar `CMD` - Forma Exec { #use-cmd-exec-form }
La instrucción Docker <ahref="https://docs.docker.com/reference/dockerfile/#cmd"class="external-link"target="_blank">`CMD`</a> se puede escribir usando dos formas:
La instrucción Docker [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) se puede escribir usando dos formas:
Asegúrate de siempre usar la **forma exec** para garantizar que FastAPI pueda cerrarse de manera adecuada y que [los eventos de lifespan](../advanced/events.md){.internal-link target=_blank} sean disparados.
Asegúrate de siempre usar la **forma exec** para garantizar que FastAPI pueda cerrarse de manera adecuada y que [los eventos de lifespan](../advanced/events.md) sean disparados.
Puedes leer más sobre esto en las <ahref="https://docs.docker.com/reference/dockerfile/#shell-and-exec-form"class="external-link"target="_blank">documentación de Docker para formas de shell y exec</a>.
Puedes leer más sobre esto en la [documentación de Docker para formas de shell y exec](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form).
Esto puede ser bastante notorio al usar `docker compose`. Consulta esta sección de preguntas frecuentes de Docker Compose para más detalles técnicos: <ahref="https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop"class="external-link"target="_blank">¿Por qué mis servicios tardan 10 segundos en recrearse o detenerse?</a>.
Esto puede ser bastante notorio al usar `docker compose`. Consulta esta sección de preguntas frecuentes de Docker Compose para más detalles técnicos: [¿Por qué mis servicios tardan 10 segundos en recrearse o detenerse?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop).
#### Estructura de Directorios { #directory-structure }
Deberías poder revisarlo en la URL de tu contenedor de Docker, por ejemplo: <ahref="http://192.168.99.100/items/5?q=somequery"class="external-link"target="_blank">http://192.168.99.100/items/5?q=somequery</a> o <ahref="http://127.0.0.1/items/5?q=somequery"class="external-link"target="_blank">http://127.0.0.1/items/5?q=somequery</a> (o equivalente, usando tu host de Docker).
Deberías poder revisarlo en la URL de tu contenedor de Docker, por ejemplo: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) o [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (o equivalente, usando tu host de Docker).
Verás algo como:
@ -362,17 +362,17 @@ Verás algo como:
## Documentación Interactiva de la API { #interactive-api-docs }
Ahora puedes ir a <ahref="http://192.168.99.100/docs"class="external-link"target="_blank">http://192.168.99.100/docs</a> o <ahref="http://127.0.0.1/docs"class="external-link"target="_blank">http://127.0.0.1/docs</a> (o equivalente, usando tu host de Docker).
Ahora puedes ir a [http://192.168.99.100/docs](http://192.168.99.100/docs) o [http://127.0.0.1/docs](http://127.0.0.1/docs) (o equivalente, usando tu host de Docker).
Verás la documentación interactiva automática de la API (proporcionada por <ahref="https://github.com/swagger-api/swagger-ui"class="external-link"target="_blank">Swagger UI</a>):
Verás la documentación interactiva automática de la API (proporcionada por [Swagger UI](https://github.com/swagger-api/swagger-ui)):
## Documentación Alternativa de la API { #alternative-api-docs }
Y también puedes ir a <ahref="http://192.168.99.100/redoc"class="external-link"target="_blank">http://192.168.99.100/redoc</a> o <ahref="http://127.0.0.1/redoc"class="external-link"target="_blank">http://127.0.0.1/redoc</a> (o equivalente, usando tu host de Docker).
Y también puedes ir a [http://192.168.99.100/redoc](http://192.168.99.100/redoc) o [http://127.0.0.1/redoc](http://127.0.0.1/redoc) (o equivalente, usando tu host de Docker).
Verás la documentación alternativa automática (proporcionada por <ahref="https://github.com/Rebilly/ReDoc"class="external-link"target="_blank">ReDoc</a>):
Verás la documentación alternativa automática (proporcionada por [ReDoc](https://github.com/Rebilly/ReDoc)):
@ -413,7 +413,7 @@ Cuando pasas el archivo a `fastapi run`, detectará automáticamente que es un a
## Conceptos de Despliegue { #deployment-concepts }
Hablemos nuevamente de algunos de los mismos [Conceptos de Despliegue](concepts.md){.internal-link target=_blank} en términos de contenedores.
Hablemos nuevamente de algunos de los mismos [Conceptos de Despliegue](concepts.md) en términos de contenedores.
Los contenedores son principalmente una herramienta para simplificar el proceso de **construcción y despliegue** de una aplicación, pero no imponen un enfoque particular para manejar estos **conceptos de despliegue**, y hay varias estrategias posibles.
@ -432,7 +432,7 @@ Revisemos estos **conceptos de despliegue** en términos de contenedores:
Si nos enfocamos solo en la **imagen de contenedor** para una aplicación FastAPI (y luego el **contenedor** en ejecución), HTTPS normalmente sería manejado **externamente** por otra herramienta.
Podría ser otro contenedor, por ejemplo, con <ahref="https://traefik.io/"class="external-link"target="_blank">Traefik</a>, manejando **HTTPS** y la adquisición **automática** de **certificados**.
Podría ser otro contenedor, por ejemplo, con [Traefik](https://traefik.io/), manejando **HTTPS** y la adquisición **automática** de **certificados**.
/// tip | Consejo
@ -558,7 +558,7 @@ Si tienes **múltiples contenedores**, probablemente cada uno ejecutando un **pr
/// info | Información
Si estás usando Kubernetes, probablemente sería un <ahref="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/"class="external-link"target="_blank">Contenedor de Inicialización</a>.
Si estás usando Kubernetes, probablemente sería un [Contenedor de Inicialización](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/).
///
@ -570,7 +570,7 @@ Si tienes una configuración simple, con un **contenedor único** que luego inic
### Imagen Base de Docker { #base-docker-image }
Solía haber una imagen official de Docker de FastAPI: <ahref="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker"class="external-link"target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. Pero ahora está obsoleta. ⛔️
Solía haber una imagen oficial de Docker de FastAPI: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). Pero ahora está obsoleta. ⛔️
Probablemente **no** deberías usar esta imagen base de Docker (o cualquier otra similar).
@ -600,7 +600,7 @@ Por ejemplo:
## Imagen de Docker con `uv` { #docker-image-with-uv }
Si estás usando <ahref="https://github.com/astral-sh/uv"class="external-link"target="_blank">uv</a> para instalar y gestionar tu proyecto, puedes seguir su <ahref="https://docs.astral.sh/uv/guides/integration/docker/"class="external-link"target="_blank">guía de Docker de uv</a>.
Si estás usando [uv](https://github.com/astral-sh/uv) para instalar y gestionar tu proyecto, puedes seguir su [guía de Docker de uv](https://docs.astral.sh/uv/guides/integration/docker/).
Puedes desplegar tu app de FastAPI en <ahref="https://fastapicloud.com"class="external-link"target="_blank">FastAPI Cloud</a> con **un solo comando**; ve y únete a la lista de espera si aún no lo has hecho. 🚀
Puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con **un solo comando**; ve y únete a la lista de espera si aún no lo has hecho. 🚀
## Iniciar sesión { #login }
@ -40,7 +40,7 @@ Deploying to FastAPI Cloud...
## Acerca de FastAPI Cloud { #about-fastapi-cloud }
**<ahref="https://fastapicloud.com"class="external-link"target="_blank">FastAPI Cloud</a>** está creado por el mismo autor y equipo detrás de **FastAPI**.
**[FastAPI Cloud](https://fastapicloud.com)** está creado por el mismo autor y equipo detrás de **FastAPI**.
Agiliza el proceso de **crear**, **desplegar** y **acceder** a una API con el mínimo esfuerzo.
@ -10,7 +10,7 @@ Si tienes prisa o no te importa, continúa con las siguientes secciones para ver
///
Para **aprender los conceptos básicos de HTTPS**, desde una perspectiva de consumidor, revisa <ahref="https://howhttps.works/"class="external-link"target="_blank">https://howhttps.works/</a>.
Para **aprender los conceptos básicos de HTTPS**, desde una perspectiva de consumidor, revisa [https://howhttps.works/](https://howhttps.works/).
Ahora, desde una **perspectiva de desarrollador**, aquí hay varias cosas a tener en cuenta al pensar en HTTPS:
@ -28,13 +28,13 @@ Ahora, desde una **perspectiva de desarrollador**, aquí hay varias cosas a tene
* **Por defecto**, eso significaría que solo puedes tener **un certificado HTTPS por dirección IP**.
* No importa cuán grande sea tu servidor o qué tan pequeña pueda ser cada aplicación que tengas en él.
* Sin embargo, hay una **solución** para esto.
* Hay una **extensión** para el protocolo **TLS** (el que maneja la encriptación a nivel de TCP, antes de HTTP) llamada **<ahref="https://en.wikipedia.org/wiki/Server_Name_Indication"class="external-link"target="_blank"><abbrtitle="Server Name Indication – Indicación del nombre del servidor">SNI</abbr></a>**.
* Hay una **extensión** para el protocolo **TLS** (el que maneja la encriptación a nivel de TCP, antes de HTTP) llamada **[<abbr title="Server Name Indication - Indicación del nombre del servidor">SNI</abbr>](https://en.wikipedia.org/wiki/Server_Name_Indication)**.
* Esta extensión SNI permite que un solo servidor (con una **sola dirección IP**) tenga **varios certificados HTTPS** y sirva **múltiples dominios/aplicaciones HTTPS**.
* Para que esto funcione, un componente (programa) **único** que se ejecute en el servidor, escuchando en la **dirección IP pública**, debe tener **todos los certificados HTTPS** en el servidor.
* **Después** de obtener una conexión segura, el protocolo de comunicación sigue siendo **HTTP**.
* Los contenidos están **encriptados**, aunque se envién con el **protocolo HTTP**.
Es una práctica común tener **un programa/servidor HTTP** ejecutándose en el servidor (la máquina, host, etc.) y **gestionando todas las partes de HTTPS**: recibiendo los **requests HTTPS encriptados**, enviando los **requests HTTP desencriptados** a la aplicación HTTP real que se ejecuta en el mismo servidor (la aplicación **FastAPI**, en este caso), tomando el **response HTTP** de la aplicación, **encriptándolo** usando el **certificado HTTPS** adecuado y enviándolo de vuelta al cliente usando **HTTPS**. Este servidor a menudo se llama un **<ahref="https://en.wikipedia.org/wiki/TLS_termination_proxy"class="external-link"target="_blank">TLS Termination Proxy</a>**.
Es una práctica común tener **un programa/servidor HTTP** ejecutándose en el servidor (la máquina, host, etc.) y **gestionando todas las partes de HTTPS**: recibiendo los **requests HTTPS encriptados**, enviando los **requests HTTP desencriptados** a la aplicación HTTP real que se ejecuta en el mismo servidor (la aplicación **FastAPI**, en este caso), tomando el **response HTTP** de la aplicación, **encriptándolo** usando el **certificado HTTPS** adecuado y enviándolo de vuelta al cliente usando **HTTPS**. Este servidor a menudo se llama un **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)**.
Algunas de las opciones que podrías usar como un TLS Termination Proxy son:
@ -49,7 +49,7 @@ Antes de Let's Encrypt, estos **certificados HTTPS** eran vendidos por terceros.
El proceso para adquirir uno de estos certificados solía ser complicado, requerir bastante papeleo y los certificados eran bastante costosos.
Pero luego se creó **<ahref="https://letsencrypt.org/"class="external-link"target="_blank">Let's Encrypt</a>**.
Pero luego se creó **[Let's Encrypt](https://letsencrypt.org/)**.
Es un proyecto de la Linux Foundation. Proporciona **certificados HTTPS de forma gratuita**, de manera automatizada. Estos certificados usan toda la seguridad criptográfica estándar, y tienen una corta duración (aproximadamente 3 meses), por lo que la **seguridad es en realidad mejor** debido a su lifespan reducida.
@ -200,9 +200,9 @@ Este **proxy** normalmente configuraría algunos headers HTTP sobre la marcha an
@ -218,7 +218,7 @@ Esto sería útil, por ejemplo, para manejar correctamente redirecciones.
/// tip | Consejo
Puedes aprender más sobre esto en la documentación de [Detrás de un proxy - Habilitar headers reenviados por el proxy](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank}
Puedes aprender más sobre esto en la documentación de [Detrás de un proxy - Habilitar headers reenviados por el proxy](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers)
@ -16,7 +16,7 @@ Hay varias maneras de hacerlo dependiendo de tu caso de uso específico y las he
Podrías **desplegar un servidor** tú mismo utilizando una combinación de herramientas, podrías usar un **servicio en la nube** que hace parte del trabajo por ti, u otras opciones posibles.
Por ejemplo, nosotros, el equipo detrás de FastAPI, construimos <ahref="https://fastapicloud.com"class="external-link"target="_blank">**FastAPI Cloud**</a>, para hacer que desplegar aplicaciones de FastAPI en la nube sea lo más ágil posible, con la misma experiencia de desarrollador de trabajar con FastAPI.
Por ejemplo, nosotros, el equipo detrás de FastAPI, construimos [**FastAPI Cloud**](https://fastapicloud.com), para hacer que desplegar aplicaciones de FastAPI en la nube sea lo más ágil posible, con la misma experiencia de desarrollador de trabajar con FastAPI.
Te mostraré algunos de los conceptos principales que probablemente deberías tener en cuenta al desplegar una aplicación **FastAPI** (aunque la mayoría se aplica a cualquier otro tipo de aplicación web).
@ -52,11 +52,11 @@ Lo principal que necesitas para ejecutar una aplicación **FastAPI** (o cualquie
Hay varias alternativas, incluyendo:
* <ahref="https://www.uvicorn.dev/"class="external-link"target="_blank">Uvicorn</a>: un servidor ASGI de alto rendimiento.
* <ahref="https://hypercorn.readthedocs.io/"class="external-link"target="_blank">Hypercorn</a>: un servidor ASGI compatible con HTTP/2 y Trio entre otras funcionalidades.
* <ahref="https://github.com/django/daphne"class="external-link"target="_blank">Daphne</a>: el servidor ASGI construido para Django Channels.
* <ahref="https://github.com/emmett-framework/granian"class="external-link"target="_blank">Granian</a>: Un servidor HTTP Rust para aplicaciones en Python.
* <ahref="https://unit.nginx.org/howto/fastapi/"class="external-link"target="_blank">NGINX Unit</a>: NGINX Unit es un runtime para aplicaciones web ligero y versátil.
* [Uvicorn](https://www.uvicorn.dev/): un servidor ASGI de alto rendimiento.
* [Hypercorn](https://hypercorn.readthedocs.io/): un servidor ASGI compatible con HTTP/2 y Trio entre otras funcionalidades.
* [Daphne](https://github.com/django/daphne): el servidor ASGI construido para Django Channels.
* [Granian](https://github.com/emmett-framework/granian): Un servidor HTTP Rust para aplicaciones en Python.
* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit es un runtime para aplicaciones web ligero y versátil.
## Máquina Servidor y Programa Servidor { #server-machine-and-server-program }
@ -74,7 +74,7 @@ Cuando instalas FastAPI, viene con un servidor de producción, Uvicorn, y puedes
Pero también puedes instalar un servidor ASGI manualmente.
Asegúrate de crear un [entorno virtual](../virtual-environments.md){.internal-link target=_blank}, actívalo, y luego puedes instalar la aplicación del servidor.
Asegúrate de crear un [entorno virtual](../virtual-environments.md), actívalo, y luego puedes instalar la aplicación del servidor.
@ -13,13 +13,13 @@ Hasta este punto, con todos los tutoriales en la documentación, probablemente h
Al desplegar aplicaciones probablemente querrás tener algo de **replicación de procesos** para aprovechar **múltiples núcleos** y poder manejar más requests.
Como viste en el capítulo anterior sobre [Conceptos de Despliegue](concepts.md){.internal-link target=_blank}, hay múltiples estrategias que puedes usar.
Como viste en el capítulo anterior sobre [Conceptos de Despliegue](concepts.md), hay múltiples estrategias que puedes usar.
Aquí te mostraré cómo usar **Uvicorn** con **worker processes** usando el comando `fastapi` o el comando `uvicorn` directamente.
/// info | Información
Si estás usando contenedores, por ejemplo con Docker o Kubernetes, te contaré más sobre eso en el próximo capítulo: [FastAPI en Contenedores - Docker](docker.md){.internal-link target=_blank}.
Si estás usando contenedores, por ejemplo con Docker o Kubernetes, te contaré más sobre eso en el próximo capítulo: [FastAPI en Contenedores - Docker](docker.md).
En particular, cuando corras en **Kubernetes** probablemente **no** querrás usar workers y en cambio correr **un solo proceso de Uvicorn por contenedor**, pero te contaré sobre eso más adelante en ese capítulo.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started parent process <b>[</b><fontcolor="#34E2E2"><b>27365</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27368</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27369</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27370</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27367</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27370</b></font><b>]</b>
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27367</b></font><b>]</b>
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
@ -126,7 +126,7 @@ De la lista de conceptos de despliegue de antes, usar workers ayudaría principa
## Contenedores y Docker { #containers-and-docker }
En el próximo capítulo sobre [FastAPI en Contenedores - Docker](docker.md){.internal-link target=_blank} te explicaré algunas estrategias que podrías usar para manejar los otros **conceptos de despliegue**.
En el próximo capítulo sobre [FastAPI en Contenedores - Docker](docker.md) te explicaré algunas estrategias que podrías usar para manejar los otros **conceptos de despliegue**.
Te mostraré cómo **construir tu propia imagen desde cero** para ejecutar un solo proceso de Uvicorn. Es un proceso sencillo y probablemente es lo que querrías hacer al usar un sistema de gestión de contenedores distribuido como **Kubernetes**.
Se añaden nuevas funcionalidades con frecuencia, se corrigen bugs regularmente, y el código sigue mejorando continuamente.
Por eso las versiones actuales siguen siendo `0.x.x`, esto refleja que cada versión podría tener potencialmente cambios incompatibles. Esto sigue las convenciones de <ahref="https://semver.org/"class="external-link"target="_blank">Semantic Versioning</a>.
Por eso las versiones actuales siguen siendo `0.x.x`, esto refleja que cada versión podría tener potencialmente cambios incompatibles. Esto sigue las convenciones de [Semantic Versioning](https://semver.org/).
Puedes crear aplicaciones de producción con **FastAPI** ahora mismo (y probablemente ya lo has estado haciendo desde hace algún tiempo), solo debes asegurarte de que utilizas una versión que funciona correctamente con el resto de tu código.
@ -34,7 +34,7 @@ Si utilizas cualquier otra herramienta para gestionar tus instalaciones, como `u
## Versiones disponibles { #available-versions }
Puedes ver las versiones disponibles (por ejemplo, para revisar cuál es la más reciente) en las [Release Notes](../release-notes.md){.internal-link target=_blank}.
Puedes ver las versiones disponibles (por ejemplo, para revisar cuál es la más reciente) en las [Release Notes](../release-notes.md).
## Sobre las versiones { #about-versions }
@ -66,7 +66,7 @@ El "MINOR" es el número en el medio, por ejemplo, en `0.2.3`, la versión MINOR
Deberías añadir tests para tu aplicación.
Con **FastAPI** es muy fácil (gracias a Starlette), revisa la documentación: [Testing](../tutorial/testing.md){.internal-link target=_blank}
Con **FastAPI** es muy fácil (gracias a Starlette), revisa la documentación: [Escribir pruebas](../tutorial/testing.md)
Después de tener tests, puedes actualizar la versión de **FastAPI** a una más reciente, y asegurarte de que todo tu código está funcionando correctamente ejecutando tus tests.
Antes de FastAPI versión `0.122.0`, cuando las utilidades de seguridad integradas devolvían un error al cliente después de una autenticación fallida, usaban el código de estado HTTP `403 Forbidden`.
A partir de FastAPI versión `0.122.0`, usan el código de estado HTTP `401 Unauthorized`, más apropiado, y devuelven un `WWW-Authenticate` header adecuado en la response, siguiendo las especificaciones HTTP, <ahref="https://datatracker.ietf.org/doc/html/rfc7235#section-3.1"class="external-link"target="_blank">RFC 7235</a>, <ahref="https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized"class="external-link"target="_blank">RFC 9110</a>.
A partir de FastAPI versión `0.122.0`, usan el código de estado HTTP `401 Unauthorized`, más apropiado, y devuelven un `WWW-Authenticate` header adecuado en la response, siguiendo las especificaciones HTTP, [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized).
Pero si por alguna razón tus clientes dependen del comportamiento anterior, puedes volver a él sobrescribiendo el método `make_not_authenticated_error` en tus clases de seguridad.
@ -10,7 +10,7 @@ Eso no añade ninguna seguridad extra a tu API, las *path operations* seguirán
Si hay una falla de seguridad en tu código, seguirá existiendo.
Ocultar la documentación solo hace que sea más difícil entender cómo interactuar con tu API y podría dificultar más depurarla en producción. Podría considerarse simplemente una forma de <ahref="https://en.wikipedia.org/wiki/Security_through_obscurity"class="external-link"target="_blank">Seguridad mediante oscuridad</a>.
Ocultar la documentación solo hace que sea más difícil entender cómo interactuar con tu API y podría dificultar más depurarla en producción. Podría considerarse simplemente una forma de [Seguridad mediante oscuridad](https://en.wikipedia.org/wiki/Security_through_obscurity).
Si quieres asegurar tu API, hay varias cosas mejores que puedes hacer, por ejemplo:
Puedes configurar algunos <ahref="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/"class="external-link"target="_blank">parámetros adicionales de Swagger UI</a>.
Puedes configurar algunos [parámetros adicionales de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/).
Para configurarlos, pasa el argumento `swagger_ui_parameters` al crear el objeto de la app `FastAPI()` o a la función `get_swagger_ui_html()`.
@ -50,7 +50,7 @@ Por ejemplo, para desactivar `deepLinking` podrías pasar estas configuraciones
## Otros parámetros de Swagger UI { #other-swagger-ui-parameters }
Para ver todas las demás configuraciones posibles que puedes usar, lee la <ahref="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/"class="external-link"target="_blank">documentación oficial de los parámetros de Swagger UI</a>.
Para ver todas las demás configuraciones posibles que puedes usar, lee la [documentación oficial de los parámetros de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/).
## Configuraciones solo de JavaScript { #javascript-only-settings }
La documentación de la API utiliza **Swagger UI** y **ReDoc**, y cada uno de estos necesita algunos archivos JavaScript y CSS.
Por defecto, esos archivos se sirven desde un <abbrtitle="Content Delivery Network – Red de entrega de contenidos: Un servicio, normalmente compuesto de varios servidores, que proporciona archivos estáticos, como JavaScript y CSS. Se usa comúnmente para servir esos archivos desde el servidor más cercano al cliente, mejorando el rendimiento.">CDN</abbr>.
Por defecto, esos archivos se sirven desde un <abbrtitle="Content Delivery Network - Red de entrega de contenidos: Un servicio, normalmente compuesto de varios servidores, que proporciona archivos estáticos, como JavaScript y CSS. Se usa comúnmente para servir esos archivos desde el servidor más cercano al cliente, mejorando el rendimiento.">CDN</abbr>.
Pero es posible personalizarlo, puedes establecer un CDN específico, o servir los archivos tú mismo.
## CDN Personalizado para JavaScript y CSS { #custom-cdn-for-javascript-and-css }
Digamos que quieres usar un <abbrtitle="Content Delivery Network – Red de entrega de contenidos">CDN</abbr> diferente, por ejemplo, quieres usar `https://unpkg.com/`.
Digamos que quieres usar un <abbrtitle="Content Delivery Network - Red de entrega de contenidos">CDN</abbr> diferente, por ejemplo, quieres usar `https://unpkg.com/`.
Esto podría ser útil si, por ejemplo, vives en un país que restringe algunas URLs.
@ -54,7 +54,7 @@ Ahora, para poder probar que todo funciona, crea una *path operation*:
### Pruébalo { #test-it }
Ahora, deberías poder ir a tu documentación en <ahref="http://127.0.0.1:8000/docs"class="external-link"target="_blank">http://127.0.0.1:8000/docs</a>, y recargar la página, cargará esos recursos desde el nuevo CDN.
Ahora, deberías poder ir a tu documentación en [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs), y recargar la página, cargará esos recursos desde el nuevo CDN.
## self hosting de JavaScript y CSS para la documentación { #self-hosting-javascript-and-css-for-docs }
@ -93,12 +93,12 @@ Probablemente puedas hacer clic derecho en cada enlace y seleccionar una opción
Después de eso, tu estructura de archivos podría verse así:
@ -122,7 +122,7 @@ Después de eso, tu estructura de archivos podría verse así:
### Prueba los archivos estáticos { #test-the-static-files }
Inicia tu aplicación y ve a <ahref="http://127.0.0.1:8000/static/redoc.standalone.js"class="external-link"target="_blank">http://127.0.0.1:8000/static/redoc.standalone.js</a>.
Inicia tu aplicación y ve a [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js).
Deberías ver un archivo JavaScript muy largo de **ReDoc**.
@ -180,6 +180,6 @@ Ahora, para poder probar que todo funciona, crea una *path operation*:
### Prueba la UI de Archivos Estáticos { #test-static-files-ui }
Ahora, deberías poder desconectar tu WiFi, ir a tu documentación en <ahref="http://127.0.0.1:8000/docs"class="external-link"target="_blank">http://127.0.0.1:8000/docs</a>, y recargar la página.
Ahora, deberías poder desconectar tu WiFi, ir a tu documentación en [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs), y recargar la página.
E incluso sin Internet, podrás ver la documentación de tu API e interactuar con ella.
@ -18,7 +18,7 @@ Si apenas estás comenzando con **FastAPI**, quizás quieras saltar esta secció
Algunos casos de uso incluyen:
* Convertir cuerpos de requests no-JSON a JSON (por ejemplo, <ahref="https://msgpack.org/index.html"class="external-link"target="_blank">`msgpack`</a>).
* Convertir cuerpos de requests no-JSON a JSON (por ejemplo, [`msgpack`](https://msgpack.org/index.html)).
* Descomprimir cuerpos de requests comprimidos con gzip.
* Registrar automáticamente todos los request bodies.
@ -32,13 +32,13 @@ Y una subclase de `APIRoute` para usar esa clase de request personalizada.
/// tip | Consejo
Este es un ejemplo sencillo para demostrar cómo funciona. Si necesitas soporte para Gzip, puedes usar el [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} proporcionado.
Este es un ejemplo sencillo para demostrar cómo funciona. Si necesitas soporte para Gzip, puedes usar el [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) proporcionado.
///
Primero, creamos una clase `GzipRequest`, que sobrescribirá el método `Request.body()` para descomprimir el cuerpo si hay un header apropiado.
Primero, creamos una clase `GzipRequest`, que sobrescribirá el método `Request.body()` para descomprimir el request body si hay un header apropiado.
Si no hay `gzip` en el header, no intentará descomprimir el cuerpo.
Si no hay `gzip` en el header, no intentará descomprimir el request body.
De esa manera, la misma clase de ruta puede manejar requests comprimidos con gzip o no comprimidos.
@ -60,13 +60,13 @@ Aquí lo usamos para crear un `GzipRequest` a partir del request original.
Un `Request` tiene un atributo `request.scope`, que es simplemente un `dict` de Python que contiene los metadatos relacionados con el request.
Un `Request` también tiene un `request.receive`, que es una función para "recibir" el cuerpo del request.
Un `Request` también tiene un `request.receive`, que es una función para "recibir" el request body.
El `dict``scope` y la función `receive` son ambos parte de la especificación ASGI.
Y esas dos cosas, `scope` y `receive`, son lo que se necesita para crear una nueva *Request instance*.
Para aprender más sobre el `Request`, revisa <ahref="https://www.starlette.dev/requests/"class="external-link"target="_blank">la documentación de Starlette sobre Requests</a>.
Para aprender más sobre el `Request`, revisa [la documentación de Starlette sobre Requests](https://www.starlette.dev/requests/).
///
@ -82,7 +82,7 @@ Pero debido a nuestros cambios en `GzipRequest.body`, el request body se descomp
/// tip | Consejo
Para resolver este mismo problema, probablemente sea mucho más fácil usar el `body` en un manejador personalizado para `RequestValidationError` ([Manejo de Errores](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}).
Para resolver este mismo problema, probablemente sea mucho más fácil usar el `body` en un manejador personalizado para `RequestValidationError` ([Manejo de Errores](../tutorial/handling-errors.md#use-the-requestvalidationerror-body)).
Pero este ejemplo sigue siendo válido y muestra cómo interactuar con los componentes internos.
@ -37,7 +37,7 @@ El parámetro `summary` está disponible en OpenAPI 3.1.0 y versiones superiores
Usando la información anterior, puedes usar la misma función de utilidad para generar el esquema de OpenAPI y sobrescribir cada parte que necesites.
Por ejemplo, vamos a añadir <ahref="https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo"class="external-link"target="_blank">la extensión OpenAPI de ReDoc para incluir un logo personalizado</a>.
Por ejemplo, vamos a añadir [la extensión OpenAPI de ReDoc para incluir un logo personalizado](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo).
### **FastAPI** normal { #normal-fastapi }
@ -75,6 +75,6 @@ Ahora puedes reemplazar el método `.openapi()` por tu nueva función.
### Revisa { #check-it }
Una vez que vayas a <ahref="http://127.0.0.1:8000/redoc"class="external-link"target="_blank">http://127.0.0.1:8000/redoc</a> verás que estás usando tu logo personalizado (en este ejemplo, el logo de **FastAPI**):
Una vez que vayas a [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) verás que estás usando tu logo personalizado (en este ejemplo, el logo de **FastAPI**):
@ -4,36 +4,40 @@ Aquí tienes varias indicaciones hacia otros lugares en la documentación, para
## Filtrar Datos - Seguridad { #filter-data-security }
Para asegurarte de que no devuelves más datos de los que deberías, lee la documentación para [Tutorial - Modelo de Response - Tipo de Retorno](../tutorial/response-model.md){.internal-link target=_blank}.
Para asegurarte de que no devuelves más datos de los que deberías, lee la documentación para [Tutorial - Modelo de Response - Tipo de Retorno](../tutorial/response-model.md).
## Optimizar el Rendimiento del Response - Modelo de Response - Tipo de Retorno { #optimize-response-performance-response-model-return-type }
Para optimizar el rendimiento al devolver datos JSON, usa un tipo de retorno o un modelo de Response; de esa manera Pydantic se encargará de la serialización a JSON del lado de Rust, sin pasar por Python. Lee más en la documentación para [Tutorial - Modelo de Response - Tipo de Retorno](../tutorial/response-model.md).
## Etiquetas de Documentación - OpenAPI { #documentation-tags-openapi }
Para agregar etiquetas a tus *path operations*, y agruparlas en la interfaz de usuario de la documentación, lee la documentación para [Tutorial - Configuraciones de Path Operation - Etiquetas](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}.
Para agregar etiquetas a tus *path operations*, y agruparlas en la interfaz de usuario de la documentación, lee la documentación para [Tutorial - Configuraciones de Path Operation - Etiquetas](../tutorial/path-operation-configuration.md#tags).
## Resumen y Descripción de Documentación - OpenAPI { #documentation-summary-and-description-openapi }
Para agregar un resumen y descripción a tus *path operations*, y mostrarlos en la interfaz de usuario de la documentación, lee la documentación para [Tutorial - Configuraciones de Path Operation - Resumen y Descripción](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}.
Para agregar un resumen y descripción a tus *path operations*, y mostrarlos en la interfaz de usuario de la documentación, lee la documentación para [Tutorial - Configuraciones de Path Operation - Resumen y Descripción](../tutorial/path-operation-configuration.md#summary-and-description).
## Documentación de Descripción de Response - OpenAPI { #documentation-response-description-openapi }
Para definir la descripción del response, mostrada en la interfaz de usuario de la documentación, lee la documentación para [Tutorial - Configuraciones de Path Operation - Descripción del Response](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}.
Para definir la descripción del response, mostrada en la interfaz de usuario de la documentación, lee la documentación para [Tutorial - Configuraciones de Path Operation - Descripción del Response](../tutorial/path-operation-configuration.md#response-description).
## Documentar la Deprecación de una *Path Operation* - OpenAPI { #documentation-deprecate-a-path-operation-openapi }
Para deprecar una *path operation*, y mostrarla en la interfaz de usuario de la documentación, lee la documentación para [Tutorial - Configuraciones de Path Operation - Deprecación](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}.
Para deprecar una *path operation*, y mostrarla en la interfaz de usuario de la documentación, lee la documentación para [Tutorial - Configuraciones de Path Operation - Deprecación](../tutorial/path-operation-configuration.md#deprecate-a-path-operation).
## Convertir cualquier Dato a Compatible con JSON { #convert-any-data-to-json-compatible }
Para convertir cualquier dato a compatible con JSON, lee la documentación para [Tutorial - Codificador Compatible con JSON](../tutorial/encoder.md){.internal-link target=_blank}.
Para convertir cualquier dato a compatible con JSON, lee la documentación para [Tutorial - Codificador Compatible con JSON](../tutorial/encoder.md).
Para agregar metadatos a tu esquema de OpenAPI, incluyendo una licencia, versión, contacto, etc, lee la documentación para [Tutorial - Metadatos y URLs de Documentación](../tutorial/metadata.md){.internal-link target=_blank}.
Para agregar metadatos a tu esquema de OpenAPI, incluyendo una licencia, versión, contacto, etc, lee la documentación para [Tutorial - Metadatos y URLs de Documentación](../tutorial/metadata.md).
## URL Personalizada de OpenAPI { #openapi-custom-url }
Para personalizar la URL de OpenAPI (o eliminarla), lee la documentación para [Tutorial - Metadatos y URLs de Documentación](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}.
Para personalizar la URL de OpenAPI (o eliminarla), lee la documentación para [Tutorial - Metadatos y URLs de Documentación](../tutorial/metadata.md#openapi-url).
## URLs de Documentación de OpenAPI { #openapi-docs-urls }
Para actualizar las URLs usadas para las interfaces de usuario de documentación generadas automáticamente, lee la documentación para [Tutorial - Metadatos y URLs de Documentación](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}.
Para actualizar las URLs usadas para las interfaces de usuario de documentación generadas automáticamente, lee la documentación para [Tutorial - Metadatos y URLs de Documentación](../tutorial/metadata.md#docs-urls).
* Con <ahref="https://tartiflette.github.io/tartiflette-asgi/"class="external-link"target="_blank">Tartiflette ASGI</a> para proporcionar integración con ASGI
* Con <ahref="https://github.com/ciscorn/starlette-graphene3"class="external-link"target="_blank">starlette-graphene3</a>
* [Strawberry](https://strawberry.rocks/) 🍓
* Con [documentación para FastAPI](https://strawberry.rocks/docs/integrations/fastapi)
* [Ariadne](https://ariadnegraphql.org/)
* Con [documentación para FastAPI](https://ariadnegraphql.org/docs/fastapi-integration)
* [Tartiflette](https://tartiflette.io/)
* Con [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) para proporcionar integración con ASGI
* [Graphene](https://graphene-python.org/)
* Con [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3)
## GraphQL con Strawberry { #graphql-with-strawberry }
Si necesitas o quieres trabajar con **GraphQL**, <ahref="https://strawberry.rocks/"class="external-link"target="_blank">**Strawberry**</a> es el paquete **recomendado** ya que tiene un diseño muy similar al diseño de **FastAPI**, todo basado en **anotaciones de tipos**.
Si necesitas o quieres trabajar con **GraphQL**, [**Strawberry**](https://strawberry.rocks/) es el paquete **recomendado** ya que tiene un diseño muy similar al diseño de **FastAPI**, todo basado en **anotaciones de tipos**.
Dependiendo de tu caso de uso, podrías preferir usar un paquete diferente, pero si me preguntas, probablemente te sugeriría probar **Strawberry**.
@ -37,24 +37,24 @@ Aquí tienes una pequeña vista previa de cómo podrías integrar Strawberry con
Puedes aprender más sobre Strawberry en la <ahref="https://strawberry.rocks/"class="external-link"target="_blank">documentación de Strawberry</a>.
Puedes aprender más sobre Strawberry en la [documentación de Strawberry](https://strawberry.rocks/).
Y también la documentación sobre <ahref="https://strawberry.rocks/docs/integrations/fastapi"class="external-link"target="_blank">Strawberry con FastAPI</a>.
Y también la documentación sobre [Strawberry con FastAPI](https://strawberry.rocks/docs/integrations/fastapi).
## `GraphQLApp` viejo de Starlette { #older-graphqlapp-from-starlette }
Las versiones anteriores de Starlette incluían una clase `GraphQLApp` para integrar con <ahref="https://graphene-python.org/"class="external-link"target="_blank">Graphene</a>.
Las versiones anteriores de Starlette incluían una clase `GraphQLApp` para integrar con [Graphene](https://graphene-python.org/).
Fue deprecada de Starlette, pero si tienes código que lo usaba, puedes fácilmente **migrar** a <ahref="https://github.com/ciscorn/starlette-graphene3"class="external-link"target="_blank">starlette-graphene3</a>, que cubre el mismo caso de uso y tiene una **interfaz casi idéntica**.
Fue deprecada de Starlette, pero si tienes código que lo usaba, puedes fácilmente **migrar** a [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3), que cubre el mismo caso de uso y tiene una **interfaz casi idéntica**.
/// tip | Consejo
Si necesitas GraphQL, aún te recomendaría revisar <ahref="https://strawberry.rocks/"class="external-link"target="_blank">Strawberry</a>, ya que se basa en anotaciones de tipos en lugar de clases y tipos personalizados.
Si necesitas GraphQL, aún te recomendaría revisar [Strawberry](https://strawberry.rocks/), ya que se basa en anotaciones de tipos en lugar de clases y tipos personalizados.
///
## Aprende Más { #learn-more }
Puedes aprender más sobre **GraphQL** en la <ahref="https://graphql.org/"class="external-link"target="_blank">documentación oficial de GraphQL</a>.
Puedes aprender más sobre **GraphQL** en la [documentación oficial de GraphQL](https://graphql.org/).
También puedes leer más sobre cada uno de esos paquetes descritos arriba en sus enlaces.
@ -8,6 +8,6 @@ Si algo parece interesante y útil para tu proyecto, adelante y revísalo, pero
/// tip | Consejo
Si quieres **aprender FastAPI** de una manera estructurada (recomendado), ve y lee el [Tutorial - Guía de Usuario](../tutorial/index.md){.internal-link target=_blank} capítulo por capítulo en su lugar.
Si quieres **aprender FastAPI** de una manera estructurada (recomendado), ve y lee el [Tutorial - Guía de Usuario](../tutorial/index.md) capítulo por capítulo en su lugar.
@ -22,7 +22,7 @@ Si tienes una app de FastAPI antigua con Pydantic v1, aquí te muestro cómo mig
## Guía oficial { #official-guide }
Pydantic tiene una <ahref="https://docs.pydantic.dev/latest/migration/"class="external-link"target="_blank">Guía de migración</a> oficial de v1 a v2.
Pydantic tiene una [Guía de migración](https://docs.pydantic.dev/latest/migration/) oficial de v1 a v2.
También incluye qué cambió, cómo las validaciones ahora son más correctas y estrictas, posibles consideraciones, etc.
@ -30,7 +30,7 @@ Puedes leerla para entender mejor qué cambió.
## Tests { #tests }
Asegúrate de tener [tests](../tutorial/testing.md){.internal-link target=_blank} para tu app y de ejecutarlos en integración continua (CI).
Asegúrate de tener [tests](../tutorial/testing.md) para tu app y de ejecutarlos en integración continua (CI).
Así podrás hacer la actualización y asegurarte de que todo sigue funcionando como esperas.
@ -38,7 +38,7 @@ Así podrás hacer la actualización y asegurarte de que todo sigue funcionando
En muchos casos, cuando usas modelos de Pydantic normales sin personalizaciones, podrás automatizar gran parte del proceso de migración de Pydantic v1 a Pydantic v2.
Puedes usar <ahref="https://github.com/pydantic/bump-pydantic"class="external-link"target="_blank">`bump-pydantic`</a> del mismo equipo de Pydantic.
Puedes usar [`bump-pydantic`](https://github.com/pydantic/bump-pydantic) del mismo equipo de Pydantic.
Esta herramienta te ayudará a cambiar automáticamente la mayor parte del código que necesita cambiarse.
# Escribiendo pruebas para una base de datos { #testing-a-database }
# Escribir pruebas para una base de datos { #testing-a-database }
Puedes estudiar sobre bases de datos, SQL y SQLModel en la <ahref="https://sqlmodel.tiangolo.com/"class="external-link"target="_blank">documentación de SQLModel</a>. 🤓
Puedes estudiar sobre bases de datos, SQL y SQLModel en la [documentación de SQLModel](https://sqlmodel.tiangolo.com/). 🤓
Hay un mini <ahref="https://sqlmodel.tiangolo.com/tutorial/fastapi/"class="external-link"target="_blank">tutorial sobre el uso de SQLModel con FastAPI</a>. ✨
Hay un mini [tutorial sobre el uso de SQLModel con FastAPI](https://sqlmodel.tiangolo.com/tutorial/fastapi/). ✨
Ese tutorial incluye una sección sobre <ahref="https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/"class="external-link"target="_blank">escribir pruebas para bases de datos SQL</a>. 😎
Ese tutorial incluye una sección sobre [escribir pruebas para bases de datos SQL](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/). 😎