committed by
GitHub
4 changed files with 0 additions and 342 deletions
@ -1,96 +0,0 @@ |
|||||
# 고급 미들웨어 |
|
||||
|
|
||||
메인 튜토리얼에서 [Custom Middleware](../tutorial/middleware.md){.internal-link target=_blank}를 응용프로그램에 추가하는 방법을 읽으셨습니다. |
|
||||
|
|
||||
그리고 [CORS with the `CORSMiddleware`](){.internal-link target=_blank}하는 방법도 보셨습니다. |
|
||||
|
|
||||
이 섹션에서는 다른 미들웨어들을 사용하는 방법을 알아보겠습니다. |
|
||||
|
|
||||
## ASGI 미들웨어 추가하기 |
|
||||
|
|
||||
**FastAPI**는 Starlette을 기반으로 하고 있으며, <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr> 사양을 구현하므로 ASGI 미들웨어를 사용할 수 있습니다. |
|
||||
|
|
||||
미들웨어가 FastAPI나 Starlette용으로 만들어지지 않아도 ASGI 사양을 준수하는 한 동작할 수 있습니다. |
|
||||
|
|
||||
일반적으로 ASGI 미들웨어는 첫 번째 인수로 ASGI 앱을 받는 클래스들입니다. |
|
||||
|
|
||||
따라서 타사 ASGI 미들웨어 문서에서 일반적으로 다음과 같이 사용하도록 안내할 것입니다. |
|
||||
|
|
||||
```Python |
|
||||
from unicorn import UnicornMiddleware |
|
||||
|
|
||||
app = SomeASGIApp() |
|
||||
|
|
||||
new_app = UnicornMiddleware(app, some_config="rainbow") |
|
||||
``` |
|
||||
|
|
||||
하지만 내부 미들웨어가 서버 오류를 처리하고 사용자 정의 예외 처리기가 제대로 작동하도록 하는 더 간단한 방법을 제공하는 FastAPI(실제로는 Starlette)가 있습니다. |
|
||||
|
|
||||
이를 위해 `app.add_middleware()`를 사용합니다(CORS의 예에서와 같이). |
|
||||
|
|
||||
```Python |
|
||||
from fastapi import FastAPI |
|
||||
from unicorn import UnicornMiddleware |
|
||||
|
|
||||
app = FastAPI() |
|
||||
|
|
||||
app.add_middleware(UnicornMiddleware, some_config="rainbow") |
|
||||
``` |
|
||||
|
|
||||
`app.add_middleware()`는 첫 번째 인수로 미들웨어 클래스와 미들웨어에 전달할 추가 인수를 받습니다. |
|
||||
|
|
||||
## 통합 미들웨어 |
|
||||
|
|
||||
**FastAPI**에는 일반적인 사용 사례를 위한 여러 미들웨어가 포함되어 있으며, 사용 방법은 다음에서 살펴보겠습니다. |
|
||||
|
|
||||
/// note | 기술 세부 사항 |
|
||||
|
|
||||
다음 예제에서는 `from starlette.middleware.something import SomethingMiddleware`를 사용할 수도 있습니다. |
|
||||
|
|
||||
**FastAPI**는 개발자의 편의를 위해 `fastapi.middleware`에 여러 미들웨어를 제공합니다. 그러나 사용 가능한 대부분의 미들웨어는 Starlette에서 직접 제공합니다. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
## `HTTPSRedirectMiddleware` |
|
||||
|
|
||||
들어오는 모든 요청이 `https` 또는 `wss`여야 합니다. |
|
||||
|
|
||||
`http` 또는 `ws`로 들어오는 모든 요청은 대신 보안 체계로 리디렉션됩니다. |
|
||||
|
|
||||
{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *} |
|
||||
|
|
||||
## `TrustedHostMiddleware` |
|
||||
|
|
||||
HTTP 호스트 헤더 공격을 방지하기 위해 모든 수신 요청에 올바르게 설정된 `Host` 헤더를 갖도록 강제합니다. |
|
||||
|
|
||||
{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *} |
|
||||
|
|
||||
다음 인수가 지원됩니다: |
|
||||
|
|
||||
* `allowed_hosts` - 호스트 이름으로 허용해야 하는 도메인 이름 목록입니다. 일치하는 하위 도메인에 대해 `*.example.com`과 같은 와일드카드 도메인이 지원됩니다. 모든 호스트 이름을 허용하려면 `allowed_hosts=[“*”]`를 사용하거나 미들웨어를 생략하세요. |
|
||||
|
|
||||
수신 요청의 유효성이 올바르게 확인되지 않으면 `400`이라는 응답이 전송됩니다. |
|
||||
|
|
||||
## `GZipMiddleware` |
|
||||
|
|
||||
`Accept-Encoding` 헤더에 `“gzip”`이 포함된 모든 요청에 대해 GZip 응답을 처리합니다. |
|
||||
|
|
||||
미들웨어는 표준 응답과 스트리밍 응답을 모두 처리합니다. |
|
||||
|
|
||||
{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *} |
|
||||
|
|
||||
지원되는 인수는 다음과 같습니다: |
|
||||
|
|
||||
* `minimum_size` - 이 최소 크기(바이트)보다 작은 응답은 GZip하지 않습니다. 기본값은 `500`입니다. |
|
||||
* `compresslevel` - GZip 압축 중에 사용됩니다. 1에서 9 사이의 정수입니다. 기본값은 `9`입니다. 값이 낮을수록 압축 속도는 빨라지지만 파일 크기는 커지고, 값이 높을수록 압축 속도는 느려지지만 파일 크기는 작아집니다. |
|
||||
|
|
||||
## 기타 미들웨어 |
|
||||
|
|
||||
다른 많은 ASGI 미들웨어가 있습니다. |
|
||||
|
|
||||
예를 들어: |
|
||||
|
|
||||
<a href=“https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py” class=“external-link” target=“_blank”>유비콘의 `ProxyHeadersMiddleware`></a> |
|
||||
<a href=“https://github.com/florimondmanca/msgpack-asgi” class=“external-link” target=“_blank”>MessagePack</a> |
|
||||
|
|
||||
사용 가능한 다른 미들웨어를 확인하려면 <a href=“https://www.starlette.io/middleware/” class=“external-link” target=“_blank”>스타렛의 미들웨어 문서</a> 및 <a href=“https://github.com/florimondmanca/awesome-asgi” class=“external-link” target=“_blank”>ASGI Awesome List</a>를 참조하세요. |
|
@ -1,55 +0,0 @@ |
|||||
# OpenAPI 웹훅(Webhooks) |
|
||||
|
|
||||
API **사용자**에게 특정 **이벤트**가 발생할 때 *그들*의 앱(시스템)에 요청을 보내 **알림**을 전달할 수 있다는 것을 알리고 싶은 경우가 있습니다. |
|
||||
|
|
||||
즉, 일반적으로 사용자가 API에 요청을 보내는 것과는 반대로, **API**(또는 앱)가 **사용자의 시스템**(그들의 API나 앱)으로 **요청을 보내는** 상황을 의미합니다. |
|
||||
|
|
||||
이를 흔히 **웹훅(Webhook)**이라고 부릅니다. |
|
||||
|
|
||||
## 웹훅 스텝 |
|
||||
|
|
||||
**코드에서** 웹훅으로 보낼 메시지, 즉 요청의 **바디(body)**를 정의하는 것이 일반적인 프로세스입니다. |
|
||||
|
|
||||
앱에서 해당 요청이나 이벤트를 전송할 **시점**을 정의합니다. |
|
||||
|
|
||||
**사용자**는 앱이 해당 요청을 보낼 **URL**을 정의합니다. (예: 웹 대시보드에서 설정) |
|
||||
|
|
||||
웹훅의 URL을 등록하는 방법과 이러한 요청을 실제로 전송하는 코드에 대한 모든 로직은 여러분에게 달려 있습니다. 원하는대로 **고유의 코드**를 작성하면 됩니다. |
|
||||
|
|
||||
## **FastAPI**와 OpenAPI로 웹훅 문서화하기 |
|
||||
|
|
||||
**FastAPI**를 사용하여 OpenAPI와 함께 웹훅의 이름, 앱이 보낼 수 있는 HTTP 작업 유형(예: `POST`, `PUT` 등), 그리고 보낼 요청의 **바디**를 정의할 수 있습니다. |
|
||||
|
|
||||
이를 통해 사용자가 **웹훅** 요청을 수신할 **API 구현**을 훨씬 쉽게 할 수 있으며, 경우에 따라 사용자 API 코드의 일부를 자동 생성할 수도 있습니다. |
|
||||
|
|
||||
/// info |
|
||||
|
|
||||
웹훅은 OpenAPI 3.1.0 이상에서 지원되며, FastAPI `0.99.0` 이상 버전에서 사용할 수 있습니다. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
## 웹훅이 포함된 앱 만들기 |
|
||||
|
|
||||
**FastAPI** 애플리케이션을 만들 때, `webhooks` 속성을 사용하여 *웹훅*을 정의할 수 있습니다. 이는 `@app.webhooks.post()`와 같은 방식으로 *경로(path) 작업*을 정의하는 것과 비슷합니다. |
|
||||
|
|
||||
{* ../../docs_src/openapi_webhooks/tutorial001.py hl[9:13,36:53] *} |
|
||||
|
|
||||
이렇게 정의한 웹훅은 **OpenAPI** 스키마와 자동 **문서화 UI**에 표시됩니다. |
|
||||
|
|
||||
/// info |
|
||||
|
|
||||
`app.webhooks` 객체는 사실 `APIRouter`일 뿐이며, 여러 파일로 앱을 구성할 때 사용하는 것과 동일한 타입입니다. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
웹훅에서는 실제 **경로(path)** (예: `/items/`)를 선언하지 않는 점에 유의해야 합니다. 여기서 전달하는 텍스트는 **식별자**로, 웹훅의 이름(이벤트 이름)입니다. 예를 들어, `@app.webhooks.post("new-subscription")`에서 웹훅 이름은 `new-subscription`입니다. |
|
||||
|
|
||||
이는 실제 **URL 경로**는 **사용자**가 다른 방법(예: 웹 대시보드)을 통해 지정하도록 기대되기 때문입니다. |
|
||||
|
|
||||
### 문서 확인하기 |
|
||||
|
|
||||
이제 앱을 시작하고 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>로 이동해 봅시다. |
|
||||
|
|
||||
문서에서 기존 *경로 작업*뿐만 아니라 **웹훅**도 표시된 것을 확인할 수 있습니다: |
|
||||
|
|
||||
<img src="/img/tutorial/openapi-webhooks/image01.png"> |
|
@ -1,19 +0,0 @@ |
|||||
# 고급 보안 |
|
||||
|
|
||||
## 추가 기능 |
|
||||
|
|
||||
[자습서 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank} 문서에서 다룬 내용 외에도 보안 처리를 위한 몇 가지 추가 기능이 있습니다. |
|
||||
|
|
||||
/// tip |
|
||||
|
|
||||
다음 섹션은 **반드시 "고급"** 기능은 아닙니다. |
|
||||
|
|
||||
그리고 여러분의 사용 사례에 따라, 적합한 해결책이 그 중 하나에 있을 가능성이 있습니다. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
## 먼저 자습서 읽기 |
|
||||
|
|
||||
다음 섹션은 이미 [자습서 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank} 문서를 읽었다고 가정합니다. |
|
||||
|
|
||||
이 섹션들은 모두 동일한 개념을 바탕으로 하며, 추가 기능을 제공합니다. |
|
@ -1,172 +0,0 @@ |
|||||
# Arquivos de Requisição |
|
||||
|
|
||||
Você pode definir arquivos para serem enviados para o cliente utilizando `File`. |
|
||||
|
|
||||
/// info |
|
||||
|
|
||||
Para receber arquivos compartilhados, primeiro instale <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>. |
|
||||
|
|
||||
E.g. `pip install python-multipart`. |
|
||||
|
|
||||
Isso se deve por que arquivos enviados são enviados como "dados de formulário". |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
## Importe `File` |
|
||||
|
|
||||
Importe `File` e `UploadFile` do `fastapi`: |
|
||||
|
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} |
|
||||
|
|
||||
## Defina os parâmetros de `File` |
|
||||
|
|
||||
Cria os parâmetros do arquivo da mesma forma que você faria para `Body` ou `Form`: |
|
||||
|
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} |
|
||||
|
|
||||
/// info | Informação |
|
||||
|
|
||||
`File` é uma classe que herda diretamente de `Form`. |
|
||||
|
|
||||
Mas lembre-se que quando você importa `Query`,`Path`, `File`, entre outros, do `fastapi`, essas são na verdade funções que retornam classes especiais. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
/// tip | Dica |
|
||||
|
|
||||
Para declarar o corpo de arquivos, você precisa utilizar `File`, do contrário os parâmetros seriam interpretados como parâmetros de consulta ou corpo (JSON) da requisição. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
Os arquivos serão enviados como "form data". |
|
||||
|
|
||||
Se você declarar o tipo do seu parâmetro na sua *função de operação de rota* como `bytes`, o **FastAPI** irá ler o arquivo para você e você receberá o conteúdo como `bytes`. |
|
||||
|
|
||||
Lembre-se que isso significa que o conteúdo inteiro será armazenado em memória. Isso funciona bem para arquivos pequenos. |
|
||||
|
|
||||
Mas existem vários casos em que você pode se beneficiar ao usar `UploadFile`. |
|
||||
|
|
||||
## Parâmetros de arquivo com `UploadFile` |
|
||||
|
|
||||
Defina um parâmetro de arquivo com o tipo `UploadFile` |
|
||||
|
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} |
|
||||
|
|
||||
Utilizando `UploadFile` tem várias vantagens sobre `bytes`: |
|
||||
|
|
||||
* Você não precisa utilizar `File()` como o valor padrão do parâmetro. |
|
||||
* A classe utiliza um arquivo em "spool": |
|
||||
* Um arquivo guardado em memória até um tamanho máximo, depois desse limite ele é guardado em disco. |
|
||||
* Isso significa que a classe funciona bem com arquivos grandes como imagens, vídeos, binários extensos, etc. Sem consumir toda a memória. |
|
||||
* Você pode obter metadados do arquivo enviado. |
|
||||
* Ela possui uma interface <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">semelhante a arquivos</a> `async`. |
|
||||
* Ela expõe um objeto python <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> que você pode repassar para bibliotecas que esperam um objeto com comportamento de arquivo. |
|
||||
|
|
||||
### `UploadFile` |
|
||||
|
|
||||
`UploadFile` tem os seguintes atributos: |
|
||||
|
|
||||
* `filename`: Uma string (`str`) com o nome original do arquivo enviado (e.g. `myimage.jpg`). |
|
||||
* `content-type`: Uma `str` com o tipo do conteúdo (tipo MIME / media) (e.g. `image/jpeg`). |
|
||||
* `file`: Um objeto do tipo <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (um objeto <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a>). O arquivo propriamente dito que você pode passar diretamente para outras funções ou bibliotecas que esperam um objeto "file-like". |
|
||||
|
|
||||
`UploadFile` tem os seguintes métodos `async`. Todos eles chamam os métodos de arquivos por baixo dos panos (usando o objeto `SpooledTemporaryFile` interno). |
|
||||
|
|
||||
* `write(data)`: escreve dados (`data`) em `str` ou `bytes` no arquivo. |
|
||||
* `read(size)`: Lê um número de bytes/caracteres de acordo com a quantidade `size` (`int`). |
|
||||
* `seek(offset)`: Navega para o byte na posição `offset` (`int`) do arquivo. |
|
||||
* E.g., `await myfile.seek(0)` navegaria para o ínicio do arquivo. |
|
||||
* Isso é especialmente útil se você executar `await myfile.read()` uma vez e depois precisar ler os conteúdos do arquivo de novo. |
|
||||
* `close()`: Fecha o arquivo. |
|
||||
|
|
||||
Como todos esses métodos são assíncronos (`async`) você precisa esperar ("await") por eles. |
|
||||
|
|
||||
Por exemplo, dentro de uma *função de operação de rota* assíncrona você pode obter os conteúdos com: |
|
||||
|
|
||||
```Python |
|
||||
contents = await myfile.read() |
|
||||
``` |
|
||||
|
|
||||
Se você estiver dentro de uma *função de operação de rota* definida normalmente com `def`, você pode acessar `UploadFile.file` diretamente, por exemplo: |
|
||||
|
|
||||
```Python |
|
||||
contents = myfile.file.read() |
|
||||
``` |
|
||||
|
|
||||
/// note | Detalhes técnicos do `async` |
|
||||
|
|
||||
Quando você utiliza métodos assíncronos, o **FastAPI** executa os métodos do arquivo em uma threadpool e espera por eles. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
/// note | Detalhes técnicos do Starlette |
|
||||
|
|
||||
O `UploadFile` do **FastAPI** herda diretamente do `UploadFile` do **Starlette**, mas adiciona algumas funcionalidades necessárias para ser compatível com o **Pydantic** |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
## O que é "Form Data" |
|
||||
|
|
||||
A forma como formulários HTML(`<form></form>`) enviam dados para o servidor normalmente utilizam uma codificação "especial" para esses dados, que é diferente do JSON. |
|
||||
|
|
||||
O **FastAPI** garante que os dados serão lidos da forma correta, em vez do JSON. |
|
||||
|
|
||||
/// note | Detalhes Técnicos |
|
||||
|
|
||||
Dados vindos de formulários geralmente tem a codificação com o "media type" `application/x-www-form-urlencoded` quando estes não incluem arquivos. |
|
||||
|
|
||||
Mas quando os dados incluem arquivos, eles são codificados como `multipart/form-data`. Se você utilizar `File`, **FastAPI** saberá que deve receber os arquivos da parte correta do corpo da requisição. |
|
||||
|
|
||||
Se você quer ler mais sobre essas codificações e campos de formulário, veja a documentação online da <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> sobre <code> POST</code> </a>. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
/// warning | Aviso |
|
||||
|
|
||||
Você pode declarar múltiplos parâmetros `File` e `Form` em uma *operação de rota*, mas você não pode declarar campos `Body`que seriam recebidos como JSON junto desses parâmetros, por que a codificação do corpo da requisição será `multipart/form-data` em vez de `application/json`. |
|
||||
|
|
||||
Isso não é uma limitação do **FastAPI**, é uma parte do protocolo HTTP. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
## Arquivo de upload opcional |
|
||||
|
|
||||
Você pode definir um arquivo como opcional utilizando as anotações de tipo padrão e definindo o valor padrão como `None`: |
|
||||
|
|
||||
{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} |
|
||||
|
|
||||
## `UploadFile` com Metadados Adicionais |
|
||||
|
|
||||
Você também pode utilizar `File()` com `UploadFile`, por exemplo, para definir metadados adicionais: |
|
||||
|
|
||||
{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} |
|
||||
|
|
||||
## Envio de Múltiplos Arquivos |
|
||||
|
|
||||
É possível enviar múltiplos arquivos ao mesmo tmepo. |
|
||||
|
|
||||
Ele ficam associados ao mesmo "campo do formulário" enviado com "form data". |
|
||||
|
|
||||
Para usar isso, declare uma lista de `bytes` ou `UploadFile`: |
|
||||
|
|
||||
{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} |
|
||||
|
|
||||
Você irá receber, como delcarado uma lista (`list`) de `bytes` ou `UploadFile`s, |
|
||||
|
|
||||
/// note | Detalhes Técnicos |
|
||||
|
|
||||
Você também poderia utilizar `from starlette.responses import HTMLResponse`. |
|
||||
|
|
||||
O **FastAPI** fornece as mesmas `starlette.responses` como `fastapi.responses` apenas como um facilitador para você, desenvolvedor. Mas a maior parte das respostas vem diretamente do Starlette. |
|
||||
|
|
||||
/// |
|
||||
|
|
||||
### Enviando Múltiplos Arquivos com Metadados Adicionais |
|
||||
|
|
||||
E da mesma forma que antes, você pode utilizar `File()` para definir parâmetros adicionais, até mesmo para `UploadFile`: |
|
||||
|
|
||||
{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} |
|
||||
|
|
||||
## Recapitulando |
|
||||
|
|
||||
Use `File`, `bytes` e `UploadFile` para declarar arquivos que serão enviados na requisição, enviados como dados do formulário. |
|
Loading…
Reference in new issue