From 50191c15f8d776d039afe8b6a22270f8d30e254c Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:42:52 +0300
Subject: [PATCH 001/776] New translations cookies.md (Korean)
---
src/ko/guide/basics/cookies.md | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)
diff --git a/src/ko/guide/basics/cookies.md b/src/ko/guide/basics/cookies.md
index 24c8cdacdc..c030cd7757 100644
--- a/src/ko/guide/basics/cookies.md
+++ b/src/ko/guide/basics/cookies.md
@@ -4,27 +4,21 @@
---:1
-쿠키는 `Request` 객체의 `cookies` 사전(dict)을 통해 액세스 할 수 있습니다.
-
-:--:1
-
+쿠키는 `Request` 객체의 `cookies` 사전(dict)을 통해 액세스 할 수 있습니다. :--:1
```python
@app.route("/cookie")
async def test(request):
test_cookie = request.cookies.get("test")
return text("Test cookie: {}".format(test_cookie))
```
-
:---
+
## 쓰기(Writing)
---:1
-응답을 반환할 때 `Response`객체인 `response.cookies`에 쿠키를 설정할 수 있습니다. 이 객체는 응답 헤더를 자동으로 작성하는 특별한 종류의 사전(dict)인 `CookieJar`의 인스턴스입니다.
-
-:--:1
-
+응답을 반환할 때 `Response`객체인 `response.cookies`에 쿠키를 설정할 수 있습니다. 이 객체는 응답 헤더를 자동으로 작성하는 특별한 종류의 사전(dict)인 `CookieJar`의 인스턴스입니다. :--:1
```python
@app.route("/cookie")
async def test(request):
@@ -34,10 +28,9 @@ async def test(request):
response.cookies["test"]["httponly"] = True
return response
```
-
:---
-응답 쿠키는 사전 값과 같이 설정할 수 있으며 다음 매개변수들을 사용할 수 있습니다.:
+:--:1
- `expires: datetime` - 클라이언트의 브라우저에서 쿠키가 만료되는 시간입니다.
- `path: str` - 이 쿠키가 적용되는 URL의 하위 집합입니다. 기본값은 `/`입니다.
@@ -52,10 +45,7 @@ async def test(request):
---:1
-쿠키는 의미적으로 또는 명시적으로 제거할 수 있습니다.
-
-:--:1
-
+Cookies can be removed semantically or explicitly. :--:1
```python
@app.route("/cookie")
async def test(request):
@@ -76,9 +66,8 @@ async def test(request):
return response
```
-
:---
## 먹기(Eating)
-저는 쿠키를 좋아합니다 :cookie:
+쿠키는 의미적으로 또는 명시적으로 제거할 수 있습니다.
From c783077c8793d80301327017d5add4fe380512e6 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:42:55 +0300
Subject: [PATCH 002/776] New translations README.md (Chinese Simplified)
---
src/zh/guide/basics/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/zh/guide/basics/README.md b/src/zh/guide/basics/README.md
index 334cb2727a..76d1d5cf5a 100644
--- a/src/zh/guide/basics/README.md
+++ b/src/zh/guide/basics/README.md
@@ -1 +1 @@
-# 入门
\ No newline at end of file
+# 入门
From 59e12bc5d12fa4d9e6eee51d9442df02f44f71a2 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:42:55 +0300
Subject: [PATCH 003/776] New translations README.md (Portuguese, Brazilian)
---
src/pt/guide/basics/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/basics/README.md
diff --git a/src/pt/guide/basics/README.md b/src/pt/guide/basics/README.md
new file mode 100644
index 0000000000..25dcc52044
--- /dev/null
+++ b/src/pt/guide/basics/README.md
@@ -0,0 +1 @@
+# Basics
From 000d486beabaef5e395a6363b979d540e9b43d84 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:42:56 +0300
Subject: [PATCH 004/776] New translations app.md (Japanese)
---
src/ja/guide/basics/app.md | 60 +++++++++++++-------------------------
1 file changed, 21 insertions(+), 39 deletions(-)
diff --git a/src/ja/guide/basics/app.md b/src/ja/guide/basics/app.md
index 54fc47b61a..8230791a9f 100644
--- a/src/ja/guide/basics/app.md
+++ b/src/ja/guide/basics/app.md
@@ -2,9 +2,7 @@
## Instance
----:1
-最も基本的な構成要素は、`Sanic()`インスタンスです。これは必須ではありませんが、カスタムはこれを`server.py`というファイルでインスタンス化します。
-:--:1
+---:1 最も基本的な構成要素は、`Sanic()`インスタンスです。 これは必須ではありませんが、カスタムはこれを`server.py`というファイルでインスタンス化します。 :--:1 :--:1
```python
# /path/to/server.py
@@ -16,10 +14,9 @@ app = Sanic("My Hello, world app")
## Application context
-ほとんどのアプリケーションでは、コード・ベースのさまざまな部分でデータやオブジェクトを共有/再利用する必要があります。最も一般的な例はDB接続です。
----:1
-v21.3より前のバージョンのSanicでは、これは通常、属性をアプリケーションインスタンスにアタッチすることによって行われていました。
-:--:1
+ほとんどのアプリケーションでは、コード・ベースのさまざまな部分でデータやオブジェクトを共有/再利用する必要があります。 最も一般的な例はDB接続です。 ---:1 v21.3より前のバージョンのSanicでは、これは通常、属性をアプリケーションインスタンスにアタッチすることによって行われていました。 :--:1
+
+---:1 In versions of Sanic prior to v21.3, this was commonly done by attaching an attribute to the application instance :--:1
```python
# Raises a warning as deprecated feature in 21.3
app = Sanic("MyApp")
@@ -27,9 +24,7 @@ app.db = Database()
```
:---
----:1
-これにより、名前の競合に関する潜在的な問題が発生したり、[要求コンテキスト](./request.md#context)オブジェクトv 21.3では、アプリケーションレベルのコンテキストオブジェクトが導入されました。
-:--:1
+---:1 これにより、名前の競合に関する潜在的な問題が発生したり、[要求コンテキスト](./request.md#context)オブジェクトv 21.3では、アプリケーションレベルのコンテキストオブジェクトが導入されました。 :--:1 :--:1
```python
# Correct way to attach objects to the application
app = Sanic("MyApp")
@@ -40,8 +35,8 @@ app.ctx.db = Database()
## App Registry
---:1
-Sanicインスタンスをインスタンス化すると、後でSanicアプリケーションレジストリから取得できます。これは、他の方法ではアクセスできない場所からSanicインスタンスにアクセスする必要がある場合などに便利です。
-:--:1
+
+Sanicインスタンスをインスタンス化すると、後でSanicアプリケーションレジストリから取得できます。 これは、他の方法ではアクセスできない場所からSanicインスタンスにアクセスする必要がある場合などに便利です。 :--:1 :--:1
```python
# ./path/to/server.py
from sanic import Sanic
@@ -56,8 +51,8 @@ app = Sanic.get_app("my_awesome_server")
:---
---:1
-存在しないアプリケーションで`Sanic.get_app("non-existing")`を呼び出すと、デフォルトで`SanicException'が発生します。代わりに、その名前の新しいSanicインスタンスを返すようにメソッドに強制できます。
-:--:1
+
+---:1 存在しないアプリケーションで`Sanic.get_app("non-existing")`を呼び出すと、デフォルトで`SanicException'が発生します。 代わりに、その名前の新しいSanicインスタンスを返すようにメソッドに強制できます。 :--:1 :--:1
```python
app = Sanic.get_app(
"non-existing",
@@ -66,9 +61,7 @@ app = Sanic.get_app(
```
:---
----:1
-**Sanicインスタンスが1つしか登録されていない**場合、引数なしで`Sanic.get_app () `を呼び出すと、そのインスタンスが返されます。
-:--:1
+---:1 **Sanicインスタンスが1つしか登録されていない**場合、引数なしで`Sanic.get_app ()`を呼び出すと、そのインスタンスが返されます。 :--:1
```python
Sanic("My only app")
@@ -78,9 +71,7 @@ app = Sanic.get_app()
## Configuration
----:1
-Sanicは、Sanicインスタンスのconfig属性に設定を保持します。構成は、ドット表記を使用するか、辞書のように変更できます。
-:--:1
+---:1 Sanic holds the configuration in the `config` attribute of the `Sanic` instance. Configuration can be modified **either** using dot-notation **OR** like a dictionary. ---:1
```python
app = Sanic('myapp')
@@ -96,15 +87,13 @@ app.config.update(db_settings)
```
:---
-::: tip Heads up
-構成キーは大文字でなければなりません。しかし、これは主に規約によるもので、ほとんどの場合小文字で動作します。
+::: tip Heads up 構成キーは大文字でなければなりません。 しかし、これは主に規約によるもので、ほとんどの場合小文字で動作します。
```
-app.config.GOOD = "yay!"
-app.config.bad = "boo"
+app.config.GOOD = "yay!" app.config.bad = "boo"
```
:::
-[設定の詳細](/guide/deployment/configuration.md)については後で説明します。
+カスタム設定の最も単純な形式は、独自のオブジェクトを直接そのSanicアプリケーションインスタンスに渡すことです。
## Customization
@@ -114,9 +103,9 @@ Sanicアプリケーションインスタンスは、インスタンス化時に
### Custom configuration
---:1
-カスタム設定の最も単純な形式は、独自のオブジェクトを直接そのSanicアプリケーションインスタンスに渡すことです。
+This simplest form of custom configuration would be to pass your own object directly into that Sanic application instance
-カスタム設定オブジェクトを作成する場合は、Sanicの`Config`オプションをサブクラス化して、その動作を継承することを強くお勧めします。このオプションを使用して、プロパティを追加することも、独自のカスタムロジックセットを追加することもできます。
+カスタム設定オブジェクトを作成する場合は、Sanicの`Config`オプションをサブクラス化して、その動作を継承することを強くお勧めします。 このオプションを使用して、プロパティを追加することも、独自のカスタムロジックセットを追加することもできます。
:--:1
```python
@@ -129,10 +118,7 @@ app = Sanic(..., config=MyConfig())
```
:---
----:1
-
-この機能の有用な例は、 [supported](../deployment/configuration.md#using-sanic-update-config)とは異なる形式の設定ファイルを使用する場合です。
-:--:1
+この機能の有用な例は、 [supported](../deployment/configuration.md#using-sanic-update-config)とは異なる形式の設定ファイルを使用する場合です。 :--:1 ---:1
```python
from sanic import Sanic, text
from sanic.config import Config
@@ -168,7 +154,7 @@ app = Sanic(toml_config.APP_NAME, config=toml_config)
### Custom context
---:1
-デフォルトでは、アプリケーション・コンテキストは [`SimpleNamespace()`](https://docs.python.org/3/library/types.html#types.SimpleNamespace) であり、必要なプロパティを設定できます。ただし、代わりに任意のオブジェクトを渡すこともできます。
+デフォルトでは、アプリケーション・コンテキストは [`SimpleNamespace()`](https://docs.python.org/3/library/types.html#types.SimpleNamespace) であり、必要なプロパティを設定できます。 ただし、代わりに任意のオブジェクトを渡すこともできます。
:--:1
```python
@@ -187,15 +173,13 @@ app = Sanic(..., ctx=MyContext())
```
:---
### Custom requests
----:1
-独自の 「Request」 クラスを用意し、デフォルトの代わりにそれを使用するようにSanicに指示すると便利な場合があります。たとえば、デフォルトの`request.id`ジェネレータを変更する場合です。
+---:1 独自の 「Request」 クラスを用意し、デフォルトの代わりにそれを使用するようにSanicに指示すると便利な場合があります。 たとえば、デフォルトの`request.id`ジェネレータを変更する場合です。
::: tip Important
クラスのインスタンスではなく、*クラス*を渡すことを覚えておくことが重要です。
-:::
-:--:1
+::: :--:1
```python
import time
@@ -219,9 +203,7 @@ async def handler(request):
### Custom error handler
----:1
-詳細については、[exception handling](../best-practices/exceptions.md#custom-error-handling)を参照してください。
-:--:1
+---:1 詳細については、[exception handling](../best-practices/exceptions.md#custom-error-handling)を参照してください。 :--:1
```python
from sanic.handlers import ErrorHandler
From 04f4c5150fc95cdeb732bdd6e3530565850391a5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:42:57 +0300
Subject: [PATCH 005/776] New translations app.md (Korean)
---
src/ko/guide/basics/app.md | 83 +++++++++-----------------------------
1 file changed, 19 insertions(+), 64 deletions(-)
diff --git a/src/ko/guide/basics/app.md b/src/ko/guide/basics/app.md
index 84fddd4d9a..bb7f8fcddf 100644
--- a/src/ko/guide/basics/app.md
+++ b/src/ko/guide/basics/app.md
@@ -2,10 +2,7 @@
## 인스턴스(Instance)
----:1
-가장 기본적인 구성 요소는 `Sanic()` 인스턴스입니다. 꼭 필요한 것은 아니지만 `server.py`라는 파일에서 이를 인스턴스화하는 것이 암묵적인 규칙입니다.
-:--:1
-
+---:1 가장 기본적인 구성 요소는 `Sanic()` 인스턴스입니다. 꼭 필요한 것은 아니지만 `server.py`라는 파일에서 이를 인스턴스화하는 것이 암묵적인 규칙입니다. :--:1
```python
# /path/to/server.py
@@ -13,45 +10,31 @@ from sanic import Sanic
app = Sanic("My Hello, world app")
```
-
:---
## 애플리케이션 컨텍스트(Application context)
대부분의 애플리케이션은 코드베이스의 여러 부분에서 데이터 또는 객체를 공유/재사용할 것입니다. 가장 흔한 예로는 DB 연결이 있겠네요.
----:1
-v21.3 이전의 Sanic 버전에서는 일반적으로 애플리케이션 인스턴스에 속성을 추가하는 방식을 사용했습니다.
-:--:1
-
+---:1 In versions of Sanic prior to v21.3, this was commonly done by attaching an attribute to the application instance :--:1
```python
-# 21.3에서는 사용하지 않는 기능으로 경고를 발생시킵니다.
-app = Sanic("MyApp")
+# 21.3에서는 사용하지 않는 기능으로 경고를 발생시킵니다. app = Sanic("MyApp")
app.db = Database()
```
-
:---
----:1
-하지만 이로 인해 이름 충돌 등의 잠재적인 문제가 발생할 수 있고 [요청 컨텍스트](./request.md#context)객체와 일관성을 유지하기 위해 v21.3에서는 응용 프로그램 수준 컨텍스트 객체를 도입했습니다.
-:--:1
-
+---:1 하지만 이로 인해 이름 충돌 등의 잠재적인 문제가 발생할 수 있고 [요청 컨텍스트](./request.md#context)객체와 일관성을 유지하기 위해 v21.3에서는 응용 프로그램 수준 컨텍스트 객체를 도입했습니다. :--:1
```python
-
-# 객체를 응용프로그램에 추가하는 올바른 방법입니다.
-app = Sanic("MyApp")
+# 객체를 응용프로그램에 추가하는 올바른 방법입니다. app = Sanic("MyApp")
app.ctx.db = Database()
```
-
:---
## 앱 레지스트리(App Registry)
---:1
-Sanic 인스턴스를 인스턴스화하면 Sanic 앱 레지스트리에서 나중에 검색할 수 있습니다. 이 기능은 달리 액세스할 수 없는 위치에서 Sanic 인스턴스에 액세스해야 하는 경우 등에서 유용할 것입니다.
-:--:1
-
+Sanic 인스턴스를 인스턴스화하면 Sanic 앱 레지스트리에서 나중에 검색할 수 있습니다. 이 기능은 달리 액세스할 수 없는 위치에서 Sanic 인스턴스에 액세스해야 하는 경우 등에서 유용할 것입니다. :--:1
```python
# ./path/to/server.py
from sanic import Sanic
@@ -63,44 +46,30 @@ from sanic import Sanic
app = Sanic.get_app("my_awesome_server")
```
-
:---
---:1
-존재하지 않는 앱에서 `Sanic.get_app'("non-existing")`을 호출하면 기본적으로 `SanicException`이 발생합니다. 대신 메소드가 해당 이름의 새 Sanic 인스턴스를 반환하도록 강제할 수 있습니다.
-:--:1
-
+존재하지 않는 앱에서 `Sanic.get_app'("non-existing")`을 호출하면 기본적으로 `SanicException`이 발생합니다. 대신 메소드가 해당 이름의 새 Sanic 인스턴스를 반환하도록 강제할 수 있습니다. :--:1
```python
app = Sanic.get_app(
"non-existing",
force_create=True,
)
```
-
:---
----:1
-등록된 Sanic 인스턴스가 **하나만** 있는 경우 인수 없이 `Sanic.get_app()`을 호출하면 해당 인스턴스가 반환됩니다.
-:--:1
-
+---:1 등록된 Sanic 인스턴스가 **하나만** 있는 경우 인수 없이 `Sanic.get_app()`을 호출하면 해당 인스턴스가 반환됩니다. :--:1
```python
Sanic("My only app")
app = Sanic.get_app()
```
-
:---
## 구성(Configuration)
----:1
-
-Sanic은 `Sanic` 인스턴스의 `config` 속성에 구성을 보유합니다.
-구성은 **속성** 또는 **딕셔너리** 를 사용하여 구성을 수정할 수 있습니다.
-
-:--:1
-
+Sanic은 `Sanic` 인스턴스의 `config` 속성에 구성을 보유합니다. 구성은 **속성** 또는 **딕셔너리** 를 사용하여 구성을 수정할 수 있습니다. :--:1
```python
app = Sanic('myapp')
@@ -114,30 +83,25 @@ db_settings = {
}
app.config.update(db_settings)
```
-
:---
-::: tip 주의 사항
-구성 키는 _대문자_ 여야 합니다. 하지만 이건 거의 암묵적인 규칙일 뿐이며 소문자도 대부분의 경우에는 잘 작동할 것입니다.
-
-```py
-app.config.GOOD = "yay!"
-app.config.bad = "boo"
+::: tip 주의 사항 구성 키는 _대문자_ 여야 합니다. 하지만 이건 거의 암묵적인 규칙일 뿐이며 소문자도 대부분의 경우에는 잘 작동할 것입니다.
+```
+app.config.GOOD = "yay!" app.config.bad = "boo"
```
-
:::
나중에 [구성에 대한 자세한 내용](/guide/deployment/configuration.md)에서 자세히 소개됩니다.
+
## 커스터마이징(Customization)
-Sanic 애플리케이션 인스턴스는 인스턴스화 할 경우 다양한 방식으로 애플리케이션 요구사항에 맞게 사용자 정의할 수 있습니다.
+The Sanic application instance can be customized for your application needs in a variety of ways at instantiation.
### 사용자 정의 구성(Custom configuration)
-
---:1
-이 가장 간단한 형태의 사용자 지정 구성은 Sanic 응용 프로그램 인스턴스에 직접 객체를 전달하는 것입니다.
+Sanic 애플리케이션 인스턴스는 인스턴스화 할 경우 다양한 방식으로 애플리케이션 요구사항에 맞게 사용자 정의할 수 있습니다.
사용자 지정 구성 객체를 생성하는 경우 Sanic `Config` 옵션을 하위 클래스로 지정하여 해당 동작을 상속하는 것이 *매우* 권장됩니다. 속성을 추가하거나 고유한 사용자 정의 로직을 추가하는 데 이 옵션을 사용할 수 있습니다.
@@ -152,9 +116,7 @@ app = Sanic(..., config=MyConfig())
```
:---
----:1
-이 기능의 유용한 예는 [지원하는](../deployment/configuration.md#using-sanic-update-config)다른 형식으로 구성 파일을 사용하려는 경우입니다.
-:--:1
+---:1 이 기능의 유용한 예는 [지원하는](../deployment/configuration.md#using-sanic-update-config)다른 형식으로 구성 파일을 사용하려는 경우입니다. :--:1
```python
from sanic import Sanic, text
from sanic.config import Config
@@ -208,18 +170,14 @@ class MyContext:
app = Sanic(..., ctx=MyContext())
```
:---
-
### 사용자 정의 요청(Custom requests)
-
----:1
-때로는 자신만의 `Request` 클래스를 갖고 Sanic에게 기본값 대신 사용하도록 지시하는 것이 도움이 됩니다. 한 가지 예는 기본 `request.id` 생성기를 수정하려는 경우입니다.
+---:1 때로는 자신만의 `Request` 클래스를 갖고 Sanic에게 기본값 대신 사용하도록 지시하는 것이 도움이 됩니다. 한 가지 예는 기본 `request.id` 생성기를 수정하려는 경우입니다.
::: tip 중요
클래스의 인스턴스가 아닌 *class*를 전달한다는 것을 기억하는 것이 중요합니다.
-:::
-:--:1
+::: :--:1
```python
import time
@@ -243,9 +201,7 @@ async def handler(request):
### 사용자 정의 에러 핸들러(Custom error handler)
----:1
-자세한 내용은 [exception handling](../best-practices/exceptions.md#custom-error-handling)를 참조하세요.
-:--:1
+---:1 자세한 내용은 [exception handling](../best-practices/exceptions.md#custom-error-handling)를 참조하세요. :--:1
```python
from sanic.handlers import ErrorHandler
@@ -258,4 +214,3 @@ class CustomErrorHandler(ErrorHandler):
app = Sanic(..., error_handler=CustomErrorHandler())
```
:---
-
From 0a630607e540a2bb0652afd17604baa75de96ef3 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:42:58 +0300
Subject: [PATCH 006/776] New translations app.md (Chinese Simplified)
---
src/zh/guide/basics/app.md | 113 ++++++++-----------------------------
1 file changed, 24 insertions(+), 89 deletions(-)
diff --git a/src/zh/guide/basics/app.md b/src/zh/guide/basics/app.md
index fd72cf8fda..d1dbb6b2f1 100644
--- a/src/zh/guide/basics/app.md
+++ b/src/zh/guide/basics/app.md
@@ -2,63 +2,41 @@
## 实例(Instance)
----:1
-
-`Sanic()` 是最基础的组成部分,通常我们会在一个名为 `server.py` 的文件中将其实例化,当然文件名称并不是必须的, 但是我们还是推荐使用 `server.py` 做为文件名称来实例化 Sanic 对象。
-
-:--:1
-
+---:1 The most basic building block is the `Sanic()` instance. `Sanic()` 是最基础的组成部分,通常我们会在一个名为 `server.py` 的文件中将其实例化,当然文件名称并不是必须的, 但是我们还是推荐使用 `server.py` 做为文件名称来实例化 Sanic 对象。 :--:1
```python
# /path/to/server.py
from sanic import Sanic
app = Sanic("My Hello, world app")
-
```
-
:---
## 应用上下文(Application context)
-大多数应用程序都需要跨代码库的不同部分共享/重用数据或对象。最常见的例子是数据库连接。
-
----:1
+大多数应用程序都需要跨代码库的不同部分共享/重用数据或对象。 最常见的例子是数据库连接。
在 21.3 版之前的 Sanic 版本中,这通常是通过将属性附加到应用程序上来实现的。
-
-:--:1
-
```python
# Raises a warning as deprecated feature in 21.3
app = Sanic("MyApp")
app.db = Database()
```
-
:---
----:1
-
-在 v21.3 版本中,我们引入了应用级的上下文对象,且使用方法与 [请求上下文](./request.md#context) 一致, 这有效的避免了命名冲突可能导致的潜在问题。
-
-:--:1
-
+在 v21.3 版本中,我们引入了应用级的上下文对象,且使用方法与 [请求上下文](./request.md#context) 一致, 这有效的避免了命名冲突可能导致的潜在问题。 :--:1
```python
# Correct way to attach objects to the application
app = Sanic("MyApp")
app.ctx.db = Database()
```
-
:---
## App 注册表(App Registry)
---:1
-当您实例化一个 Sanic 对象之后, 您就可以随时通过 Sanic 注册表来获取该对象了,尤其是当您在无法通过其他方式来获取 Sanic 对象的时候, 这种方式将对您有非常大的帮助。
-
-:--:1
-
+When you instantiate a Sanic instance, that can be retrieved at a later time from the Sanic app registry. This can be useful, for example, if you need to access your Sanic instance from a location where it is not otherwise accessible. :--:1
```python
# ./path/to/server.py
from sanic import Sanic
@@ -70,47 +48,30 @@ from sanic import Sanic
app = Sanic.get_app("my_awesome_server")
```
-
:---
---:1
-如果您希望使用 `Sanic.get_app("non-existing")` 来获取不存在的 Sanic 对象, 您应该通过添加 `force_create` 参数,此参数意味着如果要获取的 Sanic 对象不存在,则主动创建一个同名的
-Sanic 对象并返回。如果不设置该参数,那么默认情况下将会抛出 `SanicException` 异常。
-
-:--:1
-
+如果您希望使用 `Sanic.get_app("non-existing")` 来获取不存在的 Sanic 对象, 您应该通过添加 `force_create` 参数,此参数意味着如果要获取的 Sanic 对象不存在,则主动创建一个同名的 Sanic 对象并返回。 如果不设置该参数,那么默认情况下将会抛出 `SanicException` 异常。 You can, instead, force the method to return a new instance of Sanic with that name. :--:1
```python
app = Sanic.get_app(
"non-existing",
force_create=True,
)
```
-
:---
----:1
-
-如果 **只有一个** Sanic 实例被注册了,那么调用 `Sanic.get_app()` 时如果不传入任何参数则将返回该实例。
-
-:--:1
-
+---:1 If there is **only one** Sanic instance registered, then calling `Sanic.get_app()` with no arguments will return that instance :--:1
```python
Sanic("My only app")
app = Sanic.get_app()
```
-
:---
## 配置(Configuration)
----:1
-
-Sanic 将配置保存在 Sanic 对象的 `config` 属性中。可以使用 **属性操作** 或 **字典操作** 的方式来修改配置。
-
-:--:1
-
+Sanic 将配置保存在 Sanic 对象的 `config` 属性中。 可以使用 **属性操作** 或 **字典操作** 的方式来修改配置。 :--:1
```python
app = Sanic('myapp')
@@ -124,36 +85,30 @@ db_settings = {
}
app.config.update(db_settings)
```
-
:---
-::: tip 小提示:
-
-按照惯例,配置中的键名都需要完全大写,但是多数情况下小写也会起作用,不过我们仍旧建议您使用大写作为配置的键名。
-
+::: tip Heads up Config keys _should_ be uppercase. But, this is mainly by convention, and lowercase will work most of the time.
```
app.config.GOOD = "yay!"
app.config.bad = "boo"
```
-
:::
之后还有更多关于 [配置](/zh/guide/deployment/configuration.md) 的细节。
+
## 自定义(Customization)
-Sanic 应用在实例化时可以根据您的需求以多种方式进行定制。
+The Sanic application instance can be customized for your application needs in a variety of ways at instantiation.
### 自定义配置(Custom configuration)
-
---:1
-自定义配置最简单的方式,就是将您自己的配置对象直接传递到 Sanic 实例中
+如果 **只有一个** Sanic 实例被注册了,那么调用 `Sanic.get_app()` 时如果不传入任何参数则将返回该实例。
-如果您使用了自定义配置对象类,*强烈建议* 您将自定义类继承 Sanic 的 `Config` 类,以保持与父类行为一致。这样,您就可以调用父类方法来添加属性。当然,您也可以自己实现一套类似的逻辑。
+如果您使用了自定义配置对象类,*强烈建议* 您将自定义类继承 Sanic 的 `Config` 类,以保持与父类行为一致。 You could use this option for adding properties, or your own set of custom logic.
:--:1
-
```python
from sanic.config import Config
@@ -164,15 +119,9 @@ class MyConfig(Config):
app = Sanic(..., config=MyConfig())
```
-
:---
----:1
-
-如果您想使用一个与[通用配置](../deployment/configuration.md#使用通用方法加载-using-sanic-update-config)格式不一样的配置文件时会比较有用。
-
-:--:1
-
+如果您想使用一个与[通用配置](../deployment/configuration.md#使用通用方法加载-using-sanic-update-config)格式不一样的配置文件时会比较有用。 :--:1
```python
from sanic import Sanic, text
from sanic.config import Config
@@ -206,18 +155,13 @@ class TomlConfig(Config):
toml_config = TomlConfig(path="/path/to/config.toml")
app = Sanic(toml_config.APP_NAME, config=toml_config)
```
-
:---
-
### 自定义上下文(Custom context)
-
---:1
-在默认情况下,应用程序上下文是一个 [`SimpleNamespace`](https://docs.python.org/3/library/types.html#types.SimpleNamespace)
-实例,它允许您在上面设置任何您想要的属性。然而,您也可以选择使用其他对象来代替。
+在默认情况下,应用程序上下文是一个 [`SimpleNamespace`](https://docs.python.org/3/library/types.html#types.SimpleNamespace) 实例,它允许您在上面设置任何您想要的属性。 然而,您也可以选择使用其他对象来代替。
:--:1
-
```python
app = Sanic(..., ctx=1)
```
@@ -230,26 +174,21 @@ app = Sanic(..., ctx={})
class MyContext:
...
+class MyContext:
+ ...
+
app = Sanic(..., ctx=MyContext())
```
-
:---
-
### 自定义请求(Custom requests)
+有时,自定义一个 `Request` 类显得很重要。 举一个简单的例子,设置自定义的 `request.id` 属性。
----:1
-
-有时,自定义一个 `Request` 类显得很重要。举一个简单的例子,设置自定义的 `request.id` 属性。
-
-::: tip 重要
+Sanic 应用在实例化时可以根据您的需求以多种方式进行定制。
记住,您应该传入 *类* 对象作为参数,而不是该类的实例。
-:::
-
-:--:1
-
+自定义配置最简单的方式,就是将您自己的配置对象直接传递到 Sanic 实例中
```python
import time
@@ -269,17 +208,11 @@ app = Sanic(..., request_class=NanoSecondRequest)
async def handler(request):
return text(str(request.id))
```
-
:---
### 自定义错误响应函数(Custom error handler)
----:1
-
详见 [exception handling](../best-practices/exceptions.md#自定义异常处理-custom-error-handling)
-
-:--:1
-
```python
from sanic.handlers import ErrorHandler
@@ -292,6 +225,8 @@ class CustomErrorHandler(ErrorHandler):
app = Sanic(..., error_handler=CustomErrorHandler())
-```
+ return super().default(request, exception)
-:---
\ No newline at end of file
+app = Sanic(..., error_handler=CustomErrorHandler())
+```
+:---
From 94577b94a435cb5232512478e67de787944e567e Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:42:59 +0300
Subject: [PATCH 007/776] New translations app.md (Portuguese, Brazilian)
---
src/pt/guide/basics/app.md | 219 +++++++++++++++++++++++++++++++++++++
1 file changed, 219 insertions(+)
create mode 100644 src/pt/guide/basics/app.md
diff --git a/src/pt/guide/basics/app.md b/src/pt/guide/basics/app.md
new file mode 100644
index 0000000000..9936bc8632
--- /dev/null
+++ b/src/pt/guide/basics/app.md
@@ -0,0 +1,219 @@
+# Sanic Application
+
+## Instance
+
+---:1 The most basic building block is the `Sanic()` instance. It is not required, but the custom is to instantiate this in a file called `server.py`. :--:1
+```python
+# /path/to/server.py
+
+from sanic import Sanic
+
+app = Sanic("MyHelloWorldApp")
+```
+:---
+
+## Application context
+
+Most applications will have the need to share/reuse data or objects across different parts of the code base. The most common example is DB connections.
+
+---:1 In versions of Sanic prior to v21.3, this was commonly done by attaching an attribute to the application instance :--:1
+```python
+# Raises a warning as deprecated feature in 21.3
+app = Sanic("MyApp")
+app.db = Database()
+```
+:---
+
+---:1 Because this can create potential problems with name conflicts, and to be consistent with [request context](./request.md#context) objects, v21.3 introduces application level context object. :--:1
+```python
+# Correct way to attach objects to the application
+app = Sanic("MyApp")
+app.ctx.db = Database()
+```
+:---
+
+## App Registry
+
+---:1
+
+When you instantiate a Sanic instance, that can be retrieved at a later time from the Sanic app registry. This can be useful, for example, if you need to access your Sanic instance from a location where it is not otherwise accessible. :--:1
+```python
+# ./path/to/server.py
+from sanic import Sanic
+
+app = Sanic("my_awesome_server")
+
+# ./path/to/somewhere_else.py
+from sanic import Sanic
+
+app = Sanic.get_app("my_awesome_server")
+```
+:---
+
+---:1
+
+If you call `Sanic.get_app("non-existing")` on an app that does not exist, it will raise `SanicException` by default. You can, instead, force the method to return a new instance of Sanic with that name. :--:1
+```python
+app = Sanic.get_app(
+ "non-existing",
+ force_create=True,
+)
+```
+:---
+
+---:1 If there is **only one** Sanic instance registered, then calling `Sanic.get_app()` with no arguments will return that instance :--:1
+```python
+Sanic("My only app")
+
+app = Sanic.get_app()
+```
+:---
+
+## Configuration
+
+---:1 Sanic holds the configuration in the `config` attribute of the `Sanic` instance. Configuration can be modified **either** using dot-notation **OR** like a dictionary. :--:1
+```python
+app = Sanic('myapp')
+
+app.config.DB_NAME = 'appdb'
+app.config['DB_USER'] = 'appuser'
+
+db_settings = {
+ 'DB_HOST': 'localhost',
+ 'DB_NAME': 'appdb',
+ 'DB_USER': 'appuser'
+}
+app.config.update(db_settings)
+```
+:---
+
+::: tip Heads up Config keys _should_ be uppercase. But, this is mainly by convention, and lowercase will work most of the time.
+```
+app.config.GOOD = "yay!"
+app.config.bad = "boo"
+```
+:::
+
+There is much [more detail about configuration](/guide/deployment/configuration.md) later on.
+
+
+## Customization
+
+The Sanic application instance can be customized for your application needs in a variety of ways at instantiation.
+
+### Custom configuration
+---:1
+
+This simplest form of custom configuration would be to pass your own object directly into that Sanic application instance
+
+If you create a custom configuration object, it is *highly* recommended that you subclass the Sanic `Config` option to inherit its behavior. You could use this option for adding properties, or your own set of custom logic.
+
+:--:1
+```python
+from sanic.config import Config
+
+class MyConfig(Config):
+ FOO = "bar"
+
+app = Sanic(..., config=MyConfig())
+```
+:---
+
+---:1 A useful example of this feature would be if you wanted to use a config file in a form that differs from what is [supported](../deployment/configuration.md#using-sanic-update-config). :--:1
+```python
+from sanic import Sanic, text
+from sanic.config import Config
+
+class TomlConfig(Config):
+ def __init__(self, *args, path: str, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ with open(path, "r") as f:
+ self.apply(toml.load(f))
+
+ def apply(self, config):
+ self.update(self._to_uppercase(config))
+
+ def _to_uppercase(self, obj: Dict[str, Any]) -> Dict[str, Any]:
+ retval: Dict[str, Any] = {}
+ for key, value in obj.items():
+ upper_key = key.upper()
+ if isinstance(value, list):
+ retval[upper_key] = [
+ self._to_uppercase(item) for item in value
+ ]
+ elif isinstance(value, dict):
+ retval[upper_key] = self._to_uppercase(value)
+ else:
+ retval[upper_key] = value
+ return retval
+
+toml_config = TomlConfig(path="/path/to/config.toml")
+app = Sanic(toml_config.APP_NAME, config=toml_config)
+```
+:---
+### Custom context
+---:1
+
+By default, the application context is a [`SimpleNamespace()`](https://docs.python.org/3/library/types.html#types.SimpleNamespace) that allows you to set any properties you want on it. However, you also have the option of passing any object whatsoever instead.
+
+:--:1
+```python
+app = Sanic(..., ctx=1)
+```
+
+```python
+app = Sanic(..., ctx={})
+```
+
+```python
+class MyContext:
+ ...
+
+app = Sanic(..., ctx=MyContext())
+```
+:---
+### Custom requests
+---:1 It is sometimes helpful to have your own `Request` class, and tell Sanic to use that instead of the default. One example is if you wanted to modify the default `request.id` generator.
+
+::: tip Important
+
+It is important to remember that you are passing the *class* not an instance of the class.
+
+::: :--:1
+```python
+import time
+
+from sanic import Request, Sanic, text
+
+
+class NanoSecondRequest(Request):
+ @classmethod
+ def generate_id(*_):
+ return time.time_ns()
+
+
+app = Sanic(..., request_class=NanoSecondRequest)
+
+
+@app.get("/")
+async def handler(request):
+ return text(str(request.id))
+```
+:---
+
+### Custom error handler
+
+---:1 See [exception handling](../best-practices/exceptions.md#custom-error-handling) for more :--:1
+```python
+from sanic.handlers import ErrorHandler
+
+class CustomErrorHandler(ErrorHandler):
+ def default(self, request, exception):
+ ''' handles errors that have no error handlers assigned '''
+ # You custom error handling logic...
+ return super().default(request, exception)
+
+app = Sanic(..., error_handler=CustomErrorHandler())
+```
+:---
From 6e84041aabf768b8302975f1a08e4062c502f385 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:01 +0300
Subject: [PATCH 008/776] New translations cookies.md (Japanese)
---
src/ja/guide/basics/cookies.md | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/src/ja/guide/basics/cookies.md b/src/ja/guide/basics/cookies.md
index 7350a88b4a..92de792eb1 100644
--- a/src/ja/guide/basics/cookies.md
+++ b/src/ja/guide/basics/cookies.md
@@ -4,8 +4,7 @@
---:1
-クッキーは、`Request`オブジェクトの`cookies`辞書を介してアクセスできます。
-:--:1
+クッキーは、`Request`オブジェクトの`cookies`辞書を介してアクセスできます。 :--:1 :--:1
```python
@app.route("/cookie")
async def test(request):
@@ -19,8 +18,7 @@ async def test(request):
---:1
-応答を返すとき、クッキーは`Response`オブジェクトに設定できます: `response.cookies`。このオブジェクトは、応答ヘッダーを自動的に書き込む特別な種類の辞書である「CookieJar」のインスタンスです。
-:--:1
+応答を返すとき、クッキーは`Response`オブジェクトに設定できます: `response.cookies`。 このオブジェクトは、応答ヘッダーを自動的に書き込む特別な種類の辞書である「CookieJar」のインスタンスです。 :--:1 :--:1
```python
@app.route("/cookie")
async def test(request):
@@ -35,9 +33,9 @@ async def test(request):
応答クッキーは辞書の値のように設定でき、次のパラメータを使用できます。
- `expires: datetime` - クライアントのブラウザでクッキーが期限切れになる時間。
-- `path: str` - このクッキーが適用されるURLのサブセット。デフォルトは `/` です。
+- `path: str` - このクッキーが適用されるURLのサブセット。 デフォルトは `/` です。
- `comment: str` - コメント(メタデータ)。
-- `domain: str` - クッキーが有効なドメインを指定します。明示的に指定されたドメインは常にドットで始まる必要があります。
+- `domain: str` - クッキーが有効なドメインを指定します。 明示的に指定されたドメインは常にドットで始まる必要があります。
- `max-age: int` - クッキーが存息する秒数。
- `secure: bool` - クッキーがHTTPS経由でのみ送信されるかどうかを指定します。
- `httponly: bool` - クッキーをJavaScriptで読み取ることができないかどうかを指定します。
@@ -47,8 +45,7 @@ async def test(request):
---:1
-クッキーは意味的または明示的に削除できます。
-:--:1
+クッキーは意味的または明示的に削除できます。 :--:1 :--:1
```python
@app.route("/cookie")
async def test(request):
From 84590d9ebc8352b1f1ba8abb9ff96525a6231af0 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:02 +0300
Subject: [PATCH 009/776] New translations cookies.md (Chinese Simplified)
---
src/zh/guide/basics/cookies.md | 49 +++++++++++++---------------------
1 file changed, 19 insertions(+), 30 deletions(-)
diff --git a/src/zh/guide/basics/cookies.md b/src/zh/guide/basics/cookies.md
index 8b11ab4d78..50afa1f26d 100644
--- a/src/zh/guide/basics/cookies.md
+++ b/src/zh/guide/basics/cookies.md
@@ -4,28 +4,21 @@
---:1
-您可以通过 `Request` 对象的 `cookies` 字典来访问 Cookies。
-
-:--:1
-
+Cookies can be accessed via the `Request` object’s `cookies` dictionary. :--:1
```python
@app.route("/cookie")
async def test(request):
test_cookie = request.cookies.get("test")
return text("Test cookie: {}".format(test_cookie))
```
-
:---
+
## 写入(Writing)
---:1
-返回 response 的时候, 您可以通过 `Response` 对象的 `response.cookies` 来设置 cookies,它是一个 `CookieJar`
-对象,这是一种特殊的字典类型,能够帮助您自动编写响应头。
-
-:--:1
-
+When returning a response, cookies can be set on the `Response` object: `response.cookies`. 返回 response 的时候, 您可以通过 `Response` 对象的 `response.cookies` 来设置 cookies,它是一个 `CookieJar` 对象,这是一种特殊的字典类型,能够帮助您自动编写响应头。 :--:1
```python
@app.route("/cookie")
async def test(request):
@@ -34,31 +27,28 @@ async def test(request):
response.cookies["test"]["domain"] = ".yummy-yummy-cookie.com"
response.cookies["test"]["httponly"] = True
return response
+ response.cookies["test"]["domain"] = ".yummy-yummy-cookie.com"
+ response.cookies["test"]["httponly"] = True
+ return response
```
-
:---
-response 的 cookies 可以通过和字典类型一样的操作方法来进行设置,而且它可以使用以下参数:
+:--:1
-| 参数名称 | 参数类型 | 参数说明 |
-| :------: | :------: | :------------------------------------------------------: |
-| expires | datetime | Cookie 在客户端浏览器上失效的时间。 |
-| path | str | 此 Cookie 适用的 URL 子集。默认值为 `/` |
-| comment | str | 注释(元数据) |
-| domain | str | 指定 Cookie 的有效域。显式指定的域必须始终以点开始。 |
-| max-age | int | Cookie 应生存的秒数。 |
-| secure | bool | 指定是否仅通过 HTTPS 发送 Cookie。 |
-| httponly | bool | 指定 Javascript 是否无法读取 Cookie。 | |
-| samesite | str | 默认值取决于浏览器,规范状态(Lax、Strict 和 None)是有效值。|
+- Cookie 在客户端浏览器上失效的时间。
+- 此 Cookie 适用的 URL 子集。 默认值为 `/`
+- `comment: str` - A comment (metadata).
+- 指定 Cookie 的有效域。 显式指定的域必须始终以点开始。
+- Cookie 应生存的秒数。
+- 指定是否仅通过 HTTPS 发送 Cookie。
+- 您可以通过 `Request` 对象的 `cookies` 字典来访问 Cookies。
+- 默认值取决于浏览器,规范状态(Lax、Strict 和 None)是有效值。
## 删除(Deleting)
---:1
-您可以通过语义设置或对 Cookies 进行显示操作来达到删除的效果。
-
-:--:1
-
+Cookies can be removed semantically or explicitly. :--:1
```python
@app.route("/cookie")
async def test(request):
@@ -70,20 +60,19 @@ async def test(request):
# 此 cookie 将在 5 秒后删除
response.cookies["short_life"] = "Glad to be here"
response.cookies["short_life"]["max-age"] = 5
-
+
del response.cookies["favorite_color"]
# 此 cookie 将保持不变
response.cookies["favorite_color"] = "blue"
response.cookies["favorite_color"] = "pink"
-
+
del response.cookies["favorite_color"]
return response
```
-
:---
## 食用(Eating)
-我喜欢饼干!:cookie:
+您可以通过语义设置或对 Cookies 进行显示操作来达到删除的效果。
From 8edecef0c8365abeb09195836b69dbe25c4ab97c Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:03 +0300
Subject: [PATCH 010/776] New translations websockets.md (Chinese Simplified)
---
src/zh/guide/advanced/websockets.md | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/src/zh/guide/advanced/websockets.md b/src/zh/guide/advanced/websockets.md
index 84c8734cc7..d502ef844c 100644
--- a/src/zh/guide/advanced/websockets.md
+++ b/src/zh/guide/advanced/websockets.md
@@ -2,42 +2,37 @@
Sanic 提供了操作一个易操作的 [websockets](https://websockets.readthedocs.io/en/stable/) 封装。
+
## 定义路由(Routing)
---:1
-定义 Websocket 的路由和定义普通的路由相似。
-
-:--:1
-
+Websocket handlers can be hooked up to the router similar to regular handlers. :--:1
```python
async def feed(request, ws):
pass
app.add_websocket_route(feed, "/feed")
```
-
```python
@app.websocket("/feed")
async def feed(request, ws):
pass
```
-
:---
## 定义响应函数(Handler)
----:1
-
-通常的,一个 websocket 的响应函数将会打开并维持一个通讯循环。
-然后,可以调用传入函数的第二个参数对象的 `send()` 和 `recv()` 方法来处理业务。
+---:1
-下面这个例子定义了一个简单的 websocket 路由,它将客户端发送的信息再发送回去。
+Typically, a websocket handler will want to hold open a loop.
-:--:1
+通常的,一个 websocket 的响应函数将会打开并维持一个通讯循环。
+下面这个例子定义了一个简单的 websocket 路由,它将客户端发送的信息再发送回去。 :--:1
```python
+
@app.websocket("/feed")
async def feed(request, ws):
while True:
@@ -46,14 +41,15 @@ async def feed(request, ws):
await ws.send(data)
data = await ws.recv()
print("Received: " + data)
+ print("Sending: " + data)
+ await ws.send(data)
+ data = await ws.recv()
+ print("Received: " + data)
```
-
:---
-
## 配置(Configuration)
-更多细节请看 [配置](/zh/guide/deployment/configuration.md) 章节。
-
+:--:1
```python
app.config.WEBSOCKET_MAX_SIZE = 2 ** 20
app.config.WEBSOCKET_MAX_QUEUE = 32
From 934620d277a3c68eb95bc604c1c153bb96c1169f Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:04 +0300
Subject: [PATCH 011/776] New translations cookies.md (Portuguese, Brazilian)
---
src/pt/guide/basics/cookies.md | 73 ++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
create mode 100644 src/pt/guide/basics/cookies.md
diff --git a/src/pt/guide/basics/cookies.md b/src/pt/guide/basics/cookies.md
new file mode 100644
index 0000000000..851ee2f6d8
--- /dev/null
+++ b/src/pt/guide/basics/cookies.md
@@ -0,0 +1,73 @@
+# Cookies
+
+## Reading
+
+---:1
+
+Cookies can be accessed via the `Request` object’s `cookies` dictionary. :--:1
+```python
+@app.route("/cookie")
+async def test(request):
+ test_cookie = request.cookies.get("test")
+ return text("Test cookie: {}".format(test_cookie))
+```
+:---
+
+
+## Writing
+
+---:1
+
+When returning a response, cookies can be set on the `Response` object: `response.cookies`. This object is an instance of `CookieJar` which is a special sort of dictionary that automatically will write the response headers for you. :--:1
+```python
+@app.route("/cookie")
+async def test(request):
+ response = text("There's a cookie up in this response")
+ response.cookies["test"] = "It worked!"
+ response.cookies["test"]["domain"] = ".yummy-yummy-cookie.com"
+ response.cookies["test"]["httponly"] = True
+ return response
+```
+:---
+
+Response cookies can be set like dictionary values and have the following parameters available:
+
+- `expires: datetime` - The time for the cookie to expire on the client’s browser.
+- `path: str` - The subset of URLs to which this cookie applies. Defaults to `/`.
+- `comment: str` - A comment (metadata).
+- `domain: str` - Specifies the domain for which the cookie is valid. An explicitly specified domain must always start with a dot.
+- `max-age: int` - Number of seconds the cookie should live for.
+- `secure: bool` - Specifies whether the cookie will only be sent via HTTPS.
+- `httponly: bool` - Specifies whether the cookie cannot be read by JavaScript.
+- `samesite: str` - Default is browser dependent, specification states (Lax, Strict, and None) are valid values.
+
+## Deleting
+
+---:1
+
+Cookies can be removed semantically or explicitly. :--:1
+```python
+@app.route("/cookie")
+async def test(request):
+ response = text("Time to eat some cookies muahaha")
+
+ # This cookie will be set to expire in 0 seconds
+ del response.cookies["kill_me"]
+
+ # This cookie will self destruct in 5 seconds
+ response.cookies["short_life"] = "Glad to be here"
+ response.cookies["short_life"]["max-age"] = 5
+ del response.cookies["favorite_color"]
+
+ # This cookie will remain unchanged
+ response.cookies["favorite_color"] = "blue"
+ response.cookies["favorite_color"] = "pink"
+ del response.cookies["favorite_color"]
+
+ return response
+```
+:---
+
+## Eating
+
+I like cookies :cookie:
From 784dd66c663828e935e06317d89d88f8aa238d9b Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:05 +0300
Subject: [PATCH 012/776] New translations handlers.md (Japanese)
---
src/ja/guide/basics/handlers.md | 30 +++++++++++++-----------------
1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/src/ja/guide/basics/handlers.md b/src/ja/guide/basics/handlers.md
index 4c15b683a4..81502f892f 100644
--- a/src/ja/guide/basics/handlers.md
+++ b/src/ja/guide/basics/handlers.md
@@ -1,6 +1,6 @@
# Handlers
-次の重要な構成要素は、あなたの_handlers_です。これらは「ビュー」とも呼ばれます。
+次の重要な構成要素は、あなたの_handlers_です。 これらは「ビュー」とも呼ばれます。
Sanicでは、ハンドラは、少なくとも「Request`インスタンスを引数として受け取り、`HTTPResponse`インスタンス、または同じことを行うコルーチンのいずれかを返す呼び出し可能物です。
@@ -10,10 +10,9 @@ Sanicでは、ハンドラは、少なくとも「Request`インスタンスを
え? :confused:
-これは**関数**です。同期または非同期のいずれかです。
+これは**関数**です。 同期または非同期のいずれかです。
-ハンドラの仕事は、エンドポイントに応答し、何かをすることです。これはあなたのビジネスロジックの大半が行く場所です。
-:--:1
+ハンドラの仕事は、エンドポイントに応答し、何かをすることです。 これはあなたのビジネスロジックの大半が行く場所です。 :--:1 :--:1
```python
def i_am_a_handler(request):
return HTTPResponse()
@@ -23,19 +22,17 @@ async def i_am_ALSO_a_handler(request):
```
:---
-::: tip Heads up
-ロジックのカプセル化の詳細については、[クラスベースのビュー](/guide/advanced/class-based-views.md) をチェックアウトしてください。
-:::
+::: tip Heads up ロジックのカプセル化の詳細については、[クラスベースのビュー](/guide/advanced/class-based-views.md) をチェックアウトしてください。 :::
---:1
-次に、エンドポイントに配線するだけです。[すぐにルーティング](./routing.md)について詳しく学びます。
+次に、エンドポイントに配線するだけです。
+::: ---:1 Then, all you need to do is wire it up to an endpoint. [すぐにルーティング](./routing.md)について詳しく学びます。
実際の例を見てみましょう。
- アプリインスタンスで便利なデコレータを使用します: `@app.get()`
- そして、応答オブジェクトを生成するための便利な便利なメソッド: `text()`
-達成されたミッション :muscle:
-:--:1
+達成されたミッション :muscle: :--:1
```python
from sanic.response import text
@@ -53,13 +50,12 @@ async def foo_handler(request):
同期しているハンドラーを書くことは完全に可能です。
-この例では、_blocking_ `time.sleep()`を使用して100msの処理時間をシミュレートしています。おそらく、これはDB、またはサードパーティのウェブサイトからデータを取得することを表します。
+この例では、_blocking_ `time.sleep()`を使用して100msの処理時間をシミュレートしています。 おそらく、これはDB、またはサードパーティのウェブサイトからデータを取得することを表します。
4つのワーカープロセスと共通のベンチマークツールを使用する:
- **956** 30.10秒のリクエスト
-- または、約**31.76**リクエスト/秒
-:--:1
+- または、約**31.76**リクエスト/秒 :--:1
```python
@app.get("/sync")
def sync_handler(request):
@@ -79,11 +75,11 @@ def sync_handler(request):
:flushed:
-さて...これはとんでもなく劇的な結果です。そして、あなたが見るベンチマークは本質的に非常に偏っています。この例は、ウェブの世界で「async/await」の利点をオーバーザトップで示すことを目的としています。結果は確かに異なります。Sanicやその他の非同期Pythonライブラリなどのツールは、物事をより速くする魔法の弾丸ではありません。彼らはそれらをより効率的にします。
+さて...これはとんでもなく劇的な結果です。 そして、あなたが見るベンチマークは本質的に非常に偏っています。 この例は、ウェブの世界で「async/await」の利点をオーバーザトップで示すことを目的としています。 結果は確かに異なります。 Sanicやその他の非同期Pythonライブラリなどのツールは、物事をより速くする魔法の弾丸ではありません。 彼らはそれらをより効率的にします。
この例では、1つのリクエストがスリープしている間、別のリクエストと別のリクエスト、別のリクエスト、別のリクエスト、別のリクエストを開始できるため、非同期バージョンの方がはるかに優れています。
-しかし、これがポイントです!Sanicは、利用可能なリソースを取り出し、それらからパフォーマンスを絞り出すため、高速です。多くのリクエストを同時に処理できるため、1秒あたりのリクエストが増えます。
+But, this is the point! しかし、これがポイントです!Sanicは、利用可能なリソースを取り出し、それらからパフォーマンスを絞り出すため、高速です。 多くのリクエストを同時に処理できるため、1秒あたりのリクエストが増えます。
:--:1
```python
@@ -96,9 +92,9 @@ async def async_handler(request):
::: 警告 よくある間違い!
-こんなことしないで!ウェブサイトにpingを送信する必要があります。何を使いますか?`pip install your-fav-request-library` :see_no_evil:
+Don't do this! こんなことしないで!ウェブサイトにpingを送信する必要があります。 What do you use? 何を使いますか?`pip install your-fav-request-library` :see_no_evil:
-その代わり、`async/await` が可能なクライアントを使用してみてください。あなたのサーバーはあなたに感謝するでしょう。ブロッキングツールの使用は避け、非同期のエコシステムでうまく機能するものを選びましょう。もし推薦が必要なら、[Awesome Sanic](https://github.com/mekicha/awesome-sanic)をチェックしてください。
+その代わり、`async/await` が可能なクライアントを使用してみてください。 あなたのサーバーはあなたに感謝するでしょう。 ブロッキングツールの使用は避け、非同期のエコシステムでうまく機能するものを選びましょう。 もし推薦が必要なら、[Awesome Sanic](https://github.com/mekicha/awesome-sanic)をチェックしてください。
Sanicは、テストパッケージ(sanic-testing)内で[httpx](https://www.python-httpx.org/)を使用しています。 :wink:.
From a87caf2231c8e3129e9a878da9465145ca599210 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:06 +0300
Subject: [PATCH 013/776] New translations handlers.md (Korean)
---
src/ko/guide/basics/handlers.md | 35 +++++++++------------------------
1 file changed, 9 insertions(+), 26 deletions(-)
diff --git a/src/ko/guide/basics/handlers.md b/src/ko/guide/basics/handlers.md
index 5fc4ad53ea..d4447f3441 100644
--- a/src/ko/guide/basics/handlers.md
+++ b/src/ko/guide/basics/handlers.md
@@ -4,16 +4,15 @@
Sanic에서 핸들러는 `Request` 인스턴스를 인수로 취하는 모든 호출 가능한 함수(Callable) 입니다, 그리고 `HTTP Response` 인스턴스 또는 같은 작업을 수행하는 코루틴(coroutine)을 반환합니다.
+
+
---:1
어라? :confused:
이것은 일반 함수일 수도 있고, 비동기 함수일 수도 있습니다.
-핸들러의 역할은 엔드 포인트에 응답하여 무언가를 하는 것입니다. 이것은 대부분의 비즈니스 로직이 적용되는 곳입니다.
-
-:--:1
-
+핸들러의 역할은 엔드 포인트에 응답하여 무언가를 하는 것입니다. 이것은 대부분의 비즈니스 로직이 적용되는 곳입니다. :--:1
```python
def i_am_a_handler(request):
return HTTPResponse()
@@ -21,32 +20,23 @@ def i_am_a_handler(request):
async def i_am_ALSO_a_handler(request):
return HTTPResponse()
```
-
:---
-::: tip Heads up
-논리 캡슐화에 대해 자세히 알아보려면 [클래스 기반 뷰](/guide/advanced/class-based-views.md)를 확인하세요.
-:::
----:1
-그 다음 엔드포인트(endpoint)에 연결하기만 하면 됩니다. 곧 [라우팅](./routing.md)에서 자세히 알아 보겠습니다.
+::: tip Heads up 논리 캡슐화에 대해 자세히 알아보려면 [클래스 기반 뷰](/guide/advanced/class-based-views.md)를 확인하세요. ::: ---:1 그 다음 엔드포인트(endpoint)에 연결하기만 하면 됩니다. 곧 [라우팅](./routing.md)에서 자세히 알아 보겠습니다.
-실용적인 예를 살펴보겠습니다.
+Let's look at a practical example.
- 앱 인스턴스에 편리한 데코레이터를 사용합니다 :`@ app.get ()`
- 응답 객체를 생성하기 위한 편리한 방법: `text()`
-임무 완수 :muscle:
-:--:1
-
+실용적인 예를 살펴보겠습니다.
```python
-
from sanic.response import text
@app.get("/foo")
async def foo_handler(request):
return text("I said foo!")
```
-
:---
---
@@ -57,28 +47,23 @@ async def foo_handler(request):
동기식 핸들러를 작성하는 것도 당연히 가능합니다.
-이 예에서는 _블로킹(blocking)_ `time.sleep()`을 사용하여 100ms의 처리 시간을 시뮬레이션합니다.
-이것은 DB 또는 타사 웹 사이트에서 데이터를 가져오는 것을 나타냅니다.
+이 예에서는 _블로킹(blocking)_ `time.sleep()`을 사용하여 100ms의 처리 시간을 시뮬레이션합니다. 이것은 DB 또는 타사 웹 사이트에서 데이터를 가져오는 것을 나타냅니다.
4개의 작업자(worker) 프로세스와 평범한 벤치마킹 도구를 사용합니다.:
- 30.10초 동안 **956**건의 요청이 이뤄졌습니다.
- 또는 약 **31.76** 요청/초입니다.
-
-:--:1
-
```python
@app.get("/sync")
def sync_handler(request):
time.sleep(0.1)
return text("Done.")
```
-
:---
---:1
-비동기식 대안 `asyncio.sleep()`으로 변경하는 것만으로도 성능이 크게 변하는 것을 볼 수 있습니다.
+비동기식 대안 `asyncio.sleep()`으로 변경하는 것만으로도 성능이 크게 변하는 것을 볼 수 있습니다. :rocket:
동일한 4 개의 작업자(worker) 프로세스 사용:
@@ -94,19 +79,17 @@ def sync_handler(request):
하지만, 요점은 이것입니다! Sanic은 사용 가능한 리소스를 사용하고 성능을 압축하기 때문에 속도가 빠릅니다. 동시에 많은 요청을 처리할 수 있으므로 초당 더 많은 요청을 처리할 수 있습니다.
:--:1
-
```python
@app.get("/async")
async def async_handler(request):
await asyncio.sleep(0.1)
return text("Done.")
```
-
:---
::: warning 일반적인 실수입니다!
-이러지 마세요! 웹 사이트를 ping해야 할 때, 뭘 쓰시나요? `pip install your-fav-request-library` :see_no_evil:
+이러지 마세요! 웹 사이트를 ping해야 할 때, 뭘 쓰시나요? What do you use? `pip install your-fav-request-library` :see_no_evil:
대신 `async / await` 가 가능한 클라이언트를 사용해보세요. 당신의 서버가 고마워 할 것입니다. 차단(Blocking) 도구를 사용하지 말고 비동기 생태계에서 잘 작동하는 도구를 사용하세요. 추천이 필요한 경우 [Awesome Sanic](https://github.com/mekicha/awesome-sanic)을 확인하세요.
From 20e74565b3914a0b67ece9c0ac4c4ef3e427df0a Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:08 +0300
Subject: [PATCH 014/776] New translations handlers.md (Chinese Simplified)
---
src/zh/guide/basics/handlers.md | 71 +++++++++++++--------------------
1 file changed, 27 insertions(+), 44 deletions(-)
diff --git a/src/zh/guide/basics/handlers.md b/src/zh/guide/basics/handlers.md
index 9cef631df7..552ffd6e05 100644
--- a/src/zh/guide/basics/handlers.md
+++ b/src/zh/guide/basics/handlers.md
@@ -1,19 +1,18 @@
# 响应函数(Handlers)
-第二个重要的组件就是响应函数(Handlers),也就是我们通常所说的视图(views)。
+The next important building block are your _handlers_. These are also sometimes called "views".
在 Sanic 中,响应函数可以是任何一个可调用程序,它至少以一个 `request` 实例作为参数,并返回一个 `HTTPResponse` 实例或一个执行其他操作的协同程序作为响应。
----:1
-哈? :flushed:
-它既可以是一个普通函数,也可以是一个异步的函数。
+---:1
-它的工作是响应指定端点的访问, 并执行一些指定的操作,所以这里是承载业务逻辑代码的地方。
+Huh? 哈? :flushed:
-:--:1
+它既可以是一个普通函数,也可以是一个异步的函数。
+The job of the handler is to respond to an endpoint and do something. This is where the majority of your business logic will go. :--:1
```python
def i_am_a_handler(request):
return HTTPResponse()
@@ -21,28 +20,16 @@ def i_am_a_handler(request):
async def i_am_ALSO_a_handler(request):
return HTTPResponse()
```
-
:---
-::: tip 小提示:
-
-如果您想要了解更多关于封装逻辑的信息,可以通过 [基于类的视图](/zh/guide/advanced/class-based-views.md) 这一章节来了解更多
+::: tip Heads up If you want to learn more about encapsulating your logic, checkout [class based views](/guide/advanced/class-based-views.md). ::: ---:1 Then, all you need to do is wire it up to an endpoint. 在 [路由](/zh/guide/basics/routing.md) 这一章节,我们将会了解更多相关的内容
-:::
-
----:1
-
-之后,您需要做的就只是将其挂载到服务端点上。 在 [路由](/zh/guide/basics/routing.md) 这一章节,我们将会了解更多相关的内容
-
-让我们来用一个示例进行讲解:
+::: tip 小提示:
- 我们在响应函数实例中使用了装饰器:`@app.get()`
-- 我们还使用了函数 `text()` 来快速的生成一个文本类型的响应对象。
-
-任务完成 :muscle:
-
-:--:1
+- 我们还使用了函数 `text()` 来快速的生成一个文本类型的响应对象。
+如果您想要了解更多关于封装逻辑的信息,可以通过 [基于类的视图](/zh/guide/advanced/class-based-views.md) 这一章节来了解更多
```python
from sanic.response import text
@@ -58,42 +45,38 @@ async def foo_handler(request):
---:1
-编写普通的响应函数是完全可行的。
-
-在下面的例子中,我们通过 `time.sleep()` 方法来等待 100 毫秒,用于模拟数据读取或者内容处理等操作。
-
-使用 4 个工作进程和一个通用基准工具进行性能测试,得到以下数据:
+It is entirely possible to write handlers that are synchronous.
-- 在 30.10 秒内,共进行了 956 次请求
-- 平均每秒响应 31.76 次请求
+In this example, we are using the _blocking_ `time.sleep()` to simulate 100ms of processing time. Perhaps this represents fetching data from a DB, or a 3rd-party website.
-:--:1
+任务完成 :muscle:
+- 在 30.10 秒内,共进行了 956 次请求
+- 平均每秒响应 31.76 次请求
```python
@app.get("/sync")
def sync_handler(request):
time.sleep(0.1)
return text("Done.")
```
-
:---
---:1
-当我们使用异步解决方案时,性能将会得到极大的提升,您会看到一组惊人的数据 :rocket:。
+Just by changing to the asynchronous alternative `asyncio.sleep()`, we see an incredible change in performance. :rocket:
-同样使用 4 个子进程和一个相同的基准工具再次进行性能测试,得到以下数据:
+编写普通的响应函数是完全可行的。
-- 在 30.10 秒内,共进行了 **115,590** 次请求
-- 平均每秒响应 **3843.17** 次请求
+- 在 30.10 秒内,共进行了 **115,590** 次请求
+- 平均每秒响应 **3843.17** 次请求
-:flushed: Wow!
+在下面的例子中,我们通过 `time.sleep()` 方法来等待 100 毫秒,用于模拟数据读取或者内容处理等操作。
-好吧,这个结果有些夸张,甚至有些好笑。这个例子有一些极端了,您所看到的任何一个基准测试都是如此的。这样的测试方式在实际生产环境中没有任何意义,这个例子旨在告诉我们在网络编程中 `async/await` 的优势有多么大。像 Sanic 和其他的异步 Python 库并不是让程序执行速度变得更快,只是让它们的组织方式变得更为高效而已。
+好吧,这个结果有些夸张,甚至有些好笑。 And any benchmark you see is inherently very biased. 这样的测试方式在实际生产环境中没有任何意义,这个例子旨在告诉我们在网络编程中 `async/await` 的优势有多么大。 Results will certainly vary. 像 Sanic 和其他的异步 Python 库并不是让程序执行速度变得更快,只是让它们的组织方式变得更为高效而已。 They make them _more efficient_.
-在我们刚才的例子中,异步版本的效率要高得多,因为当一个请求处于休眠状态时,它能够响应另一个请求、另一个请求、另一个请求、另一个请求...
+In our example, the asynchronous version is so much better because while one request is sleeping, it is able to start another one, and another one, and another one, and another one...
-没错,重点就在这里,Sanic 之所以快速是因为它充分组织了这些可用资源来提升性能。它可以同时响应多个请求,这意味着它每秒可以处理更多的请求。
+But, this is the point! 没错,重点就在这里,Sanic 之所以快速是因为它充分组织了这些可用资源来提升性能。 它可以同时响应多个请求,这意味着它每秒可以处理更多的请求。
:--:1
```python
@@ -104,13 +87,13 @@ async def async_handler(request):
```
:---
-::: warning 常见错误:
+同样使用 4 个子进程和一个相同的基准工具再次进行性能测试,得到以下数据:
-请尽量避免使用同步的工具,或许您需要 ping 一下您的站点来进行测试。
+Don't do this! You need to ping a website. What do you use? `pip install your-fav-request-library` :see_no_evil:
-请尽可能的使用异步工具来避免发生阻塞。您的服务器将感谢您。在 [Awesome Sanic](https://github.com/mekicha/awesome-sanic) 中有许多性能优秀的 Sanic 异步工具,您可以在那里找到合适自己的异步工具。
+Instead, try using a client that is `async/await` capable. 您的服务器将感谢您。 Avoid using blocking tools, and favor those that play well in the asynchronous ecosystem. If you need recommendations, check out [Awesome Sanic](https://github.com/mekicha/awesome-sanic).
-Sanic 的测试套件 (sanic-testing) 充分的发挥了 [httpx](https://www.python-httpx.org/) 的性能 :wink:。
+在我们刚才的例子中,异步版本的效率要高得多,因为当一个请求处于休眠状态时,它能够响应另一个请求、另一个请求、另一个请求、另一个请求...
:::
@@ -118,7 +101,7 @@ Sanic 的测试套件 (sanic-testing) 充分的发挥了 [httpx](https://www.pyt
## 带完整注释的响应函数(A fully annotated handler)
-Sanic 支持使用类型注解,下面的例子送给喜欢使用类型注解的人…
+For those that are using type annotations...
```python
from sanic.response import HTTPResponse, text
From dc0577d15128768133ef80b5d4e703eae2f82e61 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:09 +0300
Subject: [PATCH 015/776] New translations handlers.md (Portuguese, Brazilian)
---
src/pt/guide/basics/handlers.md | 113 ++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
create mode 100644 src/pt/guide/basics/handlers.md
diff --git a/src/pt/guide/basics/handlers.md b/src/pt/guide/basics/handlers.md
new file mode 100644
index 0000000000..4f255f3a90
--- /dev/null
+++ b/src/pt/guide/basics/handlers.md
@@ -0,0 +1,113 @@
+# Handlers
+
+The next important building block are your _handlers_. These are also sometimes called "views".
+
+In Sanic, a handler is any callable that takes at least a `Request` instance as an argument, and returns either an `HTTPResponse` instance, or a coroutine that does the same.
+
+
+
+---:1
+
+Huh? :confused:
+
+It is a **function**; either synchronous or asynchronous.
+
+The job of the handler is to respond to an endpoint and do something. This is where the majority of your business logic will go. :--:1
+```python
+def i_am_a_handler(request):
+ return HTTPResponse()
+
+async def i_am_ALSO_a_handler(request):
+ return HTTPResponse()
+```
+:---
+
+::: tip Heads up If you want to learn more about encapsulating your logic, checkout [class based views](/guide/advanced/class-based-views.md). ::: ---:1 Then, all you need to do is wire it up to an endpoint. We'll learn more about [routing soon](./routing.md).
+
+Let's look at a practical example.
+
+- We use a convenience decorator on our app instance: `@app.get()`
+- And a handy convenience method for generating out response object: `text()`
+
+Mission accomplished :muscle: :--:1
+```python
+from sanic.response import text
+
+@app.get("/foo")
+async def foo_handler(request):
+ return text("I said foo!")
+```
+:---
+
+---
+
+## A word about _async_...
+
+---:1
+
+It is entirely possible to write handlers that are synchronous.
+
+In this example, we are using the _blocking_ `time.sleep()` to simulate 100ms of processing time. Perhaps this represents fetching data from a DB, or a 3rd-party website.
+
+Using four (4) worker processes and a common benchmarking tool:
+
+- **956** requests in 30.10s
+- Or, about **31.76** requests/second :--:1
+```python
+@app.get("/sync")
+def sync_handler(request):
+ time.sleep(0.1)
+ return text("Done.")
+```
+:---
+
+---:1
+
+Just by changing to the asynchronous alternative `asyncio.sleep()`, we see an incredible change in performance. :rocket:
+
+Using the same four (4) worker processes:
+
+- **115,590** requests in 30.08s
+- Or, about **3,843.17** requests/second
+
+:flushed:
+
+Okay... this is a ridiculously overdramatic result. And any benchmark you see is inherently very biased. This example is meant to over-the-top show the benefit of `async/await` in the web world. Results will certainly vary. Tools like Sanic and other async Python libraries are not magic bullets that make things faster. They make them _more efficient_.
+
+In our example, the asynchronous version is so much better because while one request is sleeping, it is able to start another one, and another one, and another one, and another one...
+
+But, this is the point! Sanic is fast because it takes the available resources and squeezes performance out of them. It can handle many requests concurrently, which means more requests per second.
+
+:--:1
+```python
+@app.get("/async")
+async def async_handler(request):
+ await asyncio.sleep(0.1)
+ return text("Done.")
+```
+:---
+
+::: warning A common mistake!
+
+Don't do this! You need to ping a website. What do you use? `pip install your-fav-request-library` :see_no_evil:
+
+Instead, try using a client that is `async/await` capable. Your server will thank you. Avoid using blocking tools, and favor those that play well in the asynchronous ecosystem. If you need recommendations, check out [Awesome Sanic](https://github.com/mekicha/awesome-sanic).
+
+Sanic uses [httpx](https://www.python-httpx.org/) inside of its testing package (sanic-testing) :wink:.
+
+:::
+
+---
+
+## A fully annotated handler
+
+For those that are using type annotations...
+
+```python
+from sanic.response import HTTPResponse, text
+from sanic.request import Request
+
+@app.get("/typed")
+async def typed_handler(request: Request) -> HTTPResponse:
+ return text("Done.")
+```
From cb14fc7d942214ed5c5846dd36ccd4befbe4ca3d Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:10 +0300
Subject: [PATCH 016/776] New translations headers.md (Japanese)
---
src/ja/guide/basics/headers.md | 25 +++++++++++--------------
1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/src/ja/guide/basics/headers.md b/src/ja/guide/basics/headers.md
index fb9497da86..75ecc275b5 100644
--- a/src/ja/guide/basics/headers.md
+++ b/src/ja/guide/basics/headers.md
@@ -1,10 +1,10 @@
# Headers
-リクエストおよびレスポンスのヘッダーは、それぞれ`Request`オブジェクトと`HTTPResponse`オブジェクトで使用できます。単一のキーが複数の値を持つことを可能にする [`multidict`パッケージ] (https://multidict.readthedocs.io/en/stable/multidict.html#cimultidict) を利用します。
+リクエストおよびレスポンスのヘッダーは、それぞれ`Request`オブジェクトと`HTTPResponse`オブジェクトで使用できます。 単一のキーが複数の値を持つことを可能にする [`multidict`パッケージ] (https://multidict.readthedocs.io/en/stable/multidict.html#cimultidict) を利用します。
::: tip FYI
-ヘッダキーは、解析時に*小文字*に変換されます。ヘッダーでは大文字と小文字は区別されません。
+ヘッダキーは、解析時に*小文字*に変換されます。 ヘッダーでは大文字と小文字は区別されません。
:::
@@ -44,18 +44,17 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4
#### Proxy headers
-Sanicはプロキシヘッダを特別に扱います。詳細については、 [proxy headers] (/guide/advanced/proxy-headers.md) セクションを参照してください。
+Sanicはプロキシヘッダを特別に扱います。 詳細については、 \[proxy headers\] (/guide/advanced/proxy-headers.md) セクションを参照してください。
#### Host header and dynamic URL construction
-*実効ホスト*は`request.host`を介して使用できます。これは、プロキシ転送されたホストを優先し、サーバ名の設定によって強制される可能性があるため、必ずしもホストヘッダーと同じではありません。
+*実効ホスト*は`request.host`を介して使用できます。 これは、プロキシ転送されたホストを優先し、サーバ名の設定によって強制される可能性があるため、必ずしもホストヘッダーと同じではありません。
-Webアプリケーションは通常、どのようにデプロイされても同じように機能できるように、このアクセサを使用する必要があります。実際のホストヘッダーは、必要に応じて`request.headers`
+Webアプリケーションは通常、どのようにデプロイされても同じように機能できるように、このアクセサを使用する必要があります。 実際のホストヘッダーは、必要に応じて`request.headers`
実効ホストは、ハンドラの外部アドレスを決定するためにリクエストを使用する`request.url_for`を介して動的URL構築でも使用されます。
-::: tip Be wary of malicious clients
-これらのURLは、誤ったホストヘッダーを送信することで操作できます。これが懸念される場合は、代わりに`app.url_for`を使用する必要があります。
+::: tip Be wary of malicious clients これらのURLは、誤ったホストヘッダーを送信することで操作できます。 これが懸念される場合は、代わりに`app.url_for`を使用する必要があります。 :::
:::
:--:1
@@ -90,7 +89,7 @@ $ curl localhost:8000/hosts
---:1
#### Other headers
-すべてのリクエストヘッダーは`request.headers`で使用でき、辞書形式でアクセスできます。大文字はヘッダーでは考慮されず、大文字または小文字のキーを使用してアクセスできます。
+すべてのリクエストヘッダーは`request.headers`で使用でき、辞書形式でアクセスできます。 大文字はヘッダーでは考慮されず、大文字または小文字のキーを使用してアクセスできます。
:--:1
@@ -145,18 +144,16 @@ $ curl localhost:9999/headers -H "Foo: one" -H "FOO: two"|jq
:---
-::: tip FYI
-💡 request.headersオブジェクトは、辞書のタイプの1つで、各値はリストです。これは、HTTPでは1つのキーを再利用して複数の値を送信できるためです。
+::: tip FYI 💡 request.headersオブジェクトは、辞書のタイプの1つで、各値はリストです。 これは、HTTPでは1つのキーを再利用して複数の値を送信できるためです。
-ほとんどの場合、リストではなく最初の要素にアクセスするには、.get () または.getone () メソッドを使用します。すべての項目のリストが必要な場合は、.getall () を使用できます。
+ほとんどの場合、リストではなく最初の要素にアクセスするには、.get () または.getone () メソッドを使用します。 すべての項目のリストが必要な場合は、.getall () を使用できます。 :::
:::
#### Request ID
---:1
-多くの場合、 「X-Request-ID」 ヘッダーを使用してリクエストを追跡すると便利です。次の方法で簡単にアクセスできます。
-`request.id`.
+多くの場合、 「X-Request-ID」 ヘッダーを使用してリクエストを追跡すると便利です。 次の方法で簡単にアクセスできます。 `request.id`.
:--:1
@@ -205,7 +202,7 @@ async def add_csp(request, response):
---:1
-一般的な [ミドルウェア] (middleware.md) は、すべての応答に`X-Request-ID`ヘッダーを追加することです。前述のように、`request.id`は着信要求からIDを提供します。ただし、リクエストヘッダーにIDが指定されていない場合でも、自動的にIDが指定されます。
+一般的な \[ミドルウェア\] (middleware.md) は、すべての応答に`X-Request-ID`ヘッダーを追加することです。 前述のように、`request.id`は着信要求からIDを提供します。 ただし、リクエストヘッダーにIDが指定されていない場合でも、自動的にIDが指定されます。
[詳細については、APIドキュメントを参照してください。](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#sanic.request.Request.id)
From 40311241be87c5140551b2956d0d9106c7af41de Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:11 +0300
Subject: [PATCH 017/776] New translations headers.md (Korean)
---
src/ko/guide/basics/headers.md | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/src/ko/guide/basics/headers.md b/src/ko/guide/basics/headers.md
index ff2e4cce31..f4802dc896 100644
--- a/src/ko/guide/basics/headers.md
+++ b/src/ko/guide/basics/headers.md
@@ -1,10 +1,11 @@
# 헤더(Headers)
-요청 및 응답 헤더는 각각 `Request` 및 `HTTPResponse` 객체에서 사용할 수 있습니다.
-단일 키가 여러 값을 가질 수 있도록 허용하는 [`multidict` 패키지](https://multidict.readthedocs.io/en/stable/multidict.html#cimultidict)를 사용합니다.
+요청 및 응답 헤더는 각각 `Request` 및 `HTTPResponse` 객체에서 사용할 수 있습니다. 단일 키가 여러 값을 가질 수 있도록 허용하는 [`multidict` 패키지](https://multidict.readthedocs.io/en/stable/multidict.html#cimultidict)를 사용합니다.
::: tip FYI
-헤더 키는 구문 분석시 *소문자*로 변환됩니다. 헤더에는 대문자 사용이 고려되지 않습니다.
+
+::: tip FYI 헤더 키는 구문 분석시 *소문자*로 변환됩니다. 헤더에는 대문자 사용이 고려되지 않습니다.
+
:::
## 요청(Request)
@@ -15,7 +16,8 @@ Sanic은 요청 헤더를 개발자에게 제공하기 전에 요청 헤더에
#### 토큰(Tokens)
-`Token ` 또는 `Bearer `형식의 인증 토큰이 요청 객체 `request.token`으로 추출됩니다.
+`Token ` 또는 `Bearer `형식의 인증 토큰이 요청 객체 `request.token`으로 추출됩니다. :--:1
+
:--:1
```python
@@ -52,10 +54,7 @@ Sanic에는 프록시 헤더에 대한 특수 처리 기능이 있습니다. 자
유효 호스트는 요청을 사용하여 핸들러의 외부 주소를 결정하는 `request.url_for`를 통한 동적 URL 구성에도 사용됩니다.
-::: tip 악의적인 클라이언트를 조심하세요!
-
-이러한 URL은 오해의 소지가 있는 호스트 헤더를 전송하여 조작할 수 있습니다. 이것이 우려된다면 `app.url_for`를 대신 사용해야 합니다.
-:::
+이러한 URL은 오해의 소지가 있는 호스트 헤더를 전송하여 조작할 수 있습니다. 이것이 우려된다면 `app.url_for`를 대신 사용해야 합니다. :::
:--:1
@@ -144,11 +143,9 @@ $ curl localhost:9999/headers -H "Foo: one" -H "FOO: two"|jq
:---
-::: tip FYI
-💡 request.headers 객체는 각 값이 목록인 사전인 몇 가지 유형 중 하나입니다. HTTP에서는 단일 키를 재사용하여 여러 값을 보낼 수 있기 때문입니다
+::: tip FYI 💡 request.headers 객체는 각 값이 목록인 사전인 몇 가지 유형 중 하나입니다. HTTP에서는 단일 키를 재사용하여 여러 값을 보낼 수 있기 때문입니다
-대부분의 경우 .get() 또는 .getone() 메서드를 사용하여 목록이 아닌 첫 번째 요소에 액세스하려고 합니다. 모든 항목의 목록을 원하면 .getall()을 사용할 수 있습니다.
-:::
+대부분의 경우 .get() 또는 .getone() 메서드를 사용하여 목록이 아닌 첫 번째 요소에 액세스하려고 합니다. 모든 항목의 목록을 원하면 .getall()을 사용할 수 있습니다. :::
#### 요청 ID(Request ID)
@@ -181,9 +178,12 @@ Sanic은 자동으로 다음 응답 헤더(해당되는 경우)를 설정합니
- `connection`
- `transfer-encoding`
+In most circumstances, you should never need to worry about setting these headers.
+
---:1
설정할 다른 헤더는 경로 핸들러 또는 응답 미들웨어에서 수행할 수 있습니다.
+
:--:1
```python
@@ -200,11 +200,9 @@ async def add_csp(request, response):
---:1
-::: new
-일반적인 [middleware](middleware.md)는 모든 응답에 `X-Request-ID` 헤더를 추가하는 것입니다. 위에서 언급했듯이`request.id`는 수신 요청의 ID를 제공합니다. 그러나 요청 헤더에 ID가 제공되지 않은 경우에도 자동으로 제공됩니다.
+::: new 일반적인 [middleware](middleware.md)는 모든 응답에 `X-Request-ID` 헤더를 추가하는 것입니다. 위에서 언급했듯이`request.id`는 수신 요청의 ID를 제공합니다. 그러나 요청 헤더에 ID가 제공되지 않은 경우에도 자동으로 제공됩니다.
-[자세한 내용은 API 문서를 참조하세요.](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#sanic.request.Request.id)
-:::
+[[자세한 내용은 API 문서를 참조하세요.](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#sanic.request.Request.id) :::](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#sanic.request.Request.id)
:--:1
From 2760f4a6580c5bf745f9e9d621168bebf131ae57 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:12 +0300
Subject: [PATCH 018/776] New translations headers.md (Chinese Simplified)
---
src/zh/guide/basics/headers.md | 39 +++++++++++++---------------------
1 file changed, 15 insertions(+), 24 deletions(-)
diff --git a/src/zh/guide/basics/headers.md b/src/zh/guide/basics/headers.md
index f3b55964ab..6f627f4f13 100644
--- a/src/zh/guide/basics/headers.md
+++ b/src/zh/guide/basics/headers.md
@@ -1,10 +1,10 @@
# 标头(Headers)
-请求头和响应头仅在对应的 `Request` 对象和 `HTTPResponse` 对象中起作用。它们使用 [`multidict` 包](https://multidict.readthedocs.io/en/stable/multidict.html#cimultidict) 进行构建,这意味着它们允许一个键名具有多个对应值。
+请求头和响应头仅在对应的 `Request` 对象和 `HTTPResponse` 对象中起作用。 它们使用 [`multidict` 包](https://multidict.readthedocs.io/en/stable/multidict.html#cimultidict) 进行构建,这意味着它们允许一个键名具有多个对应值。
::: tip 小提示:
-请求头或响应头中的键名将会在解析过程中被转换为小写,Headers 中不考虑大写键名。
+Header keys are converted to *lowercase* when parsed. Capitalization is not considered for headers.
:::
@@ -31,6 +31,7 @@ $ curl localhost:8000 \
-H "Authorization: Token ABCDEF12345679"
ABCDEF12345679
```
+
```bash
$ curl localhost:8000 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
@@ -43,21 +44,17 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4
#### 代理头(Proxy headers)
-Sanic 对代理头也有着特殊的处理,具体的细节请参考 [代理头](/zh/guide/advanced/proxy-headers.md) 章节的解释
+Sanic has special handling for proxy headers. Sanic 对代理头也有着特殊的处理,具体的细节请参考 [代理头](/zh/guide/advanced/proxy-headers.md) 章节的解释
#### 主机标头和动态URL的构建(Host header and dynamic URL construction)
-您可以通过 `request.host` 属性来获取有效主机名。该值不一定与头信息中的主机一致,因为它更倾向于保存反向代理的主机信息,并且可以通过服务器名称强行设置。
+您可以通过 `request.host` 属性来获取有效主机名。 该值不一定与头信息中的主机一致,因为它更倾向于保存反向代理的主机信息,并且可以通过服务器名称强行设置。
-在通常情况下,Web 应用应该去设置并使用这个属性,这样能保证在任何部署方式下都能提供同样的功能。如果需要的话 `request.headers` 可以获取真实的主机头信息。
+在通常情况下,Web 应用应该去设置并使用这个属性,这样能保证在任何部署方式下都能提供同样的功能。 如果需要的话 `request.headers` 可以获取真实的主机头信息。
有效的主机名称也可以与 `request.url_for` 方法一起使用,它可以确定响应函数所对应的外部地址。
-::: tip 警惕恶意客户端
-
-由于头信息中的主机信息可能会被客户端恶意替换,为了生成正确的 URL,您应该考虑使用 `app.url_for` 方法。
-
-:::
+::: tip Be wary of malicious clients These URLs can be manipulated by sending misleading host headers. `app.url_for` should be used instead if this is a concern. :::
:--:1
@@ -89,10 +86,9 @@ $ curl localhost:8000/hosts
:---
---:1
-
#### 其他标头(Other headers)
-您可以在请求对象的 `request.headers` 属性中获取所有的请求头,并且可以通过字典的方式来进行访问。Headers 的键名不考虑大小写,可以通过大写或小写键名来进行访问。
+您可以在请求对象的 `request.headers` 属性中获取所有的请求头,并且可以通过字典的方式来进行访问。 Headers 的键名不考虑大小写,可以通过大写或小写键名来进行访问。
:--:1
@@ -147,19 +143,16 @@ $ curl localhost:9999/headers -H "Foo: one" -H "FOO: two"|jq
:---
-::: tip 小提示
-
-💡 request.headers 对象是少数几个字典类型之一,每个值都是一个列表。这是因为HTTP允许重用一个键来发送多个值。
-
-大多数情况下,您会希望使用 .get()或 .getone()方法访问第一个元素,而不是列表。如果您想要所有项目的列表,您可以使用 .getall() 方法。
-
-:::
+💡 request.headers 对象是少数几个字典类型之一,每个值都是一个列表。 这是因为HTTP允许重用一个键来发送多个值。
+大多数情况下,您会希望使用 .get()或 .getone()方法访问第一个元素,而不是列表。 如果您想要所有项目的列表,您可以使用 .getall() 方法。 :::
#### Request ID
---:1
+Often it is convenient or necessary to track a request by its `X-Request-ID` header. You can easily access that as: `request.id`.
+
:--:1
```python
@@ -178,7 +171,7 @@ ABCDEF12345679
## 响应头(Response Headers)
-Sanic将为您自动设置以下响应头(如果适用):
+Sanic will automatically set the following response headers (when appropriate) for you:
- `content-length`
- `content-type`
@@ -189,7 +182,7 @@ Sanic将为您自动设置以下响应头(如果适用):
---:1
-如果您想要设置其他的标头,那您可以在路由处理程序或者响应中间件中进行添加。
+Sanic将为您自动设置以下响应头(如果适用):
:--:1
@@ -207,9 +200,7 @@ async def add_csp(request, response):
---:1
-您可能会想要为响应也添加 `X-Request-ID` 头信息,通常,您可以添加一个 [中间件](middleware.md)。
-
-如上所述。`request.id` 可以从请求头中获取请求 ID。并且如果在请求中没有 `X-Request-ID` 头,也会自动为您创建一个。
+您可能会想要为响应也添加 `X-Request-ID` 头信息,通常,您可以添加一个 [中间件](middleware.md)。 如上所述。 `request.id` 可以从请求头中获取请求 ID。 并且如果在请求中没有 `X-Request-ID` 头,也会自动为您创建一个。
[查看API文档来获取更多信息](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#sanic.request.Request.id)
From b763e5bfeec9c885b987386fea5392676aafe669 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:13 +0300
Subject: [PATCH 019/776] New translations headers.md (Portuguese, Brazilian)
---
src/pt/guide/basics/headers.md | 230 +++++++++++++++++++++++++++++++++
1 file changed, 230 insertions(+)
create mode 100644 src/pt/guide/basics/headers.md
diff --git a/src/pt/guide/basics/headers.md b/src/pt/guide/basics/headers.md
new file mode 100644
index 0000000000..4bb06f8d8d
--- /dev/null
+++ b/src/pt/guide/basics/headers.md
@@ -0,0 +1,230 @@
+# Headers
+
+Request and response headers are available in the `Request` and `HTTPResponse` objects, respectively. They make use of the [`multidict` package](https://multidict.readthedocs.io/en/stable/multidict.html#cimultidict) that allows a single key to have multiple values.
+
+::: tip FYI
+
+Header keys are converted to *lowercase* when parsed. Capitalization is not considered for headers.
+
+:::
+
+## Request
+
+Sanic does attempt to do some normalization on request headers before presenting them to the developer, and also make some potentially meaningful extractions for common use cases.
+
+---:1
+
+#### Tokens
+
+Authorization tokens in the form `Token ` or `Bearer ` are extracted to the request object: `request.token`.
+
+:--:1
+
+```python
+@app.route("/")
+async def handler(request):
+ return text(request.token)
+```
+
+```bash
+$ curl localhost:8000 \
+ -H "Authorization: Token ABCDEF12345679"
+ABCDEF12345679
+```
+
+```bash
+$ curl localhost:8000 \
+ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
+eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
+```
+
+:---
+
+---:1
+
+#### Proxy headers
+
+Sanic has special handling for proxy headers. See the [proxy headers](/guide/advanced/proxy-headers.md) section for more details.
+
+#### Host header and dynamic URL construction
+
+The *effective host* is available via `request.host`. This is not necessarily the same as the host header, as it prefers proxy-forwarded host and can be forced by the server name setting.
+
+Webapps should generally use this accessor so that they can function the same no matter how they are deployed. The actual host header, if needed, can be found via `request.headers`
+
+The effective host is also used in dynamic URL construction via `request.url_for`, which uses the request to determine the external address of a handler.
+
+::: tip Be wary of malicious clients These URLs can be manipulated by sending misleading host headers. `app.url_for` should be used instead if this is a concern. :::
+
+:--:1
+
+```python
+app.config.SERVER_NAME = "https://example.com"
+
+@app.route("/hosts", name="foo")
+async def handler(request):
+ return json(
+ {
+ "effective host": request.host,
+ "host header": request.headers.get("host"),
+ "forwarded host": request.forwarded.get("host"),
+ "you are here": request.url_for("foo"),
+ }
+ )
+```
+
+```bash
+$ curl localhost:8000/hosts
+{
+ "effective host": "example.com",
+ "host header": "localhost:8000",
+ "forwarded host": null,
+ "you are here": "https://example.com/hosts"
+}
+```
+
+:---
+
+---:1
+#### Other headers
+
+All request headers are available on `request.headers`, and can be accessed in dictionary form. Capitalization is not considered for headers, and can be accessed using either uppercase or lowercase keys.
+
+:--:1
+
+```python
+@app.route("/")
+async def handler(request):
+ return json(
+ {
+ "foo_weakref": request.headers["foo"],
+ "foo_get": request.headers.get("Foo"),
+ "foo_getone": request.headers.getone("FOO"),
+ "foo_getall": request.headers.getall("fOo"),
+ "all": list(request.headers.items()),
+ }
+ )
+```
+
+```bash
+$ curl localhost:9999/headers -H "Foo: one" -H "FOO: two"|jq
+{
+ "foo_weakref": "one",
+ "foo_get": "one",
+ "foo_getone": "one",
+ "foo_getall": [
+ "one",
+ "two"
+ ],
+ "all": [
+ [
+ "host",
+ "localhost:9999"
+ ],
+ [
+ "user-agent",
+ "curl/7.76.1"
+ ],
+ [
+ "accept",
+ "*/*"
+ ],
+ [
+ "foo",
+ "one"
+ ],
+ [
+ "foo",
+ "two"
+ ]
+ ]
+}
+```
+
+:---
+
+::: tip FYI 💡 The request.headers object is one of a few types that is a dictionary with each value being a list. This is because HTTP allows a single key to be reused to send multiple values.
+
+Most of the time you will want to use the .get() or .getone() methods to access the first element and not a list. If you do want a list of all items, you can use .getall(). :::
+
+#### Request ID
+
+---:1
+
+Often it is convenient or necessary to track a request by its `X-Request-ID` header. You can easily access that as: `request.id`.
+
+:--:1
+
+```python
+@app.route("/")
+async def handler(request):
+ return text(request.id)
+```
+
+```bash
+$ curl localhost:8000 \
+ -H "X-Request-ID: ABCDEF12345679"
+ABCDEF12345679
+```
+
+:---
+
+## Response
+
+Sanic will automatically set the following response headers (when appropriate) for you:
+
+- `content-length`
+- `content-type`
+- `connection`
+- `transfer-encoding`
+
+In most circumstances, you should never need to worry about setting these headers.
+
+---:1
+
+Any other header that you would like to set can be done either in the route handler, or a response middleware.
+
+:--:1
+
+```python
+@app.route("/")
+async def handler(request):
+ return text("Done.", headers={"content-language": "en-US"})
+
+@app.middleware("response")
+async def add_csp(request, response):
+ response.headers["content-security-policy"] = "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';base-uri 'self';form-action 'self'"
+```
+
+:---
+
+---:1
+
+A common [middleware](middleware.md) you might want is to add a `X-Request-ID` header to every response. As stated above: `request.id` will provide the ID from the incoming request. But, even if no ID was supplied in the request headers, one will be automatically supplied for you.
+
+[See API docs for more details](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#sanic.request.Request.id)
+
+:--:1
+
+```python
+@app.route("/")
+async def handler(request):
+ return text(str(request.id))
+
+@app.on_response
+async def add_request_id_header(request, response):
+ response.headers["X-Request-ID"] = request.id
+```
+
+```bash
+$ curl localhost:8000 -i
+HTTP/1.1 200 OK
+X-Request-ID: 805a958e-9906-4e7a-8fe0-cbe83590431b
+content-length: 36
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+805a958e-9906-4e7a-8fe0-cbe83590431b
+```
+
+:---
From a6e31d5c829c4f0afc17a3318ba2d8b8df2faa02 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:14 +0300
Subject: [PATCH 020/776] New translations listeners.md (Japanese)
---
src/ja/guide/basics/listeners.md | 73 +++++++++++++++++++++-----------
1 file changed, 48 insertions(+), 25 deletions(-)
diff --git a/src/ja/guide/basics/listeners.md b/src/ja/guide/basics/listeners.md
index 008a168b8e..7ba0b59587 100644
--- a/src/ja/guide/basics/listeners.md
+++ b/src/ja/guide/basics/listeners.md
@@ -1,20 +1,27 @@
# Listeners
-Sanicは、アプリケーションのライフサイクルにオペレーションを注入する6つの機会を提供します。
+Sanicは、アプリケーションのライフサイクルにオペレーションを注入する6つの機会を提供します。 This does not include the [signals](../advanced/signals.md), which allow further injection customization.
-メインのSanicプロセスで**のみ**を実行するものが2つあります(つまり、`sanic server.app`への呼び出しごとに1回です。)。
+メインのSanicプロセスで**のみ**を実行するものが2つあります(つまり、`sanic server.app`への呼び出しごとに1回です。
- `main_process_start`
- `main_process_stop`
サーバの起動時または終了時にスタートアップ/ティアダウンコードを実行できるようにするには、4つの方法があります。
+- `reload_process_start`
+- `reload_process_stop`
+
+*Added `reload_process_start` and `reload_process_stop` in v22.3*
+
+There are four (4) that enable you to execute startup/teardown code as your server starts or closes.
+
- `before_server_start`
- `after_server_start`
- `before_server_stop`
- `after_server_stop`
-ワーカプロセスのライフサイクルは次のようになります。
+関数をリスナーとして設定するプロセスは、ルートの宣言に似ています。
```mermaid
sequenceDiagram
@@ -60,16 +67,27 @@ loop
end
Note over Process: exit
```
+
+The reloader process live outside of this worker process inside of a process that is responsible for starting and stopping the Sanic processes. Consider the following example:
+
+```python
+async def setup_db(app, loop):
+ app.ctx.db = await db_setup()
+
+app.register_listener(setup_db, "before_server_start")
+```
+
+If this application were run with auto-reload turned on, the `reload_start` function would be called once. This is contrasted with `main_start`, which would be run every time a file is save and the reloader restarts the applicaition process.
+
## Attaching a listener
---:1
-関数をリスナーとして設定するプロセスは、ルートの宣言に似ています。
+`Sanic`アプリインスタンスにも便利なデコレーターがある。 :--:1
-注入される2つの引数は、現在実行中の`Sanic()`インスタンスと現在実行中のループです。
-:--:1
+The currently running `Sanic()` instance is injected into the listener. :--:1
```python
-async def setup_db(app, loop):
+async def setup_db(app):
app.ctx.db = await db_setup()
app.register_listener(setup_db, "before_server_start")
@@ -78,8 +96,15 @@ app.register_listener(setup_db, "before_server_start")
---:1
-`Sanic`アプリインスタンスにも便利なデコレーターがある。
-:--:1
+The `Sanic` app instance also has a convenience decorator. :--:1
+```python
+@app.before_server_start
+async def setup_db(app, loop):
+ app.ctx.db = await db_setup()
+```
+:---
+
+---:1 Prior to v22.3, both the application instance and the current event loop were injected into the function. However, only the application instance is injected by default. If your function signature will accept both, then both the application and the loop will be injected as shown here. :--:1
```python
@app.listener("before_server_start")
async def setup_db(app, loop):
@@ -89,12 +114,12 @@ async def setup_db(app, loop):
---:1
-デコレーターをさらに短くすることができます。これは、オートコンプリート機能を備えたIDEがある場合に便利です。
+デコレーターをさらに短くすることができます。 これは、オートコンプリート機能を備えたIDEがある場合に便利です。
:--:1
```python
@app.before_server_start
-async def setup_db(app, loop):
+async def setup_db(app):
app.ctx.db = await db_setup()
```
:---
@@ -103,16 +128,16 @@ async def setup_db(app, loop):
リスナーは、起動時に宣言された順序で実行され、ティアダウン時に宣言された順序とは逆の順序で実行されます。
-| | Phase | Order |
-|-----------------------|-----------------|---------|
-| `main_process_start` | main startup | regular :smiley: |
-| `before_server_start` | worker startup | regular :smiley: |
-| `after_server_start` | worker startup | regular :smiley: |
+| | Phase | Order |
+| --------------------- | --------------- | ---------------------------- |
+| `main_process_start` | main startup | regular :smiley: |
+| `before_server_start` | worker startup | regular :smiley: |
+| `after_server_start` | worker startup | regular :smiley: |
| `before_server_stop` | worker shutdown | reverse :upside_down_face: |
| `after_server_stop` | worker shutdown | reverse :upside_down_face: |
| `main_process_stop` | main shutdown | reverse :upside_down_face: |
-次の設定では、2人のワーカーを実行した場合にコンソールにこのメッセージが表示されます。
+実際には、`before_server_start`ハンドラの最初のリスナーがデータベース接続を設定すると、その後に登録されたリスナーは、起動時と停止時の両方でその接続が有効であることを信頼できます。
---:1
@@ -182,18 +207,16 @@ async def listener_8(app, loop):
- `pid: 1111111` - Worker 1
- `pid: 1222222` - Worker 2
-*この例では、1つのワーカーをすべてグループ化し、次に別のワーカーをすべてグループ化していますが、実際にはこれらのワーカーは別々のプロセスで実行されているため、プロセス間の順序付けは保証されません。ただし、1人のワーカーが常にその順序を維持することは確実です。*
-:---
+*この例では、1つのワーカーをすべてグループ化し、次に別のワーカーをすべてグループ化していますが、実際にはこれらのワーカーは別々のプロセスで実行されているため、プロセス間の順序付けは保証されません。 ただし、1人のワーカーが常にその順序を維持することは確実です。 * :---
-::: tip FYI
-The practical result of this is that if the first listener in `before_server_start` handler setups a database connection, listeners that are registered after it can rely upon that connection being alive both when they are started and stopped.
-:::
+::: tip FYI The practical result of this is that if the first listener in `before_server_start` handler setups a database connection, listeners that are registered after it can rely upon that connection being alive both when they are started and stopped. :::
## ASGI Mode
-実際には、`before_server_start`ハンドラの最初のリスナーがデータベース接続を設定すると、その後に登録されたリスナーは、起動時と停止時の両方でその接続が有効であることを信頼できます。
+If you are running your application with an ASGI server, then make note of the following changes:
-- `main_process_start`と`main_process_stop`は**無視されます。**
-- `before_server_start`はできるだけ早く動きます。,そして`after_server_start`の前に実行されます。, しかし、技術的には、サーバーはすでにその時点で実行されています
- `after_server_stop`はできるだけ遅く実行され、`before_server_stop`の後になりますが、技術的には、サーバーはまだその時点で実行されています
+- `main_process_start`と`main_process_stop`は**無視されます。 **
+- `before_server_start`はできるだけ早く動きます。 ,そして`after_server_start`の前に実行されます。 , しかし、技術的には、サーバーはすでにその時点で実行されています
+- `after_server_stop` will run as late as it can, and will be after `before_server_stop`, but technically, the server is still running at that point
From 744238ccc8b49a773a6e2458134ae8b42881fe56 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:15 +0300
Subject: [PATCH 021/776] New translations websockets.md (Portuguese,
Brazilian)
---
src/pt/guide/advanced/websockets.md | 56 +++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
create mode 100644 src/pt/guide/advanced/websockets.md
diff --git a/src/pt/guide/advanced/websockets.md b/src/pt/guide/advanced/websockets.md
new file mode 100644
index 0000000000..3ac4c2eaec
--- /dev/null
+++ b/src/pt/guide/advanced/websockets.md
@@ -0,0 +1,56 @@
+# Websockets
+
+Sanic provides an easy to use abstraction on top of [websockets](https://websockets.readthedocs.io/en/stable/).
+
+
+## Routing
+
+---:1
+
+Websocket handlers can be hooked up to the router similar to regular handlers. :--:1
+```python
+async def feed(request, ws):
+ pass
+
+app.add_websocket_route(feed, "/feed")
+```
+```python
+@app.websocket("/feed")
+async def feed(request, ws):
+ pass
+```
+:---
+
+## Handler
+
+
+---:1
+
+Typically, a websocket handler will want to hold open a loop.
+
+It can then use the `send()` and `recv()` methods on the second object injected into the handler.
+
+This example is a simple endpoint that echos back to the client messages that it receives. :--:1
+```python
+
+@app.websocket("/feed")
+async def feed(request, ws):
+ while True:
+ data = "hello!"
+ print("Sending: " + data)
+ await ws.send(data)
+ data = await ws.recv()
+ print("Received: " + data)
+```
+:---
+## Configuration
+
+See [configuration section](/guide/deployment/configuration.md) for more details.
+```python
+app.config.WEBSOCKET_MAX_SIZE = 2 ** 20
+app.config.WEBSOCKET_MAX_QUEUE = 32
+app.config.WEBSOCKET_READ_LIMIT = 2 ** 16
+app.config.WEBSOCKET_WRITE_LIMIT = 2 ** 16
+app.config.WEBSOCKET_PING_INTERVAL = 20
+app.config.WEBSOCKET_PING_TIMEOUT = 20
+```
From 53383adff32b6fdd973b556cbcbd0e6f80087b97 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:16 +0300
Subject: [PATCH 022/776] New translations websockets.md (Korean)
---
src/ko/guide/advanced/websockets.md | 56 +++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
create mode 100644 src/ko/guide/advanced/websockets.md
diff --git a/src/ko/guide/advanced/websockets.md b/src/ko/guide/advanced/websockets.md
new file mode 100644
index 0000000000..3ac4c2eaec
--- /dev/null
+++ b/src/ko/guide/advanced/websockets.md
@@ -0,0 +1,56 @@
+# Websockets
+
+Sanic provides an easy to use abstraction on top of [websockets](https://websockets.readthedocs.io/en/stable/).
+
+
+## Routing
+
+---:1
+
+Websocket handlers can be hooked up to the router similar to regular handlers. :--:1
+```python
+async def feed(request, ws):
+ pass
+
+app.add_websocket_route(feed, "/feed")
+```
+```python
+@app.websocket("/feed")
+async def feed(request, ws):
+ pass
+```
+:---
+
+## Handler
+
+
+---:1
+
+Typically, a websocket handler will want to hold open a loop.
+
+It can then use the `send()` and `recv()` methods on the second object injected into the handler.
+
+This example is a simple endpoint that echos back to the client messages that it receives. :--:1
+```python
+
+@app.websocket("/feed")
+async def feed(request, ws):
+ while True:
+ data = "hello!"
+ print("Sending: " + data)
+ await ws.send(data)
+ data = await ws.recv()
+ print("Received: " + data)
+```
+:---
+## Configuration
+
+See [configuration section](/guide/deployment/configuration.md) for more details.
+```python
+app.config.WEBSOCKET_MAX_SIZE = 2 ** 20
+app.config.WEBSOCKET_MAX_QUEUE = 32
+app.config.WEBSOCKET_READ_LIMIT = 2 ** 16
+app.config.WEBSOCKET_WRITE_LIMIT = 2 ** 16
+app.config.WEBSOCKET_PING_INTERVAL = 20
+app.config.WEBSOCKET_PING_TIMEOUT = 20
+```
From dd91a9806e518ff27890998275ed8ee7172bbaa5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:18 +0300
Subject: [PATCH 023/776] New translations signals.md (Japanese)
---
src/ja/guide/advanced/signals.md | 102 +++++++++++++------------------
1 file changed, 43 insertions(+), 59 deletions(-)
diff --git a/src/ja/guide/advanced/signals.md b/src/ja/guide/advanced/signals.md
index 359f64a5a4..7ed86a8294 100644
--- a/src/ja/guide/advanced/signals.md
+++ b/src/ja/guide/advanced/signals.md
@@ -18,9 +18,7 @@ async def handle_registration(request):
## signalを追加する
----:1
-信号を追加するためのAPIは、ルートの追加と非常によく似ています。
-:--:1
+---:1 信号を追加するためのAPIは、ルートの追加と非常によく似ています。 :--:1 :--:1
```python
async def my_signal_handler():
print("something happened")
@@ -29,9 +27,7 @@ app.add_signal(my_signal_handler, "something.happened.ohmy")
```
:---
----:1
-ただし、おそらくもう少し便利な方法は、組み込みのデコレータを使用することです。
-:--:1
+---:1 ただし、おそらくもう少し便利な方法は、組み込みのデコレータを使用することです。 :--:1 :--:1
```python
@app.signal("something.happened.ohmy")
async def my_signal_handler():
@@ -39,9 +35,24 @@ async def my_signal_handler():
```
:---
----:1
-信号は設計図で宣言することもできます
-:--:1
+---:1 If the signal requires conditions, make sure to add them while adding the handler. :--:1
+```python
+async def my_signal_handler1():
+ print("something happened")
+
+app.add_signal(
+ my_signal_handler,
+ "something.happened.ohmy1",
+ conditions={"some_condition": "value"}
+)
+
+@app.signal("something.happened.ohmy2", conditions={"some_condition": "value"})
+async def my_signal_handler2():
+ print("something happened")
+```
+:---
+
+---:1 信号は設計図で宣言することもできます :--:1
```python
bp = Blueprint("foo")
@@ -53,10 +64,10 @@ async def my_signal_handler():
## signalsを設計する
-新しい信号を作成することに加えて、Sanic自体からディスパッチされる組み込み信号がいくつかあります。これらの信号は、開発者に要求とサーバーのライフサイクルに機能を追加する機会を増やすために存在します。
+新しい信号を作成することに加えて、Sanic自体からディスパッチされる組み込み信号がいくつかあります。 これらの信号は、開発者に要求とサーバーのライフサイクルに機能を追加する機会を増やすために存在します。
+
+---:1 おそらく、例は説明しやすいです: :--:1
----:1
-新しいシグナルを作成することに加えて、Sanic自体からディスパッチされる多くの組み込みシグナルがあります。これらのシグナルは、開発者がリクエストとサーバーのライフサイクルに機能を追加する機会を増やすために存在します。
他のシグナルと同じように、アプリケーションまたはブループリントインスタンスにアタッチできます。
@@ -72,7 +83,7 @@ async def my_signal_handler(conn_info):
これらの信号は、ハンドラーが取る引数、およびアタッチする条件(存在する場合)とともに、利用可能な信号です。
-| イベント名 | 変数 | 条件 |
+| イベント名 | 変数 | 条件 |
| -------------------------- | ------------------------------- | --------------------------------------------------------- |
| `http.routing.before` | request | |
| `http.routing.after` | request, route, kwargs, handler | |
@@ -92,10 +103,7 @@ async def my_signal_handler(conn_info):
| `server.shutdown.before` | app, loop | |
| `server.shutdown.after` | app, loop | |
-::: new NEW in v21.12
----:1
-ビルトインシグナルを使いやすくするために、許可されたビルトインをすべて含む `Enum` オブジェクトが用意されています。最近の IDE では、イベント名の完全なリストを文字列として覚えておく必要がないので、これは便利です。
-:--:1
+::: new NEW in v21.12 ---:1 ビルトインシグナルを使いやすくするために、許可されたビルトインをすべて含む `Enum` オブジェクトが用意されています。 最近の IDE では、イベント名の完全なリストを文字列として覚えておく必要がないので、これは便利です。 :--:1 :--:1
```python
from sanic.signals import Event
@@ -107,26 +115,20 @@ async def my_signal_handler(conn_info):
## イベント
----:1
-信号は_event_に基づいています。イベントは、単に次のパターンの文字列です。
-:--:1
+---:1 信号は_event_に基づいています。 イベントは、単に次のパターンの文字列です。 :--:1
```
namespace.reference.action
```
:---
-::: 次に
-イベントには3つの部分が必要です。何を使うべきかわからない場合は、次のパターンを試してください。
+::: 次に イベントには3つの部分が必要です。 何を使うべきかわからない場合は、次のパターンを試してください。
- `my_app.something.happened`
-- `sanic.notice.hello`
-:::
+- `sanic.notice.hello` :::
### イベントパラメータ
----:1
-イベントは「動的」であり、[pathパラメータ](../basics/routing.md#path-parameters)と同じ構文を使用して宣言できます。これにより、任意の値に基づいてマッチングできます。
-:--:1
+---:1 イベントは「動的」であり、[pathパラメータ](../basics/routing.md#path-parameters)と同じ構文を使用して宣言できます。 これにより、任意の値に基づいてマッチングできます。 :--:1 :--:1
```python
@app.signal("foo.bar.")
async def signal_handler(thing):
@@ -139,28 +141,22 @@ async def trigger(request):
```
:---
-許可された型定義の詳細については、[pathパラメータ](../basics/routing.md#path-parameters)をチェックしてください。
+---:1 シグナルハンドラの実行に加えて、アプリケーションはイベントがトリガーされるのを待つことができます。 :--:1
-::: 注意
-イベントの3番目の部分(「アクション」)のみが動的です。
+::: 注意 イベントの3番目の部分(「アクション」)のみが動的です。
- `foo.bar.` :ok:
-- `foo..baz` :x:
-:::
+- `foo..baz` :x: :::
### 待つ
----:1
-シグナルハンドラの実行に加えて、アプリケーションはイベントがトリガーされるのを待つことができます。
-:--:1
+---:1 In addition to executing a signal handler, your application can wait for an event to be triggered. :--:1
```python
await app.event("foo.bar.baz")
```
:---
----:1
-**大事**: 待つことはブロッキング機能です。したがって、これを[バックグラウンドタスク](../basics/tasks.md)で実行する必要があります。
-:--:1
+---:1 **大事**: 待つことはブロッキング機能です。 したがって、これを[バックグラウンドタスク](../basics/tasks.md)で実行する必要があります。 :--:1 :--:1
```python
async def wait_for_event(app):
while True:
@@ -174,9 +170,7 @@ async def after_server_start(app, loop):
```
:---
----:1
-イベントが動的パスで定義されている場合は、`*`を使用して任意のアクションをキャッチできます。
-:--:1
+---:1 イベントが動的パスで定義されている場合は、`*`を使用して任意のアクションをキャッチできます。 :--:1 :--:1
```python
@app.signal("foo.bar.")
@@ -190,12 +184,10 @@ await app.event("foo.bar.*")
*将来的には、Sanicは開発者がライフサイクルイベントに参加するのを支援するために、いくつかのイベントを自動的にディスパッチします。*
----:1
-イベントをDispatchすると、2つのことを行います。
+---:1 イベントをDispatchすると、2つのことを行います。
1. イベントで定義されたシグナルハンドラを実行し、
-2. イベントが完了するまで「待っている」ことをすべて解決します。
-:--:1
+2. イベントが完了するまで「待っている」ことをすべて解決します。 :--:1 :--:1
```python
@app.signal("foo.bar.")
async def foo_bar(thing):
@@ -210,9 +202,7 @@ thing=baz
### Context
----:1
-場合によっては、信号ハンドラに余分な情報を渡す必要があるかもしれません。上記の最初の例では、電子メール登録プロセスにユーザーの電子メールアドレスを指定してほしかった。
-:--:1
+---:1 場合によっては、信号ハンドラに余分な情報を渡す必要があるかもしれません。 上記の最初の例では、電子メール登録プロセスにユーザーの電子メールアドレスを指定してほしかった。 :--:1 :--:1
```python
@app.signal("user.registration.created")
async def send_registration_email(**context):
@@ -230,15 +220,13 @@ await app.dispatch(
::: tip FYI
信号はバックグラウンドタスクでディスパッチされます。
-:::
+::: :::
### Blueprints
-青写真信号のdispatchは、[middleware](../basics/middleware.md)と同様に機能します。アプリレベルから行われるものは、青写真まで流れ落ちます。ただし、青写真でディスパッチすると、その青写真で定義されている信号のみが実行されます。
+青写真信号のdispatchは、[middleware](../basics/middleware.md)と同様に機能します。 アプリレベルから行われるものは、青写真まで流れ落ちます。 ただし、青写真でディスパッチすると、その青写真で定義されている信号のみが実行されます。
----:1
-おそらく、例は説明しやすいです:
-:--:1
+---:1 `app.dispatch("foo.bar.baz")`を実行すると、両方の信号が実行されます。 :--:1
```python
bp = Blueprint("bp")
@@ -257,9 +245,7 @@ def bp_signal():
```
:---
----:1
-`app.dispatch("foo.bar.baz")`を実行すると、両方の信号が実行されます。
-:--:1
+---:1 Running `app.dispatch("foo.bar.baz")` will execute both signals. :--:1
```python
await app.dispatch("foo.bar.baz")
assert app_counter == 1
@@ -267,9 +253,7 @@ assert bp_counter == 1
```
:---
----:1
-`bp.dispatch("foo.bar.baz")`を実行すると、ブループリント信号のみが実行されます。
-:--:1
+---:1 `bp.dispatch("foo.bar.baz")`を実行すると、ブループリント信号のみが実行されます。 :--:1 :--:1
```python
await bp.dispatch("foo.bar.baz")
assert app_counter == 1
From c56b6818d2d797dd9fea881ea657579d3fbc60c3 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:19 +0300
Subject: [PATCH 024/776] New translations README.md (Portuguese, Brazilian)
---
src/pt/guide/advanced/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/advanced/README.md
diff --git a/src/pt/guide/advanced/README.md b/src/pt/guide/advanced/README.md
new file mode 100644
index 0000000000..931fae06c0
--- /dev/null
+++ b/src/pt/guide/advanced/README.md
@@ -0,0 +1 @@
+# Advanced
From 915b17fbcb2736d3d77bcbd6883fb7dd4882ce0d Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:21 +0300
Subject: [PATCH 025/776] New translations class-based-views.md (Japanese)
---
src/ja/guide/advanced/class-based-views.md | 29 ++++++++--------------
1 file changed, 11 insertions(+), 18 deletions(-)
diff --git a/src/ja/guide/advanced/class-based-views.md b/src/ja/guide/advanced/class-based-views.md
index 773a6652cf..742ae67c38 100644
--- a/src/ja/guide/advanced/class-based-views.md
+++ b/src/ja/guide/advanced/class-based-views.md
@@ -8,8 +8,7 @@
APIを設計する際の一般的なパターンは、HTTPメソッドに依存する同じエンドポイントに複数の機能を持つことです。
-これらのオプションは両方とも機能しますが、優れた設計慣行ではなく、プロジェクトが成長するにつれて時間の経過とともに維持するのが難しい場合があります。
-:--:1
+これらのオプションは両方とも機能しますが、優れた設計慣行ではなく、プロジェクトが成長するにつれて時間の経過とともに維持するのが難しい場合があります。 :--:1 :--:1
```python
@app.get("/foo")
async def foo_get(request):
@@ -38,18 +37,17 @@ async def bar(request):
### 解決策
-クラスベースのビューは、単に要求に対する応答動作を実装するクラスです。これらは、同じエンドポイントで異なるHTTPリクエストタイプの処理を区分する方法を提供します。
-:--:1
+クラスベースのビューは、単に要求に対する応答動作を実装するクラスです。 これらは、同じエンドポイントで異なるHTTPリクエストタイプの処理を区分する方法を提供します。 :--:1 :--:1
```python
from sanic.views import HTTPMethodView
class FooBar(HTTPMethodView):
async def get(self, request):
...
-
+
async def post(self, request):
...
-
+
async def put(self, request):
...
@@ -59,11 +57,11 @@ app.add_route(FooBar.as_view(), "/foobar")
## ビューの定義
-クラスベースのビューは、`HTTPMethodView` をサブクラス化する必要があります。その後、対応するHTTPメソッドの名前でクラスメソッドを実装できます。定義されたメソッドを持たない要求を受信すると、`405: Method not allowed` 応答が生成されます。
+クラスベースのビューは、`HTTPMethodView` をサブクラス化する必要があります。 その後、対応するHTTPメソッドの名前でクラスメソッドを実装できます。 定義されたメソッドを持たない要求を受信すると、`405: Method not allowed` 応答が生成されます。
---:1
-エンドポイントにクラスベースのビューを登録するには、`app.add_route`メソッドが使用されます。最初の引数は、メソッド `as_view` が呼び出された定義されたクラスで、2 番目の引数は URL エンドポイントである必要があります。
+エンドポイントにクラスベースのビューを登録するには、`app.add_route`メソッドが使用されます。 最初の引数は、メソッド `as_view` が呼び出された定義されたクラスで、2 番目の引数は URL エンドポイントである必要があります。
利用可能な方法は:
@@ -73,8 +71,7 @@ app.add_route(FooBar.as_view(), "/foobar")
- patch
- delete
- head
-- options
-:--:1
+- options :--:1
```python
from sanic.views import HTTPMethodView
from sanic.response import text
@@ -105,8 +102,7 @@ app.add_route(SimpleView.as_view(), "/")
---:1
-[ルーティングセクション](/guide/basics/routing.md)で説明されているとおりにパスパラメータを使用できます。
-:--:1
+[ルーティングセクション](/guide/basics/routing.md)で説明されているとおりにパスパラメータを使用できます。 :--:1 :--:1
```python
class NameView(HTTPMethodView):
@@ -130,8 +126,7 @@ app.add_route(NameView.as_view(), "/")
### すべての方法に適用する
-クラスにデコレータを追加する場合は、`デコレータ`クラス変数を設定できます。これらは、`as_view`が呼び出されるとクラスに適用されます。
-:--:1
+クラスにデコレータを追加する場合は、`デコレータ`クラス変数を設定できます。 これらは、`as_view`が呼び出されるとクラスに適用されます。 :--:1 :--:1
```python
class ViewWithDecorator(HTTPMethodView):
decorators = [some_decorator_here]
@@ -150,8 +145,7 @@ app.add_route(ViewWithDecorator.as_view(), "/url")
### 個々の方法に適用する
-しかし、すべてのメソッドではなく、いくつかのメソッドを飾りたい場合は、ここに示すようにできます。
-:--:1
+しかし、すべてのメソッドではなく、いくつかのメソッドを飾りたい場合は、ここに示すようにできます。 :--:1 :--:1
```python
class ViewWithSomeDecorator(HTTPMethodView):
@@ -172,8 +166,7 @@ class ViewWithSomeDecorator(HTTPMethodView):
## URLを作成
---:1
-これは、クラス名がエンドポイントの一部であることを除いて、[他のURLの生成](/guide/basics/routing.md#generating-a-url)と同じように機能します。
-:--:1
+これは、クラス名がエンドポイントの一部であることを除いて、[他のURLの生成](/guide/basics/routing.md#generating-a-url)と同じように機能します。 :--:1 :--:1
```python
@app.route("/")
def index(request):
From 7dd5c01421aaedf602b128984f8b237132408854 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:22 +0300
Subject: [PATCH 026/776] New translations class-based-views.md (Korean)
---
src/ko/guide/advanced/class-based-views.md | 184 +++++++++++++++++++++
1 file changed, 184 insertions(+)
create mode 100644 src/ko/guide/advanced/class-based-views.md
diff --git a/src/ko/guide/advanced/class-based-views.md b/src/ko/guide/advanced/class-based-views.md
new file mode 100644
index 0000000000..ebc7a976de
--- /dev/null
+++ b/src/ko/guide/advanced/class-based-views.md
@@ -0,0 +1,184 @@
+# Class Based Views
+
+## Why use them?
+
+---:1
+
+### The problem
+
+A common pattern when designing an API is to have multiple functionality on the same endpoint that depends upon the HTTP method.
+
+While both of these options work, they are not good design practices and may be hard to maintain over time as your project grows. :--:1
+```python
+@app.get("/foo")
+async def foo_get(request):
+ ...
+
+@app.post("/foo")
+async def foo_post(request):
+ ...
+
+@app.put("/foo")
+async def foo_put(request):
+ ...
+
+@app.route("/bar", methods=["GET", "POST", "PATCH"])
+async def bar(request):
+ if request.method == "GET":
+ ...
+ elif request.method == "POST":
+ ...
+ elif request.method == "PATCH":
+ ...
+```
+:---
+
+---:1
+
+### The solution
+
+Class-based views are simply classes that implement response behavior to requests. They provide a way to compartmentalize handling of different HTTP request types at the same endpoint. :--:1
+```python
+from sanic.views import HTTPMethodView
+
+class FooBar(HTTPMethodView):
+ async def get(self, request):
+ ...
+
+ async def post(self, request):
+ ...
+
+ async def put(self, request):
+ ...
+
+app.add_route(FooBar.as_view(), "/foobar")
+```
+:---
+
+## Defining a view
+
+A class-based view should subclass `HTTPMethodView`. You can then implement class methods with the name of the corresponding HTTP method. If a request is received that has no defined method, a `405: Method not allowed` response will be generated.
+
+---:1
+
+To register a class-based view on an endpoint, the `app.add_route` method is used. The first argument should be the defined class with the method `as_view` invoked, and the second should be the URL endpoint.
+
+The available methods are:
+
+- get
+- post
+- put
+- patch
+- delete
+- head
+- options :--:1
+```python
+from sanic.views import HTTPMethodView
+from sanic.response import text
+
+class SimpleView(HTTPMethodView):
+
+ def get(self, request):
+ return text("I am get method")
+
+ # You can also use async syntax
+ async def post(self, request):
+ return text("I am post method")
+
+ def put(self, request):
+ return text("I am put method")
+
+ def patch(self, request):
+ return text("I am patch method")
+
+ def delete(self, request):
+ return text("I am delete method")
+
+app.add_route(SimpleView.as_view(), "/")
+```
+:---
+
+## Path parameters
+
+---:1
+
+You can use path parameters exactly as discussed in [the routing section](/guide/basics/routing.md). :--:1
+```python
+class NameView(HTTPMethodView):
+
+ def get(self, request, name):
+ return text("Hello {}".format(name))
+
+app.add_route(NameView.as_view(), "/")
+```
+:---
+
+## Decorators
+
+As discussed in [the decorators section](/guide/best-practices/decorators.md), often you will need to add functionality to endpoints with the use of decorators. You have two options with CBV:
+
+1. Apply to _all_ HTTP methods in the view
+2. Apply individually to HTTP methods in the view
+
+Let's see what the options look like:
+
+---:1
+
+### Apply to all methods
+
+If you want to add any decorators to the class, you can set the `decorators` class variable. These will be applied to the class when `as_view` is called. :--:1
+```python
+class ViewWithDecorator(HTTPMethodView):
+ decorators = [some_decorator_here]
+
+ def get(self, request, name):
+ return text("Hello I have a decorator")
+
+ def post(self, request, name):
+ return text("Hello I also have a decorator")
+
+app.add_route(ViewWithDecorator.as_view(), "/url")
+```
+:---
+
+---:1
+
+### Apply to individual methods
+
+But if you just want to decorate some methods and not all methods, you can as shown here. :--:1
+```python
+class ViewWithSomeDecorator(HTTPMethodView):
+
+ @staticmethod
+ @some_decorator_here
+ def get(request, name):
+ return text("Hello I have a decorator")
+
+ def post(self, request, name):
+ return text("Hello I don"t have any decorators")
+
+ @some_decorator_here
+ def patch(self, request, name):
+ return text("Hello I have a decorator")
+```
+:---
+
+## Generating a URL
+---:1
+
+This works just like [generating any other URL](/guide/basics/routing.md#generating-a-url), except that the class name is a part of the endpoint. :--:1
+```python
+@app.route("/")
+def index(request):
+ url = app.url_for("SpecialClassView")
+ return redirect(url)
+
+
+class SpecialClassView(HTTPMethodView):
+ def get(self, request):
+ return text("Hello from the Special Class View!")
+
+
+app.add_route(SpecialClassView.as_view(), "/special_class_view")
+```
+:---
From e38b681d36adfff02ba77bea7ed7080a0e4ec127 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:23 +0300
Subject: [PATCH 027/776] New translations class-based-views.md (Chinese
Simplified)
---
src/zh/guide/advanced/class-based-views.md | 84 +++++++++++-----------
1 file changed, 42 insertions(+), 42 deletions(-)
diff --git a/src/zh/guide/advanced/class-based-views.md b/src/zh/guide/advanced/class-based-views.md
index ed7b82d368..8d95781696 100644
--- a/src/zh/guide/advanced/class-based-views.md
+++ b/src/zh/guide/advanced/class-based-views.md
@@ -1,6 +1,6 @@
# 基于类的视图(Class Based Views)
-## 为什么要使用它?(Why use them?)
+## 为什么要使用它?
---:1
@@ -8,11 +8,20 @@
在日常的 API 设计过程中,将不同的响应函数通过不同的 HTTP 方法挂载到同一路由上是一种常用的设计模式。
-虽然我们之前讲到的方式也能够实现同样的效果,但事实证明它们并不是一种好的设计实践。随着时间的推移以及项目的发展,它们将变得越来越难以维护:
+虽然我们之前讲到的方式也能够实现同样的效果,但事实证明它们并不是一种好的设计实践。 随着时间的推移以及项目的发展,它们将变得越来越难以维护: :--:1
+```python
+@app.get("/foo")
+async def foo_get(request):
+ ...
-:--:1
+@app.post("/foo")
+async def foo_post(request):
+ ...
+
+@app.put("/foo")
+async def foo_put(request):
+ ...
-```python
@app.get("/foo")
async def foo_get(request):
...
@@ -33,45 +42,52 @@ async def bar(request):
...
elif request.method == "PATCH":
...
+ elif request.method == "POST":
+ ...
+ elif request.method == "PATCH":
+ ...
```
-
:---
---:1
### 破局(The solution)
-基于类的视图是一种实现了响应请求行为的类,该类提供了一种在同一路由上分隔处理不同 HTTP 请求类型的方法。
-
-:--:1
-
+Class-based views are simply classes that implement response behavior to requests. They provide a way to compartmentalize handling of different HTTP request types at the same endpoint. :--:1
```python
from sanic.views import HTTPMethodView
class FooBar(HTTPMethodView):
async def get(self, request):
...
-
+
async def post(self, request):
...
-
+
async def put(self, request):
...
app.add_route(FooBar.as_view(), "/foobar")
-```
+ async def post(self, request):
+ ...
+
+ async def put(self, request):
+ ...
+
+app.add_route(FooBar.as_view(), "/foobar")
+```
:---
## 定义视图(Defining a view)
-基于类的视图应该是 `HTTPMethodView` 的子类 。您可以使用相应的 HTTP 方法的名称实现类方法。如果收到的请求没有定义的方法,将生成 `405: Method not allowed` 响应。
+基于类的视图应该是 `HTTPMethodView` 的子类 。 您可以使用相应的 HTTP 方法的名称实现类方法。 如果收到的请求没有定义的方法,将生成 `405: Method not allowed` 响应。
---:1
-若想要将基于类的视图挂载到路由上,则应该使用 `app.add_route` 方法,其中第一个参数是使用 `as_view` 调用后的已经定义好的类,第二个参数是要分配的 URL 路由。
+若想要将基于类的视图挂载到路由上,则应该使用 `app.add_route` 方法,其中第一个参数是使用 `as_view` 调用后的已经定义好的类,第二个参数是要分配的 URL 路由。 The first argument should be the defined class with the method `as_view` invoked, and the second should be the URL endpoint.
-HTTPMethodView 支持的方法有:
+The available methods are:
- get
- post
@@ -80,9 +96,6 @@ HTTPMethodView 支持的方法有:
- delete
- head
- options
-
-:--:1
-
```python
from sanic.views import HTTPMethodView
from sanic.response import text
@@ -107,17 +120,13 @@ class SimpleView(HTTPMethodView):
app.add_route(SimpleView.as_view(), "/")
```
-
:---
## 路由参数(Path parameters)
---:1
-您完全可以按照我们在 [路由](/zh/guide/basics/routing.md) 这一章节所讨论的使用方式来使用路由参数。
-
-:--:1
-
+You can use path parameters exactly as discussed in [the routing section](/guide/basics/routing.md). :--:1
```python
class NameView(HTTPMethodView):
@@ -126,26 +135,22 @@ class NameView(HTTPMethodView):
app.add_route(NameView.as_view(), "/")
```
-
:---
## 装饰器(Decorators)
-就像 [装饰器](/zh/guide/best-practices/decorators.md) 这一章节所述,您可能经常需要使用装饰器来对您的响应函数添加额外的功能,基于类的视图给出了两种方式来添加装饰器:
+就像 [装饰器](/zh/guide/best-practices/decorators.md) 这一章节所述,您可能经常需要使用装饰器来对您的响应函数添加额外的功能,基于类的视图给出了两种方式来添加装饰器: You have two options with CBV:
-1. 应用于视图中的 *所有* HTTP 方法
-2. 独自应用于视图中的 *指定* HTTP 方法
+1. 应用于视图中的 *所有* HTTP 方法
+2. 独自应用于视图中的 *指定* HTTP 方法
-让我们分别来看看他们的用法:
+您完全可以按照我们在 [路由](/zh/guide/basics/routing.md) 这一章节所讨论的使用方式来使用路由参数。
---:1
### 用于所有方法(Apply to all methods)
-如果您想要添加应用于所有方法的类,您可以通过类变量 `decorators` 来实现,设置后,这些装饰器将在调用 `as_view` 时应用于类。
-
-:--:1
-
+如果您想要添加应用于所有方法的类,您可以通过类变量 `decorators` 来实现,设置后,这些装饰器将在调用 `as_view` 时应用于类。 These will be applied to the class when `as_view` is called. :--:1
```python
class ViewWithDecorator(HTTPMethodView):
decorators = [some_decorator_here]
@@ -164,10 +169,7 @@ app.add_route(ViewWithDecorator.as_view(), "/url")
### 应用于单个方法(Apply to individual methods)
-但是,如果您只是想装饰一些方法,而不是所有的方法,您可以这样使用:
-
-:--:1
-
+但是,如果您只是想装饰一些方法,而不是所有的方法,您可以这样使用: :--:1
```python
class ViewWithSomeDecorator(HTTPMethodView):
@@ -186,13 +188,9 @@ class ViewWithSomeDecorator(HTTPMethodView):
:---
## URL生成(Generating a URL)
-
---:1
-和路由章节中的 [URL生成](/zh/guide/basics/routing.md#generating-a-url) 一样,除了指定需要添加的类之外,其他的使用方法是一致的。
-
-:--:1
-
+和路由章节中的 [URL生成](/zh/guide/basics/routing.md#generating-a-url) 一样,除了指定需要添加的类之外,其他的使用方法是一致的。 :--:1
```python
@app.route("/")
def index(request):
@@ -206,6 +204,8 @@ class SpecialClassView(HTTPMethodView):
app.add_route(SpecialClassView.as_view(), "/special_class_view")
-```
+
+app.add_route(SpecialClassView.as_view(), "/special_class_view")
+```
:---
From a9b4c1b3836e7e007dde43b63ed92e03cf0638a2 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:24 +0300
Subject: [PATCH 028/776] New translations class-based-views.md (Portuguese,
Brazilian)
---
src/pt/guide/advanced/class-based-views.md | 184 +++++++++++++++++++++
1 file changed, 184 insertions(+)
create mode 100644 src/pt/guide/advanced/class-based-views.md
diff --git a/src/pt/guide/advanced/class-based-views.md b/src/pt/guide/advanced/class-based-views.md
new file mode 100644
index 0000000000..ebc7a976de
--- /dev/null
+++ b/src/pt/guide/advanced/class-based-views.md
@@ -0,0 +1,184 @@
+# Class Based Views
+
+## Why use them?
+
+---:1
+
+### The problem
+
+A common pattern when designing an API is to have multiple functionality on the same endpoint that depends upon the HTTP method.
+
+While both of these options work, they are not good design practices and may be hard to maintain over time as your project grows. :--:1
+```python
+@app.get("/foo")
+async def foo_get(request):
+ ...
+
+@app.post("/foo")
+async def foo_post(request):
+ ...
+
+@app.put("/foo")
+async def foo_put(request):
+ ...
+
+@app.route("/bar", methods=["GET", "POST", "PATCH"])
+async def bar(request):
+ if request.method == "GET":
+ ...
+ elif request.method == "POST":
+ ...
+ elif request.method == "PATCH":
+ ...
+```
+:---
+
+---:1
+
+### The solution
+
+Class-based views are simply classes that implement response behavior to requests. They provide a way to compartmentalize handling of different HTTP request types at the same endpoint. :--:1
+```python
+from sanic.views import HTTPMethodView
+
+class FooBar(HTTPMethodView):
+ async def get(self, request):
+ ...
+
+ async def post(self, request):
+ ...
+
+ async def put(self, request):
+ ...
+
+app.add_route(FooBar.as_view(), "/foobar")
+```
+:---
+
+## Defining a view
+
+A class-based view should subclass `HTTPMethodView`. You can then implement class methods with the name of the corresponding HTTP method. If a request is received that has no defined method, a `405: Method not allowed` response will be generated.
+
+---:1
+
+To register a class-based view on an endpoint, the `app.add_route` method is used. The first argument should be the defined class with the method `as_view` invoked, and the second should be the URL endpoint.
+
+The available methods are:
+
+- get
+- post
+- put
+- patch
+- delete
+- head
+- options :--:1
+```python
+from sanic.views import HTTPMethodView
+from sanic.response import text
+
+class SimpleView(HTTPMethodView):
+
+ def get(self, request):
+ return text("I am get method")
+
+ # You can also use async syntax
+ async def post(self, request):
+ return text("I am post method")
+
+ def put(self, request):
+ return text("I am put method")
+
+ def patch(self, request):
+ return text("I am patch method")
+
+ def delete(self, request):
+ return text("I am delete method")
+
+app.add_route(SimpleView.as_view(), "/")
+```
+:---
+
+## Path parameters
+
+---:1
+
+You can use path parameters exactly as discussed in [the routing section](/guide/basics/routing.md). :--:1
+```python
+class NameView(HTTPMethodView):
+
+ def get(self, request, name):
+ return text("Hello {}".format(name))
+
+app.add_route(NameView.as_view(), "/")
+```
+:---
+
+## Decorators
+
+As discussed in [the decorators section](/guide/best-practices/decorators.md), often you will need to add functionality to endpoints with the use of decorators. You have two options with CBV:
+
+1. Apply to _all_ HTTP methods in the view
+2. Apply individually to HTTP methods in the view
+
+Let's see what the options look like:
+
+---:1
+
+### Apply to all methods
+
+If you want to add any decorators to the class, you can set the `decorators` class variable. These will be applied to the class when `as_view` is called. :--:1
+```python
+class ViewWithDecorator(HTTPMethodView):
+ decorators = [some_decorator_here]
+
+ def get(self, request, name):
+ return text("Hello I have a decorator")
+
+ def post(self, request, name):
+ return text("Hello I also have a decorator")
+
+app.add_route(ViewWithDecorator.as_view(), "/url")
+```
+:---
+
+---:1
+
+### Apply to individual methods
+
+But if you just want to decorate some methods and not all methods, you can as shown here. :--:1
+```python
+class ViewWithSomeDecorator(HTTPMethodView):
+
+ @staticmethod
+ @some_decorator_here
+ def get(request, name):
+ return text("Hello I have a decorator")
+
+ def post(self, request, name):
+ return text("Hello I don"t have any decorators")
+
+ @some_decorator_here
+ def patch(self, request, name):
+ return text("Hello I have a decorator")
+```
+:---
+
+## Generating a URL
+---:1
+
+This works just like [generating any other URL](/guide/basics/routing.md#generating-a-url), except that the class name is a part of the endpoint. :--:1
+```python
+@app.route("/")
+def index(request):
+ url = app.url_for("SpecialClassView")
+ return redirect(url)
+
+
+class SpecialClassView(HTTPMethodView):
+ def get(self, request):
+ return text("Hello from the Special Class View!")
+
+
+app.add_route(SpecialClassView.as_view(), "/special_class_view")
+```
+:---
From 1c80bfcf227e7556eb10cba56a959ea59f6815a6 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:25 +0300
Subject: [PATCH 029/776] New translations proxy-headers.md (Japanese)
---
src/ja/guide/advanced/proxy-headers.md | 27 +++++++++++---------------
1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/src/ja/guide/advanced/proxy-headers.md b/src/ja/guide/advanced/proxy-headers.md
index 9848992f01..463c7aeb93 100644
--- a/src/ja/guide/advanced/proxy-headers.md
+++ b/src/ja/guide/advanced/proxy-headers.md
@@ -1,12 +1,12 @@
# プロキシ構成
-リバースプロキシサーバー(nginxなど)を使用する場合、`request.ip`の値にはプロキシのIP(通常は`127.0.0.1`が含まれます。ほとんどの場合、これはあなたが望むものではありません。
+リバースプロキシサーバー(nginxなど)を使用する場合、`request.ip`の値にはプロキシのIP(通常は`127.0.0.1`が含まれます。 ほとんどの場合、これはあなたが望むものではありません。
-Sanicは、`request.remote_addr`として利用可能な真のクライアントIPを決定するためにプロキシヘッダーを使用するように構成できます。完全な外部URLは、ヘッダーフィールド_if available_からも構築されます。
+Sanicは、`request.remote_addr`として利用可能な真のクライアントIPを決定するためにプロキシヘッダーを使用するように構成できます。 完全な外部URLは、ヘッダーフィールド_if available_からも構築されます。
::: ヒント 注意
-適切な予防措置がなければ、悪意のあるクライアントはプロキシヘッダーを使用して独自のIPを偽装することができます。このような問題を回避するために、Sanicは明示的に有効になっていない限り、プロキシヘッダーを使用しません。
-:::
+適切な予防措置がなければ、悪意のあるクライアントはプロキシヘッダーを使用して独自のIPを偽装することができます。 このような問題を回避するために、Sanicは明示的に有効になっていない限り、プロキシヘッダーを使用しません。
+::: :::
---:1
@@ -14,8 +14,7 @@ Sanicは、`request.remote_addr`として利用可能な真のクライアント
- `FORWARDED_SECRET`
- `REAL_IP_HEADER`
-- `PROXIES_COUNT`
-:--:1
+- `PROXIES_COUNT` :--:1
```python
app.config.FORWARDED_SECRET = "super-duper-secret"
app.config.REAL_IP_HEADER = "CF-Connecting-IP"
@@ -25,7 +24,7 @@ app.config.PROXIES_COUNT = 2
## 転送されたヘッダー
-`Forwarded`ヘッダーを使用するには、信頼できるプロキシサーバーに知られている値に`app.config.FORWARDED_SECRET`を設定する必要があります。この秘密は、特定のプロキシサーバーを安全に識別するために使用されます。
+`Forwarded`ヘッダーを使用するには、信頼できるプロキシサーバーに知られている値に`app.config.FORWARDED_SECRET`を設定する必要があります。 この秘密は、特定のプロキシサーバーを安全に識別するために使用されます。
29
@@ -33,23 +32,19 @@ app.config.PROXIES_COUNT = 2
Sanicは秘密鍵のない要素を無視し、秘密が設定されていない場合、ヘッダーを解析することさえしません。
-他のすべてのプロキシヘッダーは、クライアントに関する完全な情報をすでに持っているため、信頼できる転送された要素が見つかると無視されます。
-
-`Forwarded`ヘッダーの詳細については、関連する[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded)および[Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/)の記事をお読みください。
-
## 従来のプロキシヘッダー
### IP-Header
-プロキシが既知のヘッダーのIPアドレスを転送すると、「REAL_IP_HEADER」設定値でそれが何であるかをSanicに伝えることができます。
+他のすべてのプロキシヘッダーは、クライアントに関する完全な情報をすでに持っているため、信頼できる転送された要素が見つかると無視されます。
### X-Forwarded-For
-このヘッダーには、通常、プロキシの各レイヤーを介したIPアドレスのチェーンが含まれています。`PROXIES_COUNT`を設定すると、クライアントの実際のIPアドレスを取得する深さがSanicに指示されます。この値は、チェーン内のIPアドレスの_expected_数に等しいはずです。
+このヘッダーには、通常、プロキシの各レイヤーを介したIPアドレスのチェーンが含まれています。 `PROXIES_COUNT`を設定すると、クライアントの実際のIPアドレスを取得する深さがSanicに指示されます。 この値は、チェーン内のIPアドレスの_expected_数に等しいはずです。
### Other X-headers
-クライアントIPが次のいずれかの方法で見つかった場合、SanicはURL部分に次のヘッダーを使用します。
+プロキシが既知のヘッダーのIPアドレスを転送すると、「REAL_IP_HEADER」設定値でそれが何であるかをSanicに伝えることができます。
- x-forwarded-proto
- x-forwarded-host
@@ -59,7 +54,7 @@ Sanicは秘密鍵のない要素を無視し、秘密が設定されていない
## 例えば
-次の例では、すべての要求はエンドポイントが次のようになります。
+In the following examples, all requests will assume that the endpoint looks like this:
```python
@app.route("/fwd")
async def forwarded(request):
@@ -77,7 +72,7 @@ async def forwarded(request):
---
##### 例えば 1
-FORWARDED_SECRETが設定されていない場合、xヘッダーは尊重されるべきです
+次の例では、すべての要求はエンドポイントが次のようになります。
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
From fc2510236416eeb64b708a4ae3d5bb960fe078a6 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:26 +0300
Subject: [PATCH 030/776] New translations proxy-headers.md (Korean)
---
src/ko/guide/advanced/proxy-headers.md | 435 +++++++++++++++++++++++++
1 file changed, 435 insertions(+)
create mode 100644 src/ko/guide/advanced/proxy-headers.md
diff --git a/src/ko/guide/advanced/proxy-headers.md b/src/ko/guide/advanced/proxy-headers.md
new file mode 100644
index 0000000000..f682a8626e
--- /dev/null
+++ b/src/ko/guide/advanced/proxy-headers.md
@@ -0,0 +1,435 @@
+# Proxy configuration
+
+When you use a reverse proxy server (e.g. nginx), the value of `request.ip` will contain the IP of a proxy, typically `127.0.0.1`. Almost always, this is **not** what you will want.
+
+Sanic may be configured to use proxy headers for determining the true client IP, available as `request.remote_addr`. The full external URL is also constructed from header fields _if available_.
+
+::: tip Heads up
+Without proper precautions, a malicious client may use proxy headers to spoof its own IP. To avoid such issues, Sanic does not use any proxy headers unless explicitly enabled.
+:::
+
+---:1
+
+Services behind reverse proxies must configure one or more of the following [configuration values](/guide/deployment/configuration.md):
+
+- `FORWARDED_SECRET`
+- `REAL_IP_HEADER`
+- `PROXIES_COUNT` :--:1
+```python
+app.config.FORWARDED_SECRET = "super-duper-secret"
+app.config.REAL_IP_HEADER = "CF-Connecting-IP"
+app.config.PROXIES_COUNT = 2
+```
+:---
+
+## Forwarded header
+
+In order to use the `Forwarded` header, you should set `app.config.FORWARDED_SECRET` to a value known to the trusted proxy server. The secret is used to securely identify a specific proxy server.
+
+Sanic ignores any elements without the secret key, and will not even parse the header if no secret is set.
+
+All other proxy headers are ignored once a trusted forwarded element is found, as it already carries complete information about the client.
+
+To learn more about the `Forwarded` header, read the related [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded) and [Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/) articles.
+
+## Traditional proxy headers
+
+### IP Headers
+
+When your proxy forwards you the IP address in a known header, you can tell Sanic what that is with the `REAL_IP_HEADER` config value.
+
+### X-Forwarded-For
+
+This header typically contains a chain of IP addresses through each layer of a proxy. Setting `PROXIES_COUNT` tells Sanic how deep to look to get an actual IP address for the client. This value should equal the _expected_ number of IP addresses in the chain.
+
+### Other X-headers
+
+If a client IP is found by one of these methods, Sanic uses the following headers for URL parts:
+
+- x-forwarded-proto
+- x-forwarded-host
+- x-forwarded-port
+- x-forwarded-path
+- x-scheme
+
+## Examples
+
+In the following examples, all requests will assume that the endpoint looks like this:
+```python
+@app.route("/fwd")
+async def forwarded(request):
+ return json(
+ {
+ "remote_addr": request.remote_addr,
+ "scheme": request.scheme,
+ "server_name": request.server_name,
+ "server_port": request.server_port,
+ "forwarded": request.forwarded,
+ }
+ )
+```
+---:1
+---
+
+##### Example 1
+Without configured FORWARDED_SECRET, x-headers should be respected
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=1.1.1.1, for=injected;host=", for="[::2]";proto=https;host=me.tld;path="/app/";secret=mySecret,for=broken;;secret=b0rked, for=127.0.0.3;scheme=http;port=1234' \
+ -H "X-Real-IP: 127.0.0.2" \
+ -H "X-Forwarded-For: 127.0.1.1" \
+ -H "X-Scheme: ws" \
+ -H "Host: local.site" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "127.0.0.2",
+ "scheme": "ws",
+ "server_name": "local.site",
+ "server_port": 80,
+ "forwarded": {
+ "for": "127.0.0.2",
+ "proto": "ws"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 2
+FORWARDED_SECRET now configured
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=1.1.1.1, for=injected;host=", for="[::2]";proto=https;host=me.tld;path="/app/";secret=mySecret,for=broken;;secret=b0rked, for=127.0.0.3;scheme=http;port=1234' \
+ -H "X-Real-IP: 127.0.0.2" \
+ -H "X-Forwarded-For: 127.0.1.1" \
+ -H "X-Scheme: ws" \
+ -H "Host: local.site" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "[::2]",
+ "scheme": "https",
+ "server_name": "me.tld",
+ "server_port": 443,
+ "forwarded": {
+ "for": "[::2]",
+ "proto": "https",
+ "host": "me.tld",
+ "path": "/app/",
+ "secret": "mySecret"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 3
+Empty Forwarded header -> use X-headers
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H "X-Real-IP: 127.0.0.2" \
+ -H "X-Forwarded-For: 127.0.1.1" \
+ -H "X-Scheme: ws" \
+ -H "Host: local.site" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "127.0.0.2",
+ "scheme": "ws",
+ "server_name": "local.site",
+ "server_port": 80,
+ "forwarded": {
+ "for": "127.0.0.2",
+ "proto": "ws"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 4
+Header present but not matching anything
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H "Forwarded: nomatch" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {}
+}
+
+```
+:---
+---
+---:1
+
+##### Example 5
+Forwarded header present but no matching secret -> use X-headers
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H "Forwarded: for=1.1.1.1;secret=x, for=127.0.0.1" \
+ -H "X-Real-IP: 127.0.0.2" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "127.0.0.2",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "for": "127.0.0.2"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 6
+Different formatting and hitting both ends of the header
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: Secret="mySecret";For=127.0.0.4;Port=1234' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "127.0.0.4",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 1234,
+ "forwarded": {
+ "secret": "mySecret",
+ "for": "127.0.0.4",
+ "port": 1234
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 7
+Test escapes (modify this if you see anyone implementing quoted-pairs)
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=test;quoted="\,x=x;y=\";secret=mySecret' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "test",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "for": "test",
+ "quoted": "\\,x=x;y=\\",
+ "secret": "mySecret"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 8
+Secret insulated by malformed field #1
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=test;secret=mySecret;b0rked;proto=wss;' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "test",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "for": "test",
+ "secret": "mySecret"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 9
+Secret insulated by malformed field #2
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=test;b0rked;secret=mySecret;proto=wss' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "",
+ "scheme": "wss",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "secret": "mySecret",
+ "proto": "wss"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 10
+Unexpected termination should not lose existing acceptable values
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: b0rked;secret=mySecret;proto=wss' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "",
+ "scheme": "wss",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "secret": "mySecret",
+ "proto": "wss"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 11
+Field normalization
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: PROTO=WSS;BY="CAFE::8000";FOR=unknown;PORT=X;HOST="A:2";PATH="/With%20Spaces%22Quoted%22/sanicApp?key=val";SECRET=mySecret' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "",
+ "scheme": "wss",
+ "server_name": "a",
+ "server_port": 2,
+ "forwarded": {
+ "proto": "wss",
+ "by": "[cafe::8000]",
+ "host": "a:2",
+ "path": "/With Spaces\"Quoted\"/sanicApp?key=val",
+ "secret": "mySecret"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 12
+Using "by" field as secret
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "_proxySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=1.2.3.4; by=_proxySecret' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "1.2.3.4",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "for": "1.2.3.4",
+ "by": "_proxySecret"
+ }
+}
+
+```
+:---
From 827c81ecd68edbd308a8946a37a49d4e5e5b8cc5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:27 +0300
Subject: [PATCH 031/776] New translations proxy-headers.md (Chinese
Simplified)
---
src/zh/guide/advanced/proxy-headers.md | 148 ++++---------------------
1 file changed, 22 insertions(+), 126 deletions(-)
diff --git a/src/zh/guide/advanced/proxy-headers.md b/src/zh/guide/advanced/proxy-headers.md
index 3c009b32db..da113c9377 100644
--- a/src/zh/guide/advanced/proxy-headers.md
+++ b/src/zh/guide/advanced/proxy-headers.md
@@ -1,56 +1,48 @@
# 代理设置(Proxy configuration)
-当使用反向代理时(比如 nginx 等),`request.ip` 的值将会被设置为反向代理的 IP,一般来说就是 `127.0.0.1`。而这通常并不是您希望看到的。
+当使用反向代理时(比如 nginx 等),`request.ip` 的值将会被设置为反向代理的 IP,一般来说就是 `127.0.0.1`。 而这通常并不是您希望看到的。
-Sanic 可以通过配置来从代理请求的请求头部信息获取客户端的真实的 IP 地址,这个地址会被保存到 `request.remote_addr` 属性中。如果请求头中包含 URL 的完整信息,那同样也可以获取得到。
+Sanic 可以通过配置来从代理请求的请求头部信息获取客户端的真实的 IP 地址,这个地址会被保存到 `request.remote_addr` 属性中。 如果请求头中包含 URL 的完整信息,那同样也可以获取得到。
-:::tip 小提示
-
-如果没有适当的防护措施,一些恶意客户端可能会使用代理头来隐藏自己的 IP。为了避免此类问题,除非明确启用,否则 Sanic 不会使用任何代理头。
-
-:::
+如果没有适当的防护措施,一些恶意客户端可能会使用代理头来隐藏自己的 IP。 为了避免此类问题,除非明确启用,否则 Sanic 不会使用任何代理头。 :::
---:1
-反向代理后的服务必须要设置如下一项或多项 [配置](/zh/guide/deployment/configuration.md)
+:::
- `FORWARDED_SECRET`
- `REAL_IP_HEADER`
-- `PROXIES_COUNT`
-
-:--:1
-
+- PROXIES_COUNT
```python
app.config.FORWARDED_SECRET = "super-duper-secret"
app.config.REAL_IP_HEADER = "CF-Connecting-IP"
app.config.PROXIES_COUNT = 2
```
-
:---
## 转发头(Forwarded header)
-如果想使用 `转发(Forwarded)` 头,您应该将 `app.config.FORWARDED_SECRET` 秘钥值设置为受信的反向代理服务器已知的秘钥值。这个秘钥会被用于鉴定反向代理服务是否安全。
+如果想使用 `转发(Forwarded)` 头,您应该将 `app.config.FORWARDED_SECRET` 秘钥值设置为受信的反向代理服务器已知的秘钥值。 这个秘钥会被用于鉴定反向代理服务是否安全。
-Sanic 会忽略任何不携带这个秘钥的信息,并且如果不设置秘钥值,就不会去解析请求头。
+Sanic ignores any elements without the secret key, and will not even parse the header if no secret is set.
一旦获取了受信的转发头信息,所有其他的代理相关的头信息都会被忽略,因为该头中已经携带了原始客户端的所有信息。
-想要了解关于 `转发(Forwarded)` 头的更多信息,可以查看 [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded) 或者 [Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/) 上的文章。
+To learn more about the `Forwarded` header, read the related [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded) and [Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/) articles.
## 一些代理相关的请求头(Traditional proxy headers)
### IP 头信息(IP Headers)
-当您的代理服务器在某个请求头中携带了客户端 IP,您可以通过设置 Sanic 的 `REAL_IP_HEADER` 来明确这个请求头是什么。
+Sanic 会忽略任何不携带这个秘钥的信息,并且如果不设置秘钥值,就不会去解析请求头。
### X-Forwarded-For
-这个请求头是一串 IP 地址链,通常包含了一连串的代理 IP 地址。可以通过设置 Sanic 的 `PROXIES_COUNT` 配置变量来确定客户端 IP 地址在该链路中的具体位置。这个值通常应该等于 IP 地址链中 *预期的* IP 数量。
+这个请求头是一串 IP 地址链,通常包含了一连串的代理 IP 地址。 可以通过设置 Sanic 的 `PROXIES_COUNT` 配置变量来确定客户端 IP 地址在该链路中的具体位置。 这个值通常应该等于 IP 地址链中 *预期的* IP 数量。
### 其他的 X-headers
-如果 Sanic 从以上任意一种方法中获取了客户端的IP地址,那么 URL 的部分将会从以下请求头信息中获取。
+想要了解关于 `转发(Forwarded)` 头的更多信息,可以查看 [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded) 或者 [Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/) 上的文章。
- x-forwarded-proto
- x-forwarded-host
@@ -60,8 +52,7 @@ Sanic 会忽略任何不携带这个秘钥的信息,并且如果不设置秘
## 实例(Examples)
-在接下来的例子中,假设所有的请求都是通过下面定义的这个方法:
-
+当您的代理服务器在某个请求头中携带了客户端 IP,您可以通过设置 Sanic 的 `REAL_IP_HEADER` 来明确这个请求头是什么。
```python
@app.route("/fwd")
async def forwarded(request):
@@ -75,20 +66,15 @@ async def forwarded(request):
}
)
```
-
---:1
-
---
##### 例一(Example 1)
-
-没有设置 `FORWARDED_SECRET`,那就以 x-headers 中的信息为准
-
+如果 Sanic 从以上任意一种方法中获取了客户端的IP地址,那么 URL 的部分将会从以下请求头信息中获取。
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
```
-
```bash
$ curl localhost:8000/fwd \
-H 'Forwarded: for=1.1.1.1, for=injected;host=", for="[::2]";proto=https;host=me.tld;path="/app/";secret=mySecret,for=broken;;secret=b0rked, for=127.0.0.3;scheme=http;port=1234' \
@@ -97,9 +83,7 @@ $ curl localhost:8000/fwd \
-H "X-Scheme: ws" \
-H "Host: local.site" | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -113,17 +97,12 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例二(Example 2)
-
-配置 `FORWARDED_SECRET` 后:
-
+没有设置 `FORWARDED_SECRET`,那就以 x-headers 中的信息为准
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
@@ -131,15 +110,13 @@ app.config.FORWARDED_SECRET = "mySecret"
```
```bash
$ curl localhost:8000/fwd \
- -H 'Forwarded: for=1.1.1.1, for=injected;host=", for="[::2]";proto=https;host=me.tld;path="/app/";secret=mySecret, for=broken;;secret=b0rked, for=127.0.0.3;scheme=http;port=1234' \
+ -H 'Forwarded: for=1.1.1.1, for=injected;host=", for="[::2]";proto=https;host=me.tld;path="/app/";secret=mySecret,for=broken;;secret=b0rked, for=127.0.0.3;scheme=http;port=1234' \
-H "X-Real-IP: 127.0.0.2" \
-H "X-Forwarded-For: 127.0.1.1" \
-H "X-Scheme: ws" \
-H "Host: local.site" | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -156,23 +133,17 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例三(Example 3)
-
转发头(Forwarded header)为空时,这时候还是使用 X-headers :
-
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H "X-Real-IP: 127.0.0.2" \
@@ -180,9 +151,7 @@ $ curl localhost:8000/fwd \
-H "X-Scheme: ws" \
-H "Host: local.site" | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -196,30 +165,22 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例四(Example 4)
-
-没有请求头但是不包含任何匹配的信息:
-
+Header present but not matching anything
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H "Forwarded: nomatch" | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -231,31 +192,23 @@ $ curl localhost:8000/fwd \
}
```
-
:---
-
---
-
---:1
##### 例五(Example 5)
-
虽然有转发头(Forwarded header),但是没有对的上的秘钥,还是使用 X-headers 中的值:
-
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H "Forwarded: for=1.1.1.1;secret=x, for=127.0.0.1" \
-H "X-Real-IP: 127.0.0.2" | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -268,30 +221,22 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例六(Example 6)
-
-不同的格式但也满足条件的情况:
-
+没有请求头但是不包含任何匹配的信息:
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H 'Forwarded: Secret="mySecret";For=127.0.0.4;Port=1234' | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -306,30 +251,22 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例七(Example 7)
-
-测试包含转译字符的(如果您看到有人实现了引号对,请修改这一点):
-
+Test escapes (modify this if you see anyone implementing quoted-pairs)
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H 'Forwarded: for=test;quoted="\,x=x;y=\";secret=mySecret' | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -344,30 +281,22 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例八(Example 8)
-
-如果出现破坏了格式的信息,情况1:
-
+Secret insulated by malformed field #1
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H 'Forwarded: for=test;secret=mySecret;b0rked;proto=wss;' | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -381,30 +310,22 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例九(Example 9)
-
-如果出现破坏了格式的信息,情况2:
-
+Secret insulated by malformed field #2
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H 'Forwarded: for=test;b0rked;secret=mySecret;proto=wss' | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -418,30 +339,22 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例十(Example 10)
-
-出现意外值不会丢失其他有效信息:
-
+测试包含转译字符的(如果您看到有人实现了引号对,请修改这一点):
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H 'Forwarded: b0rked;secret=mySecret;proto=wss' | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -455,30 +368,22 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例十一(Example 11)
-
-反转译:
-
+Field normalization
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "mySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H 'Forwarded: PROTO=WSS;BY="CAFE::8000";FOR=unknown;PORT=X;HOST="A:2";PATH="/With%20Spaces%22Quoted%22/sanicApp?key=val";SECRET=mySecret' | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -495,30 +400,22 @@ $ curl localhost:8000/fwd \
}
}
```
-
:---
-
---
-
---:1
##### 例十二(Example 12)
-
可以使用 “by” 字段携带密钥:
-
```python
app.config.PROXIES_COUNT = 1
app.config.REAL_IP_HEADER = "x-real-ip"
app.config.FORWARDED_SECRET = "_proxySecret"
```
-
```bash
$ curl localhost:8000/fwd \
-H 'Forwarded: for=1.2.3.4; by=_proxySecret' | jq
```
-
:--:1
-
```bash
# curl response
{
@@ -533,5 +430,4 @@ $ curl localhost:8000/fwd \
}
```
-
:---
From bbeb3aefcbae992e594470c3abdb04235883ea46 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:28 +0300
Subject: [PATCH 032/776] New translations proxy-headers.md (Portuguese,
Brazilian)
---
src/pt/guide/advanced/proxy-headers.md | 435 +++++++++++++++++++++++++
1 file changed, 435 insertions(+)
create mode 100644 src/pt/guide/advanced/proxy-headers.md
diff --git a/src/pt/guide/advanced/proxy-headers.md b/src/pt/guide/advanced/proxy-headers.md
new file mode 100644
index 0000000000..f682a8626e
--- /dev/null
+++ b/src/pt/guide/advanced/proxy-headers.md
@@ -0,0 +1,435 @@
+# Proxy configuration
+
+When you use a reverse proxy server (e.g. nginx), the value of `request.ip` will contain the IP of a proxy, typically `127.0.0.1`. Almost always, this is **not** what you will want.
+
+Sanic may be configured to use proxy headers for determining the true client IP, available as `request.remote_addr`. The full external URL is also constructed from header fields _if available_.
+
+::: tip Heads up
+Without proper precautions, a malicious client may use proxy headers to spoof its own IP. To avoid such issues, Sanic does not use any proxy headers unless explicitly enabled.
+:::
+
+---:1
+
+Services behind reverse proxies must configure one or more of the following [configuration values](/guide/deployment/configuration.md):
+
+- `FORWARDED_SECRET`
+- `REAL_IP_HEADER`
+- `PROXIES_COUNT` :--:1
+```python
+app.config.FORWARDED_SECRET = "super-duper-secret"
+app.config.REAL_IP_HEADER = "CF-Connecting-IP"
+app.config.PROXIES_COUNT = 2
+```
+:---
+
+## Forwarded header
+
+In order to use the `Forwarded` header, you should set `app.config.FORWARDED_SECRET` to a value known to the trusted proxy server. The secret is used to securely identify a specific proxy server.
+
+Sanic ignores any elements without the secret key, and will not even parse the header if no secret is set.
+
+All other proxy headers are ignored once a trusted forwarded element is found, as it already carries complete information about the client.
+
+To learn more about the `Forwarded` header, read the related [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded) and [Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/) articles.
+
+## Traditional proxy headers
+
+### IP Headers
+
+When your proxy forwards you the IP address in a known header, you can tell Sanic what that is with the `REAL_IP_HEADER` config value.
+
+### X-Forwarded-For
+
+This header typically contains a chain of IP addresses through each layer of a proxy. Setting `PROXIES_COUNT` tells Sanic how deep to look to get an actual IP address for the client. This value should equal the _expected_ number of IP addresses in the chain.
+
+### Other X-headers
+
+If a client IP is found by one of these methods, Sanic uses the following headers for URL parts:
+
+- x-forwarded-proto
+- x-forwarded-host
+- x-forwarded-port
+- x-forwarded-path
+- x-scheme
+
+## Examples
+
+In the following examples, all requests will assume that the endpoint looks like this:
+```python
+@app.route("/fwd")
+async def forwarded(request):
+ return json(
+ {
+ "remote_addr": request.remote_addr,
+ "scheme": request.scheme,
+ "server_name": request.server_name,
+ "server_port": request.server_port,
+ "forwarded": request.forwarded,
+ }
+ )
+```
+---:1
+---
+
+##### Example 1
+Without configured FORWARDED_SECRET, x-headers should be respected
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=1.1.1.1, for=injected;host=", for="[::2]";proto=https;host=me.tld;path="/app/";secret=mySecret,for=broken;;secret=b0rked, for=127.0.0.3;scheme=http;port=1234' \
+ -H "X-Real-IP: 127.0.0.2" \
+ -H "X-Forwarded-For: 127.0.1.1" \
+ -H "X-Scheme: ws" \
+ -H "Host: local.site" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "127.0.0.2",
+ "scheme": "ws",
+ "server_name": "local.site",
+ "server_port": 80,
+ "forwarded": {
+ "for": "127.0.0.2",
+ "proto": "ws"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 2
+FORWARDED_SECRET now configured
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=1.1.1.1, for=injected;host=", for="[::2]";proto=https;host=me.tld;path="/app/";secret=mySecret,for=broken;;secret=b0rked, for=127.0.0.3;scheme=http;port=1234' \
+ -H "X-Real-IP: 127.0.0.2" \
+ -H "X-Forwarded-For: 127.0.1.1" \
+ -H "X-Scheme: ws" \
+ -H "Host: local.site" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "[::2]",
+ "scheme": "https",
+ "server_name": "me.tld",
+ "server_port": 443,
+ "forwarded": {
+ "for": "[::2]",
+ "proto": "https",
+ "host": "me.tld",
+ "path": "/app/",
+ "secret": "mySecret"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 3
+Empty Forwarded header -> use X-headers
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H "X-Real-IP: 127.0.0.2" \
+ -H "X-Forwarded-For: 127.0.1.1" \
+ -H "X-Scheme: ws" \
+ -H "Host: local.site" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "127.0.0.2",
+ "scheme": "ws",
+ "server_name": "local.site",
+ "server_port": 80,
+ "forwarded": {
+ "for": "127.0.0.2",
+ "proto": "ws"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 4
+Header present but not matching anything
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H "Forwarded: nomatch" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {}
+}
+
+```
+:---
+---
+---:1
+
+##### Example 5
+Forwarded header present but no matching secret -> use X-headers
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H "Forwarded: for=1.1.1.1;secret=x, for=127.0.0.1" \
+ -H "X-Real-IP: 127.0.0.2" | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "127.0.0.2",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "for": "127.0.0.2"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 6
+Different formatting and hitting both ends of the header
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: Secret="mySecret";For=127.0.0.4;Port=1234' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "127.0.0.4",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 1234,
+ "forwarded": {
+ "secret": "mySecret",
+ "for": "127.0.0.4",
+ "port": 1234
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 7
+Test escapes (modify this if you see anyone implementing quoted-pairs)
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=test;quoted="\,x=x;y=\";secret=mySecret' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "test",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "for": "test",
+ "quoted": "\\,x=x;y=\\",
+ "secret": "mySecret"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 8
+Secret insulated by malformed field #1
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=test;secret=mySecret;b0rked;proto=wss;' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "test",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "for": "test",
+ "secret": "mySecret"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 9
+Secret insulated by malformed field #2
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=test;b0rked;secret=mySecret;proto=wss' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "",
+ "scheme": "wss",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "secret": "mySecret",
+ "proto": "wss"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 10
+Unexpected termination should not lose existing acceptable values
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: b0rked;secret=mySecret;proto=wss' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "",
+ "scheme": "wss",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "secret": "mySecret",
+ "proto": "wss"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 11
+Field normalization
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "mySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: PROTO=WSS;BY="CAFE::8000";FOR=unknown;PORT=X;HOST="A:2";PATH="/With%20Spaces%22Quoted%22/sanicApp?key=val";SECRET=mySecret' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "",
+ "scheme": "wss",
+ "server_name": "a",
+ "server_port": 2,
+ "forwarded": {
+ "proto": "wss",
+ "by": "[cafe::8000]",
+ "host": "a:2",
+ "path": "/With Spaces\"Quoted\"/sanicApp?key=val",
+ "secret": "mySecret"
+ }
+}
+```
+:---
+---
+---:1
+
+##### Example 12
+Using "by" field as secret
+```python
+app.config.PROXIES_COUNT = 1
+app.config.REAL_IP_HEADER = "x-real-ip"
+app.config.FORWARDED_SECRET = "_proxySecret"
+```
+```bash
+$ curl localhost:8000/fwd \
+ -H 'Forwarded: for=1.2.3.4; by=_proxySecret' | jq
+```
+:--:1
+```bash
+# curl response
+{
+ "remote_addr": "1.2.3.4",
+ "scheme": "http",
+ "server_name": "localhost",
+ "server_port": 8000,
+ "forwarded": {
+ "for": "1.2.3.4",
+ "by": "_proxySecret"
+ }
+}
+
+```
+:---
From 85cd9f4aef4a1b01b141a70a99e017fb99260a0f Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:29 +0300
Subject: [PATCH 033/776] New translations signals.md (Korean)
---
src/ko/guide/advanced/signals.md | 262 +++++++++++++++++++++++++++++++
1 file changed, 262 insertions(+)
create mode 100644 src/ko/guide/advanced/signals.md
diff --git a/src/ko/guide/advanced/signals.md b/src/ko/guide/advanced/signals.md
new file mode 100644
index 0000000000..c8a603cf52
--- /dev/null
+++ b/src/ko/guide/advanced/signals.md
@@ -0,0 +1,262 @@
+# Signals
+
+Signals provide a way for one part of your application to tell another part that something happened.
+
+```python
+@app.signal("user.registration.created")
+async def send_registration_email(**context):
+ await send_email(context["email"], template="registration")
+
+@app.post("/register")
+async def handle_registration(request):
+ await do_registration(request)
+ await request.app.dispatch(
+ "user.registration.created",
+ context={"email": request.json.email}
+ })
+```
+
+## Adding a signal
+
+---:1 The API for adding a signal is very similar to adding a route. :--:1
+```python
+async def my_signal_handler():
+ print("something happened")
+
+app.add_signal(my_signal_handler, "something.happened.ohmy")
+```
+:---
+
+---:1 But, perhaps a slightly more convenient method is to use the built-in decorators. :--:1
+```python
+@app.signal("something.happened.ohmy")
+async def my_signal_handler():
+ print("something happened")
+```
+:---
+
+---:1 If the signal requires conditions, make sure to add them while adding the handler. :--:1
+```python
+async def my_signal_handler1():
+ print("something happened")
+
+app.add_signal(
+ my_signal_handler,
+ "something.happened.ohmy1",
+ conditions={"some_condition": "value"}
+)
+
+@app.signal("something.happened.ohmy2", conditions={"some_condition": "value"})
+async def my_signal_handler2():
+ print("something happened")
+```
+:---
+
+---:1 Signals can also be declared on blueprints :--:1
+```python
+bp = Blueprint("foo")
+
+@bp.signal("something.happened.ohmy")
+async def my_signal_handler():
+ print("something happened")
+```
+:---
+
+## Built-in signals
+
+In addition to creating a new signal, there are a number of built-in signals that are dispatched from Sanic itself. These signals exist to provide developers with more opportunities to add functionality into the request and server lifecycles.
+
+---:1
+
+
+You can attach them just like any other signal to an application or blueprint instance.
+
+:--:1
+
+```python
+@app.signal("http.lifecycle.complete")
+async def my_signal_handler(conn_info):
+ print("Connection has been closed")
+```
+:---
+
+These signals are the signals that are available, along with the arguments that the handlers take, and the conditions that attach (if any).
+
+
+| Event name | Arguments | Conditions |
+| -------------------------- | ------------------------------- | --------------------------------------------------------- |
+| `http.routing.before` | request | |
+| `http.routing.after` | request, route, kwargs, handler | |
+| `http.lifecycle.begin` | conn_info | |
+| `http.lifecycle.read_head` | head | |
+| `http.lifecycle.request` | request | |
+| `http.lifecycle.handle` | request | |
+| `http.lifecycle.read_body` | body | |
+| `http.lifecycle.exception` | request, exception | |
+| `http.lifecycle.response` | request, response | |
+| `http.lifecycle.send` | data | |
+| `http.lifecycle.complete` | conn_info | |
+| `http.middleware.before` | request, response | `{"attach_to": "request"}` or `{"attach_to": "response"}` |
+| `http.middleware.after` | request, response | `{"attach_to": "request"}` or `{"attach_to": "response"}` |
+| `server.init.before` | app, loop | |
+| `server.init.after` | app, loop | |
+| `server.shutdown.before` | app, loop | |
+| `server.shutdown.after` | app, loop | |
+
+---:1 To make using the built-in signals easier, there is an `Enum` object that contains all of the allowed built-ins. With a modern IDE this will help so that you do not need to remember the full list of event names as strings. :--:1
+```python
+from sanic.signals import Event
+
+@app.signal(Event.HTTP_LIFECYCLE_COMPLETE)
+async def my_signal_handler(conn_info):
+ print("Connection has been closed")
+```
+:---
+
+## Events
+
+---:1 Signals are based off of an _event_. An event, is simply a string in the following pattern: :--:1
+```
+namespace.reference.action
+```
+:---
+
+::: tip Events must have three parts. If you do not know what to use, try these patterns:
+
+- `my_app.something.happened`
+- `sanic.notice.hello` :::
+
+### Event parameters
+
+---:1 An event can be "dynamic" and declared using the same syntax as [path parameters](../basics/routing.md#path-parameters). This allows matching based upon arbitrary values. :--:1
+```python
+@app.signal("foo.bar.")
+async def signal_handler(thing):
+ print(f"[signal_handler] {thing=}")
+
+@app.get("/")
+async def trigger(request):
+ await app.dispatch("foo.bar.baz")
+ return response.text("Done.")
+```
+:---
+
+Checkout [path parameters](../basics/routing.md#path-parameters) for more information on allowed type definitions.
+
+::: warning Only the third part of an event (the "action") may be dynamic:
+
+- `foo.bar.` :ok:
+- `foo..baz` :x: :::
+
+### Waiting
+
+---:1 In addition to executing a signal handler, your application can wait for an event to be triggered. :--:1
+```python
+await app.event("foo.bar.baz")
+```
+:---
+
+---:1 **IMPORTANT**: waiting is a blocking function. Therefore, you likely will want this to run in a [background task](../basics/tasks.md). :--:1
+```python
+async def wait_for_event(app):
+ while True:
+ print("> waiting")
+ await app.event("foo.bar.baz")
+ print("> event found\n")
+
+@app.after_server_start
+async def after_server_start(app, loop):
+ app.add_task(wait_for_event(app))
+```
+:---
+
+---:1 If your event was defined with a dynamic path, you can use `*` to catch any action. :--:1
+```python
+@app.signal("foo.bar.")
+
+...
+
+await app.event("foo.bar.*")
+```
+:---
+
+## Dispatching
+
+*In the future, Sanic will dispatch some events automatically to assist developers to hook into life cycle events.*
+
+---:1 Dispatching an event will do two things:
+
+1. execute any signal handlers defined on the event, and
+2. resolve anything that is "waiting" for the event to complete. :--:1
+```python
+@app.signal("foo.bar.")
+async def foo_bar(thing):
+ print(f"{thing=}")
+
+await app.dispatch("foo.bar.baz")
+```
+```
+thing=baz
+```
+:---
+
+### Context
+
+---:1 Sometimes you may find the need to pass extra information into the signal handler. In our first example above, we wanted our email registration process to have the email address for the user. :--:1
+```python
+@app.signal("user.registration.created")
+async def send_registration_email(**context):
+ print(context)
+
+await app.dispatch(
+ "user.registration.created",
+ context={"hello": "world"}
+)
+```
+```
+{'hello': 'world'}
+```
+:---
+
+::: tip FYI
+Signals are dispatched in a background task.
+:::
+
+### Blueprints
+
+Dispatching blueprint signals works similar in concept to [middleware](../basics/middleware.md). Anything that is done from the app level, will trickle down to the blueprints. However, dispatching on a blueprint, will only execute the signals that are defined on that blueprint.
+
+---:1 Perhaps an example is easier to explain: :--:1
+```python
+bp = Blueprint("bp")
+
+app_counter = 0
+bp_counter = 0
+
+@app.signal("foo.bar.baz")
+def app_signal():
+ nonlocal app_counter
+ app_counter += 1
+
+@bp.signal("foo.bar.baz")
+def bp_signal():
+ nonlocal bp_counter
+ bp_counter += 1
+```
+:---
+
+---:1 Running `app.dispatch("foo.bar.baz")` will execute both signals. :--:1
+```python
+await app.dispatch("foo.bar.baz")
+assert app_counter == 1
+assert bp_counter == 1
+```
+:---
+
+---:1 Running `bp.dispatch("foo.bar.baz")` will execute only the blueprint signal. :--:1
+```python
+await bp.dispatch("foo.bar.baz")
+assert app_counter == 1
+assert bp_counter == 2
+```
+:---
From 893a607338dee9a963c6666a990910df32944e37 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:30 +0300
Subject: [PATCH 034/776] New translations websockets.md (Japanese)
---
src/ja/guide/advanced/websockets.md | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/ja/guide/advanced/websockets.md b/src/ja/guide/advanced/websockets.md
index 607a7265b7..f566bc5e02 100644
--- a/src/ja/guide/advanced/websockets.md
+++ b/src/ja/guide/advanced/websockets.md
@@ -7,8 +7,7 @@ Sanicは、[websockets](https://websockets.readthedocs.io/en/stable/)の上に
---:1
-Websocketハンドラーは、通常のハンドラと同様にルーターに接続できます。
-:--:1
+Websocketハンドラーは、通常のハンドラと同様にルーターに接続できます。 :--:1 :--:1
```python
async def feed(request, ws):
pass
@@ -31,8 +30,7 @@ async def feed(request, ws):
その後、ハンドラーに注入された2番目のオブジェクトで `send()` メソッドと `recv()` メソッドを使用できます。
-この例は、受信したクライアントメッセージにエコーバックする単純なエンドポイントです。
-:--:1
+この例は、受信したクライアントメッセージにエコーバックする単純なエンドポイントです。 :--:1 :--:1
```python
@app.websocket("/feed")
From 04ee1988088f47414c23a2ce7dc563142086cb99 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:31 +0300
Subject: [PATCH 035/776] New translations signals.md (Chinese Simplified)
---
src/zh/guide/advanced/signals.md | 152 ++++++-------------------------
1 file changed, 29 insertions(+), 123 deletions(-)
diff --git a/src/zh/guide/advanced/signals.md b/src/zh/guide/advanced/signals.md
index f26022d338..9188869eac 100644
--- a/src/zh/guide/advanced/signals.md
+++ b/src/zh/guide/advanced/signals.md
@@ -18,38 +18,24 @@ async def handle_registration(request):
## 添加信号(Adding a signal)
----:1
-
-添加信号的 API 十分像添加路由的。
-
-:--:1
-
+---:1 如果该信号需要条件参数,请确保在添加信号处理函数的时候加上它。 :--:1
```python
async def my_signal_handler():
print("something happened")
app.add_signal(my_signal_handler, "something.happened.ohmy")
```
-
:---
----:1
-
-同样的,信号也内置了装饰器来提供了便捷的注册方法。
-
-:--:1
-
+---:1 But, perhaps a slightly more convenient method is to use the built-in decorators. :--:1
```python
@app.signal("something.happened.ohmy")
async def my_signal_handler():
print("something happened")
```
-
:---
----:1
-如果该信号需要条件参数,请确保在添加信号处理函数的时候加上它。
-:--:1
+---:1 If the signal requires conditions, make sure to add them while adding the handler. :--:1
```python
async def my_signal_handler1():
print("something happened")
@@ -66,13 +52,7 @@ async def my_signal_handler2():
```
:---
-
----:1
-
-信号也可以在注册在蓝图上。
-
-:--:1
-
+---:1 Signals can also be declared on blueprints :--:1
```python
bp = Blueprint("foo")
@@ -80,15 +60,15 @@ bp = Blueprint("foo")
async def my_signal_handler():
print("something happened")
```
-
:---
## 内置信号(Built-in signals)
-除了创建新信号外,还有许多从 Sanic 自身发出的内置信号。这些信号的存在为开发人员提供了更多将功能添加到请求和服务器生命周期中的机会。
+除了创建新信号外,还有许多从 Sanic 自身发出的内置信号。 这些信号的存在为开发人员提供了更多将功能添加到请求和服务器生命周期中的机会。
---:1
+
和其他的信号一样,您同样可以将这些内置信号附加到应用程序上或者蓝图中。
:--:1
@@ -98,10 +78,10 @@ async def my_signal_handler():
async def my_signal_handler(conn_info):
print("Connection has been closed")
```
-
:---
-以下是所有可用的信号,及信号对应可接受的参数:
+These signals are the signals that are available, along with the arguments that the handlers take, and the conditions that attach (if any).
+
| Event name | Arguments | Conditions |
| -------------------------- | ------------------------------- | --------------------------------------------------------- |
@@ -123,12 +103,7 @@ async def my_signal_handler(conn_info):
| `server.shutdown.before` | app, loop | |
| `server.shutdown.after` | app, loop | |
----:1
-
-为了更方便的使用内置信号,Sanic 设置了一个 `Enum` 对象,其中包含了所有允许的内置信号。您无需记住字符串形式的事件名称即可直接使用。
-
-:--:1
-
+为了更方便的使用内置信号,Sanic 设置了一个 `Enum` 对象,其中包含了所有允许的内置信号。 您无需记住字符串形式的事件名称即可直接使用。 :--:1
```python
from sanic.signals import Event
@@ -136,40 +111,24 @@ from sanic.signals import Event
async def my_signal_handler(conn_info):
print("Connection has been closed")
```
-
:---
## 事件(Events)
----:1
-
-信号是基于一个 _event_ 的一个事件,就是一个简单的字符串,它由以下部分组成如下:
-
-:--:1
-
+信号是基于一个 _event_ 的一个事件,就是一个简单的字符串,它由以下部分组成如下: An event, is simply a string in the following pattern: :--:1
```
namespace.reference.action
```
-
:---
-::: tip 小提示:
-
-事件必须包含三个部分。如果您不是很清楚怎么声明一个事件,可以看看下面这些例子:
+事件必须包含三个部分。 如果您不是很清楚怎么声明一个事件,可以看看下面这些例子:
- `my_app.something.happened`
-- `sanic.notice.hello`
-
-:::
+- sanic.notice.hello
### 事件参数(Event parameters)
----:1
-
-一个事件可以是“动态的”,其动态的部分使用与 [路由参数](../basics/routing.md#path-parameters) 相同的语法来声明。这允许事件根据任意值进行匹配。
-
-:--:1
-
+一个事件可以是“动态的”,其动态的部分使用与 [路由参数](../basics/routing.md#path-parameters) 相同的语法来声明。 这允许事件根据任意值进行匹配。 :--:1
```python
@app.signal("foo.bar.")
async def signal_handler(thing):
@@ -180,40 +139,24 @@ async def trigger(request):
await app.dispatch("foo.bar.baz")
return response.text("Done.")
```
-
:---
查看 [路由参数](../basics/routing.md#path-parameters) 一节来获取更多信息。
-::: warning
-
只有事件的第三部分(“动作”部分)可以是动态的:
- `foo.bar.` :ok:
- `foo..baz` :x:
-:::
-
### 等待(Waiting)
----:1
-
-除了主动分发信号来执行事件的响应函数,您的应用程序还可以被动地等待事件被触发。
-
-:--:1
-
+除了主动分发信号来执行事件的响应函数,您的应用程序还可以被动地等待事件被触发。 :--:1
```python
await app.event("foo.bar.baz")
```
-
:---
----:1
-
-**重要**:等待是一个阻塞的动作。因此您可能会想使用 [后台任务](../basics/tasks.md) 来实现类型的功能。
-
-:--:1
-
+**重要**:等待是一个阻塞的动作。 因此您可能会想使用 [后台任务](../basics/tasks.md) 来实现类型的功能。 :--:1
```python
async def wait_for_event(app):
while True:
@@ -225,38 +168,30 @@ async def wait_for_event(app):
async def after_server_start(app, loop):
app.add_task(wait_for_event(app))
```
-
:---
----:1
-
-您可以使用 `*` 符号来匹配任意动态事件。
+---:1 If your event was defined with a dynamic path, you can use `*` to catch any action. :--:1
+```python
+@app.signal("foo.bar.")
-:--:1
+...
-```python
@app.signal("foo.bar.")
...
await app.event("foo.bar.*")
```
-
:---
## 分发(Dispatching)
-_未来,Sanic 将自动分发一些事件,以帮助开发人员注入程序和请求生命周期。_
+*未来,Sanic 将自动分发一些事件,以帮助开发人员注入程序和请求生命周期。*
----:1
-
-分发事件后将会做两件事件:
+:::
1. 执行所有和该事件绑定的响应函数。
-2. 触发任何正在“等待”该事件的响应函数。
-
-:--:1
-
+2. 触发任何正在“等待”该事件的响应函数。 :--:1
```python
@app.signal("foo.bar.")
async def foo_bar(thing):
@@ -264,21 +199,14 @@ async def foo_bar(thing):
await app.dispatch("foo.bar.baz")
```
-
```
thing=baz
```
-
:---
### 上下文(Context)
----:1
-
-有时您会需要向信号的响应函数中传递额外的信息。在上面的第一个例子中,我们希望在注册的事件中能够获取用户使用的电子邮件地址。
-
-:--:1
-
+---:1 Sometimes you may find the need to pass extra information into the signal handler. 在上面的第一个例子中,我们希望在注册的事件中能够获取用户使用的电子邮件地址。 :--:1
```python
@app.signal("user.registration.created")
async def send_registration_email(**context):
@@ -289,29 +217,20 @@ await app.dispatch(
context={"hello": "world"}
)
```
-
```
{'hello': 'world'}
```
-
:---
-::: tip 小提示
-
-信号是在后台任务中分发的。
-
+::: tip FYI
+Signals are dispatched in a background task.
:::
### 蓝图(Blueprints)
-在蓝图中分发信号的工作机制类似于 [中间件](.../basics/middleware.md)。在应用层面所分发的任何信号,都会传递到蓝图上。但如果只在蓝图上分发,就只会执行在该蓝图上定义的信号响应函数。
-
----:1
-
-下面的例子可以更好解释:
-
-:--:1
+在蓝图中分发信号的工作机制类似于 [中间件](.../basics/middleware.md)。 在应用层面所分发的任何信号,都会传递到蓝图上。 但如果只在蓝图上分发,就只会执行在该蓝图上定义的信号响应函数。
+::: warning
```python
bp = Blueprint("bp")
@@ -328,33 +247,20 @@ def bp_signal():
nonlocal bp_counter
bp_counter += 1
```
-
:---
----:1
-
-调用 `app.dispatch("foo.bar.baz")` 将触发两个信号响应函数。
-
-:--:1
-
+调用 `app.dispatch("foo.bar.baz")` 将触发两个信号响应函数。 :--:1
```python
await app.dispatch("foo.bar.baz")
assert app_counter == 1
assert bp_counter == 1
```
-
:---
----:1
-
-调用 `bp.dispatch("foo.bar.baz")` 将只触发一个信号响应函数。
-
-:--:1
-
+调用 `bp.dispatch("foo.bar.baz")` 将只触发一个信号响应函数。 :--:1
```python
await bp.dispatch("foo.bar.baz")
assert app_counter == 1
assert bp_counter == 2
```
-
:---
From 28785852adacd2e8b1d4e4772ff639e685452bad Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:32 +0300
Subject: [PATCH 036/776] New translations signals.md (Portuguese, Brazilian)
---
src/pt/guide/advanced/signals.md | 262 +++++++++++++++++++++++++++++++
1 file changed, 262 insertions(+)
create mode 100644 src/pt/guide/advanced/signals.md
diff --git a/src/pt/guide/advanced/signals.md b/src/pt/guide/advanced/signals.md
new file mode 100644
index 0000000000..c8a603cf52
--- /dev/null
+++ b/src/pt/guide/advanced/signals.md
@@ -0,0 +1,262 @@
+# Signals
+
+Signals provide a way for one part of your application to tell another part that something happened.
+
+```python
+@app.signal("user.registration.created")
+async def send_registration_email(**context):
+ await send_email(context["email"], template="registration")
+
+@app.post("/register")
+async def handle_registration(request):
+ await do_registration(request)
+ await request.app.dispatch(
+ "user.registration.created",
+ context={"email": request.json.email}
+ })
+```
+
+## Adding a signal
+
+---:1 The API for adding a signal is very similar to adding a route. :--:1
+```python
+async def my_signal_handler():
+ print("something happened")
+
+app.add_signal(my_signal_handler, "something.happened.ohmy")
+```
+:---
+
+---:1 But, perhaps a slightly more convenient method is to use the built-in decorators. :--:1
+```python
+@app.signal("something.happened.ohmy")
+async def my_signal_handler():
+ print("something happened")
+```
+:---
+
+---:1 If the signal requires conditions, make sure to add them while adding the handler. :--:1
+```python
+async def my_signal_handler1():
+ print("something happened")
+
+app.add_signal(
+ my_signal_handler,
+ "something.happened.ohmy1",
+ conditions={"some_condition": "value"}
+)
+
+@app.signal("something.happened.ohmy2", conditions={"some_condition": "value"})
+async def my_signal_handler2():
+ print("something happened")
+```
+:---
+
+---:1 Signals can also be declared on blueprints :--:1
+```python
+bp = Blueprint("foo")
+
+@bp.signal("something.happened.ohmy")
+async def my_signal_handler():
+ print("something happened")
+```
+:---
+
+## Built-in signals
+
+In addition to creating a new signal, there are a number of built-in signals that are dispatched from Sanic itself. These signals exist to provide developers with more opportunities to add functionality into the request and server lifecycles.
+
+---:1
+
+
+You can attach them just like any other signal to an application or blueprint instance.
+
+:--:1
+
+```python
+@app.signal("http.lifecycle.complete")
+async def my_signal_handler(conn_info):
+ print("Connection has been closed")
+```
+:---
+
+These signals are the signals that are available, along with the arguments that the handlers take, and the conditions that attach (if any).
+
+
+| Event name | Arguments | Conditions |
+| -------------------------- | ------------------------------- | --------------------------------------------------------- |
+| `http.routing.before` | request | |
+| `http.routing.after` | request, route, kwargs, handler | |
+| `http.lifecycle.begin` | conn_info | |
+| `http.lifecycle.read_head` | head | |
+| `http.lifecycle.request` | request | |
+| `http.lifecycle.handle` | request | |
+| `http.lifecycle.read_body` | body | |
+| `http.lifecycle.exception` | request, exception | |
+| `http.lifecycle.response` | request, response | |
+| `http.lifecycle.send` | data | |
+| `http.lifecycle.complete` | conn_info | |
+| `http.middleware.before` | request, response | `{"attach_to": "request"}` or `{"attach_to": "response"}` |
+| `http.middleware.after` | request, response | `{"attach_to": "request"}` or `{"attach_to": "response"}` |
+| `server.init.before` | app, loop | |
+| `server.init.after` | app, loop | |
+| `server.shutdown.before` | app, loop | |
+| `server.shutdown.after` | app, loop | |
+
+---:1 To make using the built-in signals easier, there is an `Enum` object that contains all of the allowed built-ins. With a modern IDE this will help so that you do not need to remember the full list of event names as strings. :--:1
+```python
+from sanic.signals import Event
+
+@app.signal(Event.HTTP_LIFECYCLE_COMPLETE)
+async def my_signal_handler(conn_info):
+ print("Connection has been closed")
+```
+:---
+
+## Events
+
+---:1 Signals are based off of an _event_. An event, is simply a string in the following pattern: :--:1
+```
+namespace.reference.action
+```
+:---
+
+::: tip Events must have three parts. If you do not know what to use, try these patterns:
+
+- `my_app.something.happened`
+- `sanic.notice.hello` :::
+
+### Event parameters
+
+---:1 An event can be "dynamic" and declared using the same syntax as [path parameters](../basics/routing.md#path-parameters). This allows matching based upon arbitrary values. :--:1
+```python
+@app.signal("foo.bar.")
+async def signal_handler(thing):
+ print(f"[signal_handler] {thing=}")
+
+@app.get("/")
+async def trigger(request):
+ await app.dispatch("foo.bar.baz")
+ return response.text("Done.")
+```
+:---
+
+Checkout [path parameters](../basics/routing.md#path-parameters) for more information on allowed type definitions.
+
+::: warning Only the third part of an event (the "action") may be dynamic:
+
+- `foo.bar.` :ok:
+- `foo..baz` :x: :::
+
+### Waiting
+
+---:1 In addition to executing a signal handler, your application can wait for an event to be triggered. :--:1
+```python
+await app.event("foo.bar.baz")
+```
+:---
+
+---:1 **IMPORTANT**: waiting is a blocking function. Therefore, you likely will want this to run in a [background task](../basics/tasks.md). :--:1
+```python
+async def wait_for_event(app):
+ while True:
+ print("> waiting")
+ await app.event("foo.bar.baz")
+ print("> event found\n")
+
+@app.after_server_start
+async def after_server_start(app, loop):
+ app.add_task(wait_for_event(app))
+```
+:---
+
+---:1 If your event was defined with a dynamic path, you can use `*` to catch any action. :--:1
+```python
+@app.signal("foo.bar.")
+
+...
+
+await app.event("foo.bar.*")
+```
+:---
+
+## Dispatching
+
+*In the future, Sanic will dispatch some events automatically to assist developers to hook into life cycle events.*
+
+---:1 Dispatching an event will do two things:
+
+1. execute any signal handlers defined on the event, and
+2. resolve anything that is "waiting" for the event to complete. :--:1
+```python
+@app.signal("foo.bar.")
+async def foo_bar(thing):
+ print(f"{thing=}")
+
+await app.dispatch("foo.bar.baz")
+```
+```
+thing=baz
+```
+:---
+
+### Context
+
+---:1 Sometimes you may find the need to pass extra information into the signal handler. In our first example above, we wanted our email registration process to have the email address for the user. :--:1
+```python
+@app.signal("user.registration.created")
+async def send_registration_email(**context):
+ print(context)
+
+await app.dispatch(
+ "user.registration.created",
+ context={"hello": "world"}
+)
+```
+```
+{'hello': 'world'}
+```
+:---
+
+::: tip FYI
+Signals are dispatched in a background task.
+:::
+
+### Blueprints
+
+Dispatching blueprint signals works similar in concept to [middleware](../basics/middleware.md). Anything that is done from the app level, will trickle down to the blueprints. However, dispatching on a blueprint, will only execute the signals that are defined on that blueprint.
+
+---:1 Perhaps an example is easier to explain: :--:1
+```python
+bp = Blueprint("bp")
+
+app_counter = 0
+bp_counter = 0
+
+@app.signal("foo.bar.baz")
+def app_signal():
+ nonlocal app_counter
+ app_counter += 1
+
+@bp.signal("foo.bar.baz")
+def bp_signal():
+ nonlocal bp_counter
+ bp_counter += 1
+```
+:---
+
+---:1 Running `app.dispatch("foo.bar.baz")` will execute both signals. :--:1
+```python
+await app.dispatch("foo.bar.baz")
+assert app_counter == 1
+assert bp_counter == 1
+```
+:---
+
+---:1 Running `bp.dispatch("foo.bar.baz")` will execute only the blueprint signal. :--:1
+```python
+await bp.dispatch("foo.bar.baz")
+assert app_counter == 1
+assert bp_counter == 2
+```
+:---
From 46a8f0df3bb6b7171e4ff0523d80bdc3596a60e2 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:33 +0300
Subject: [PATCH 037/776] New translations streaming.md (Japanese)
---
src/ja/guide/advanced/streaming.md | 45 ++++++------------------------
1 file changed, 9 insertions(+), 36 deletions(-)
diff --git a/src/ja/guide/advanced/streaming.md b/src/ja/guide/advanced/streaming.md
index 96cc648296..2586864fe7 100644
--- a/src/ja/guide/advanced/streaming.md
+++ b/src/ja/guide/advanced/streaming.md
@@ -8,8 +8,7 @@ Sanicを使用すると、クライアントから送信されたデータをス
エンドポイントで有効にすると、`await request.stream.read()`を使用してリクエストボディをストリーミングできます。
-そのメソッドは、本文が完了すると「なし」を返します。
-:--:1
+That method will return `None` when the body is completed. :--:1
```python
from sanic.views import stream
@@ -28,8 +27,7 @@ class SimpleView(HTTPMethodView):
---:1
-また、デコレータのキーワード引数で有効にすることもできます。
-:--:1
+また、デコレータのキーワード引数で有効にすることもできます。 :--:1 :--:1
```python
@app.post("/stream", stream=True)
async def handler(request):
@@ -41,8 +39,7 @@ async def handler(request):
---:1
-... or the `add_route()` method.
-:--:1
+... or the `add_route()` method. :--:1
```python
bp.add_route(
bp_handler,
@@ -55,16 +52,12 @@ bp.add_route(
::: tip FYI
Post、put、patchデコレータのみがストリーム引数を持っています。
-:::
+::: :::
## Response streaming
----:1
-
-Sanicを使用すると、「StreamingHTTPResponse」のインスタンスを使用してクライアントにコンテンツをストリーミングできます。`sanic.response.stream`コンビニエンスメソッドもあります。
+---:1 Sanic allows you to stream content to the client. :--:1
-このメソッドは、クライアントへの書き込みを制御できるオブジェクトを渡されるコルーチンコールバックを受け入れます。
-:--:1
```python
from sanic.response import stream
@@ -78,7 +71,7 @@ async def test(request):
```
:---
-これは、データベースなどの外部サービスに由来するクライアントにコンテンツをストリーミングする場合に便利です。たとえば、`asyncpg`が提供する非同期カーソルを使用して、データベースレコードをクライアントにストリーミングできます。
+これは、データベースなどの外部サービスに由来するクライアントにコンテンツをストリーミングする場合に便利です。 たとえば、`asyncpg`が提供する非同期カーソルを使用して、データベースレコードをクライアントにストリーミングできます。
```python
@app.route("/")
@@ -92,37 +85,17 @@ async def index(request):
return stream(stream_from_db)
```
-::: tip FYI
-クライアントが HTTP/1.1 をサポートしている場合、Sanic は [チャンク転送エンコーディング](https://en.wikipedia.org/wiki/Chunked_transfer_encoding) を使用します。ストリーム関数のチャンクオプションを使用して明示的に有効または無効にできます。
-:::
-
----:1
-
-`stream`を使用したコルーチンコールバックパターンは必要ありません。これはストリーミングの*古いスタイル*であり、新しいインラインストリーミングに置き換える必要があります。これで、ハンドラーで応答を直接ストリーミングできるようになりました。
-:--:1
-```python
-@app.route("/")
-async def test(request):
- response = await request.respond(content_type="text/csv")
- await response.send("foo,")
- await response.send("bar")
- await response.eof()
- return response
-```
-:---
-
-上記の例では、`await response.eof()` は `await response.send("", True)` を置き換える便利なメソッドとして呼び出されます。ハンドラがクライアントに送り返すものが何も残っていないと判断した場合、** 1回** *after*を呼び出す必要があります。
+You can explicitly end a stream by calling `await response.eof()`. 上記の例では、`await response.eof()` は `await response.send("", True)` を置き換える便利なメソッドとして呼び出されます。 ハンドラがクライアントに送り返すものが何も残っていないと判断した場合、** 1回** *after*を呼び出す必要があります。 While it is *optional* to use with Sanic server, if you are running Sanic in ASGI mode, then you **must** explicitly terminate the stream.
## File streaming
---:1
-Sanicは、大きなファイルを送信する場合に便利な `sanic.response.file_stream` 関数を提供します。`StreamingHTTPResponse`オブジェクトを返し、デフォルトでチャンク転送エンコーディングを使用します。このため、Sanicは応答に`Content-Length` HTTPヘッダーを追加しません。
+Sanicは、大きなファイルを送信する場合に便利な `sanic.response.file_stream` 関数を提供します。 `StreamingHTTPResponse`オブジェクトを返し、デフォルトでチャンク転送エンコーディングを使用します。 このため、Sanicは応答に`Content-Length` HTTPヘッダーを追加しません。
-典型的なユースケースは、ビデオファイルをストリーミングしている可能性があります。
-:--:1
+典型的なユースケースは、ビデオファイルをストリーミングしている可能性があります。 :--:1 :--:1
```python
@app.route("/mp4")
async def handler_file_stream(request):
From d8d5b2c758299c7c910c4e4f7ac5c36e3f3c2de5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:34 +0300
Subject: [PATCH 038/776] New translations streaming.md (Korean)
---
src/ko/guide/advanced/streaming.md | 132 +++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
create mode 100644 src/ko/guide/advanced/streaming.md
diff --git a/src/ko/guide/advanced/streaming.md b/src/ko/guide/advanced/streaming.md
new file mode 100644
index 0000000000..e03be7cb3e
--- /dev/null
+++ b/src/ko/guide/advanced/streaming.md
@@ -0,0 +1,132 @@
+# Streaming
+
+## Request streaming
+
+Sanic allows you to stream data sent by the client to begin processing data as the bytes arrive.
+
+---:1
+
+When enabled on an endpoint, you can stream the request body using `await request.stream.read()`.
+
+That method will return `None` when the body is completed. :--:1
+```python
+from sanic.views import stream
+
+class SimpleView(HTTPMethodView):
+ @stream
+ async def post(self, request):
+ result = ""
+ while True:
+ body = await request.stream.read()
+ if body is None:
+ break
+ result += body.decode("utf-8")
+ return text(result)
+```
+:---
+
+---:1
+
+It also can be enabled with a keyword argument in the decorator... :--:1
+```python
+@app.post("/stream", stream=True)
+async def handler(request):
+ ...
+ body = await request.stream.read()
+ ...
+```
+:---
+
+---:1
+
+... or the `add_route()` method. :--:1
+```python
+bp.add_route(
+ bp_handler,
+ "/bp_stream",
+ methods=["POST"],
+ stream=True,
+)
+```
+:---
+
+::: tip FYI
+Only post, put and patch decorators have stream argument.
+:::
+
+## Response streaming
+
+---:1 Sanic allows you to stream content to the client. :--:1
+
+```python
+@app.route("/")
+async def test(request):
+ response = await request.respond(content_type="text/csv")
+ await response.send("foo,")
+ await response.send("bar")
+
+ # Optionally, you can explicitly end the stream by calling:
+ await response.eof()
+```
+:---
+
+This is useful in situations where you want to stream content to the client that originates in an external service, like a database. For example, you can stream database records to the client with the asynchronous cursor that `asyncpg` provides.
+
+```python
+@app.route("/")
+async def index(request):
+ response = await request.respond()
+ conn = await asyncpg.connect(database='test')
+ async with conn.transaction():
+ async for record in conn.cursor('SELECT generate_series(0, 10)'):
+ await response.send(record[0])
+```
+
+
+
+You can explicitly end a stream by calling `await response.eof()`. It a convenience method to replace `await response.send("", True)`. It should be called **one time** *after* your handler has determined that it has nothing left to send back to the client. While it is *optional* to use with Sanic server, if you are running Sanic in ASGI mode, then you **must** explicitly terminate the stream.
+
+## File streaming
+
+---:1
+
+Sanic provides `sanic.response.file_stream` function that is useful when you want to send a large file. It returns a `StreamingHTTPResponse` object and will use chunked transfer encoding by default; for this reason Sanic doesn’t add `Content-Length` HTTP header in the response.
+
+A typical use case might be streaming an video file. :--:1
+```python
+@app.route("/mp4")
+async def handler_file_stream(request):
+ return await response.file_stream(
+ "/path/to/sample.mp4",
+ chunk_size=1024,
+ mime_type="application/metalink4+xml",
+ headers={
+ "Content-Disposition": 'Attachment; filename="nicer_name.meta4"',
+ "Content-Type": "application/metalink4+xml",
+ },
+ )
+```
+:---
+
+---:1
+
+If you want to use the `Content-Length` header, you can disable chunked transfer encoding and add it manually simply by adding the `Content-Length` header.
+
+:--:1
+```python
+from aiofiles import os as async_os
+from sanic.response import file_stream
+
+@app.route("/")
+async def index(request):
+ file_path = "/srv/www/whatever.png"
+
+ file_stat = await async_os.stat(file_path)
+ headers = {"Content-Length": str(file_stat.st_size)}
+
+ return await file_stream(
+ file_path,
+ headers=headers,
+ )
+```
+:---
From dd566fbd01c0c4e227f0bda69ed9c2551dfa9757 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:36 +0300
Subject: [PATCH 039/776] New translations streaming.md (Chinese Simplified)
---
src/zh/guide/advanced/streaming.md | 74 ++++++------------------------
1 file changed, 13 insertions(+), 61 deletions(-)
diff --git a/src/zh/guide/advanced/streaming.md b/src/zh/guide/advanced/streaming.md
index 6afdd8bf3d..042d539721 100644
--- a/src/zh/guide/advanced/streaming.md
+++ b/src/zh/guide/advanced/streaming.md
@@ -8,10 +8,7 @@ Sanic 允许您以串流的形式接收并响应由客户端发送来的数据
当在一个路由上启用了流式传输,您就可以使用 `await request.stream.read()` 方法来获取请求数据流。
-当请求中所有的数据都传输完毕后,该方法会返回 `None` 值。
-
-:--:1
-
+That method will return `None` when the body is completed. :--:1
```python
from sanic.views import stream
@@ -27,31 +24,25 @@ class SimpleView(HTTPMethodView):
result += body.decode("utf-8")
return text(result)
```
-
:---
---:1
-在使用装饰器注册路由时也可以传入关键字参数来启动流式传输...
-
-:--:1
-
+It also can be enabled with a keyword argument in the decorator... :--:1
```python
@app.post("/stream", stream=True)
async def handler(request):
...
body = await request.stream.read()
...
+ body = await request.stream.read()
+ ...
```
-
:---
---:1
-... 或者在调用 `add_route` 方法是传入该参数。
-
-:--:1
-
+... 或者在调用 `add_route` 方法是传入该参数。 :--:1
```python
bp.add_route(
bp_handler,
@@ -60,24 +51,15 @@ bp.add_route(
stream=True,
)
```
-
:---
-::: tip 小提示
-
-只有在 post,put 和 patch 装饰器中才有该参数。
-
+::: tip FYI
+Only post, put and patch decorators have stream argument.
:::
## 响应流(Response streaming)
----:1
-
-Sanic 中的 `StreamingHTTPResponse` 对象允许您将响应的内容串流给客户端。也可以使用 `sanic.response.stream` 这个方法。
-
-这个方法接受一个协程函数作为回调,同时,该回调必须接受一个参数,该参数是一个可以控制向客户端传输数据的对象。
-
-:--:1
+---:1 Sanic allows you to stream content to the client. :--:1
```python
from sanic.response import stream
@@ -91,10 +73,9 @@ async def test(request):
return stream(sample_streaming_fn, content_type="text/csv")
```
-
:---
-流式传输在处理一些依赖第三方服务的场景下十分有用,比如数据库。下面的示例代码展示了使用 `asyncpg` 提供的异步游标来为客户端串流数据库的查询结果。
+流式传输在处理一些依赖第三方服务的场景下十分有用,比如数据库。 下面的示例代码展示了使用 `asyncpg` 提供的异步游标来为客户端串流数据库的查询结果。
```python
@app.route("/")
@@ -108,43 +89,17 @@ async def index(request):
return stream(stream_from_db)
```
-::: tip 小提示
-如果客户端支持 HTTP/1.1,Sanic 将会使用 [分块传输编码](https://en.wikipedia.org/wiki/Chunked_transfer_encoding) 进行流式传输;您也可以指定是否启用分块传输编码选项。
-:::
-
----:1
-
-使用协程 + 回调的方式来进行流式传输已经是*明日黄花*。您应该使用新的方式来进行串流。新方式的好处是允许您以自然的语序来编写处理串流的响应函数代码(非回调)。
-
-:--:1
-
-```python
-@app.route("/")
-async def test(request):
- response = await request.respond(content_type="text/csv")
- await response.send("foo,")
- await response.send("bar")
- await response.eof()
- return response
-```
-
-:---
-
-在上述例子中调用 `await response.eof()` 方法可以替代之前的 `await response.send("", True)` 方法。为客户端传输完数据*后*,您应该在响应函数内调用**一次**该方法。
+You can explicitly end a stream by calling `await response.eof()`. 在上述例子中调用 `await response.eof()` 方法可以替代之前的 `await response.send("", True)` 方法。 为客户端传输完数据*后*,您应该在响应函数内调用**一次**该方法。 While it is *optional* to use with Sanic server, if you are running Sanic in ASGI mode, then you **must** explicitly terminate the stream.
## 文件流(File streaming)
---:1
-Sanic 提供了 `sanic.response.file_stream` 函数来处理发送大文件的场景。该函数会返回一个 `StreamingHTTPResponse` 对象,并且默认使用分块传输编码;因此 Sanic
-不会为该响应添加 `Content-Length` 响应头。
-
-通常,我们可能为客户端串流一个视频文件。
-
-:--:1
+Sanic 提供了 `sanic.response.file_stream` 函数来处理发送大文件的场景。 该函数会返回一个 `StreamingHTTPResponse` 对象,并且默认使用分块传输编码;因此 Sanic 不会为该响应添加 `Content-Length` 响应头。
+A typical use case might be streaming an video file. :--:1
```python
@app.route("/mp4")
async def handler_file_stream(request):
@@ -158,15 +113,13 @@ async def handler_file_stream(request):
},
)
```
-
:---
---:1
-如果您想手动添加 `Content-Length` 响应头,参考下面的代码。并且如果您添加了该头,则会自动禁用分块传输编码。
+如果您想手动添加 `Content-Length` 响应头,参考下面的代码。 并且如果您添加了该头,则会自动禁用分块传输编码。
:--:1
-
```python
from aiofiles import os as async_os
from sanic.response import file_stream
@@ -184,5 +137,4 @@ async def index(request):
headers=headers,
)
```
-
:---
From 833029306612e4250ea438653244f93624339d9a Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:37 +0300
Subject: [PATCH 040/776] New translations streaming.md (Portuguese, Brazilian)
---
src/pt/guide/advanced/streaming.md | 132 +++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
create mode 100644 src/pt/guide/advanced/streaming.md
diff --git a/src/pt/guide/advanced/streaming.md b/src/pt/guide/advanced/streaming.md
new file mode 100644
index 0000000000..e03be7cb3e
--- /dev/null
+++ b/src/pt/guide/advanced/streaming.md
@@ -0,0 +1,132 @@
+# Streaming
+
+## Request streaming
+
+Sanic allows you to stream data sent by the client to begin processing data as the bytes arrive.
+
+---:1
+
+When enabled on an endpoint, you can stream the request body using `await request.stream.read()`.
+
+That method will return `None` when the body is completed. :--:1
+```python
+from sanic.views import stream
+
+class SimpleView(HTTPMethodView):
+ @stream
+ async def post(self, request):
+ result = ""
+ while True:
+ body = await request.stream.read()
+ if body is None:
+ break
+ result += body.decode("utf-8")
+ return text(result)
+```
+:---
+
+---:1
+
+It also can be enabled with a keyword argument in the decorator... :--:1
+```python
+@app.post("/stream", stream=True)
+async def handler(request):
+ ...
+ body = await request.stream.read()
+ ...
+```
+:---
+
+---:1
+
+... or the `add_route()` method. :--:1
+```python
+bp.add_route(
+ bp_handler,
+ "/bp_stream",
+ methods=["POST"],
+ stream=True,
+)
+```
+:---
+
+::: tip FYI
+Only post, put and patch decorators have stream argument.
+:::
+
+## Response streaming
+
+---:1 Sanic allows you to stream content to the client. :--:1
+
+```python
+@app.route("/")
+async def test(request):
+ response = await request.respond(content_type="text/csv")
+ await response.send("foo,")
+ await response.send("bar")
+
+ # Optionally, you can explicitly end the stream by calling:
+ await response.eof()
+```
+:---
+
+This is useful in situations where you want to stream content to the client that originates in an external service, like a database. For example, you can stream database records to the client with the asynchronous cursor that `asyncpg` provides.
+
+```python
+@app.route("/")
+async def index(request):
+ response = await request.respond()
+ conn = await asyncpg.connect(database='test')
+ async with conn.transaction():
+ async for record in conn.cursor('SELECT generate_series(0, 10)'):
+ await response.send(record[0])
+```
+
+
+
+You can explicitly end a stream by calling `await response.eof()`. It a convenience method to replace `await response.send("", True)`. It should be called **one time** *after* your handler has determined that it has nothing left to send back to the client. While it is *optional* to use with Sanic server, if you are running Sanic in ASGI mode, then you **must** explicitly terminate the stream.
+
+## File streaming
+
+---:1
+
+Sanic provides `sanic.response.file_stream` function that is useful when you want to send a large file. It returns a `StreamingHTTPResponse` object and will use chunked transfer encoding by default; for this reason Sanic doesn’t add `Content-Length` HTTP header in the response.
+
+A typical use case might be streaming an video file. :--:1
+```python
+@app.route("/mp4")
+async def handler_file_stream(request):
+ return await response.file_stream(
+ "/path/to/sample.mp4",
+ chunk_size=1024,
+ mime_type="application/metalink4+xml",
+ headers={
+ "Content-Disposition": 'Attachment; filename="nicer_name.meta4"',
+ "Content-Type": "application/metalink4+xml",
+ },
+ )
+```
+:---
+
+---:1
+
+If you want to use the `Content-Length` header, you can disable chunked transfer encoding and add it manually simply by adding the `Content-Length` header.
+
+:--:1
+```python
+from aiofiles import os as async_os
+from sanic.response import file_stream
+
+@app.route("/")
+async def index(request):
+ file_path = "/srv/www/whatever.png"
+
+ file_stat = await async_os.stat(file_path)
+ headers = {"Content-Length": str(file_stat.st_size)}
+
+ return await file_stream(
+ file_path,
+ headers=headers,
+ )
+```
+:---
From 81c7c1dcaca97a5b40dbcc8fd127b6f67d48e9fe Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:38 +0300
Subject: [PATCH 041/776] New translations versioning.md (Japanese)
---
src/ja/guide/advanced/versioning.md | 32 +++++++++--------------------
1 file changed, 10 insertions(+), 22 deletions(-)
diff --git a/src/ja/guide/advanced/versioning.md b/src/ja/guide/advanced/versioning.md
index ab78986576..3a01726174 100644
--- a/src/ja/guide/advanced/versioning.md
+++ b/src/ja/guide/advanced/versioning.md
@@ -1,10 +1,10 @@
# Versioning
-API構築では、エンドポイントにバージョンを追加するのが標準プラクティスです。これにより、APIを断りなく変更しようとすると、互換性のないエンドポイントを簡単に区別できます。
+API構築では、エンドポイントにバージョンを追加するのが標準プラクティスです。 これにより、APIを断りなく変更しようとすると、互換性のないエンドポイントを簡単に区別できます。
バージョンを追加すると、エンドポイントに`/v{version}` URLプレフィックスが追加されます。
-バージョンは `int`、`float`、または `str` にすることができます。許容値:
+バージョンは `int`、`float`、または `str` にすることができます。 許容値:
- `1`, `2`, `3`
- `1.1`, `2.25`, `3.0`
@@ -14,8 +14,7 @@ API構築では、エンドポイントにバージョンを追加するのが
---:1
-バージョン番号をルートに直接渡すことができます。
-:--:1
+バージョン番号をルートに直接渡すことができます。 :--:1 :--:1
```python
# /v1/text
@app.route("/text", version=1)
@@ -33,8 +32,7 @@ def handle_request(request):
---:1
-ブループリントにバージョン番号を渡すこともできます。これは、そのブループリント内のすべてのルートに適用されます。
-:--:1
+ブループリントにバージョン番号を渡すこともできます。 これは、そのブループリント内のすべてのルートに適用されます。 :--:1 :--:1
```python
bp = Blueprint("test", url_prefix="/foo", version=1)
@@ -47,10 +45,7 @@ def handle_request(request):
## Per Blueprint Group
----:1
-バージョン管理を簡素化するために、ブループリントにバージョン番号を提供できます
-グループ。青写真がまだ上書きされていない場合、その下にグループ化されたすべての青写真にも同じことが継承されます
-ブループリントインスタンスの作成中に指定された値と同じ情報。
+---:1 バージョン管理を簡素化するために、ブループリントにバージョン番号を提供できます グループ。 青写真がまだ上書きされていない場合、その下にグループ化されたすべての青写真にも同じことが継承されます ブループリントインスタンスの作成中に指定された値と同じ情報。
バージョンの管理にブループリントグループを使用する場合は、バージョンプレフィックスを登録されているルート。
@@ -59,8 +54,6 @@ def handle_request(request):
3. ブループリントグループレベルの構成
より尖ったバージョニング仕様を見つけたら、より一般的なバージョニング仕様よりもそれを選びますブループリントまたはブループリントグループの下で提供
-
-:--:1
```python
from sanic.blueprints import Blueprint
from sanic.response import json
@@ -100,7 +93,7 @@ async def handle_endpoint_2_bp2(request):
## Version prefix
-上記のように、ルートに適用される `version` は、生成された URI パスの最初のセグメントを **常に** です。したがって、バージョンの前にパスセグメントを追加できるように、`version`引数が渡されるすべての場所で、`version_prefix`を渡すこともできます。
+上記のように、ルートに適用される `version` は、生成された URI パスの最初のセグメントを **常に** です。 したがって、バージョンの前にパスセグメントを追加できるように、`version`引数が渡されるすべての場所で、`version_prefix`を渡すこともできます。
`version_prefix`引数は次のように定義できます。
@@ -110,22 +103,18 @@ async def handle_endpoint_2_bp2(request):
- `BlueprintGroup` instantiation
- `app.blueprint` registration
-複数の場所に定義がある場合、より具体的な定義はより一般的な定義を上書きします。このリストはその階層を提供します。
+複数の場所に定義がある場合、より具体的な定義はより一般的な定義を上書きします。 このリストはその階層を提供します。
`version_prefix`のデフォルト値は`/v`です。
----:1
-頻繁に要求される機能は、バージョン管理されたルートを `/api` にマウントできるようにすることです。これは「version_prefix」で簡単に実現できます。
-:--:1
+---:1 頻繁に要求される機能は、バージョン管理されたルートを `/api` にマウントできるようにすることです。 これは「version_prefix」で簡単に実現できます。 :--:1 :--:1
```python
# /v1/my/path
app.route("/my/path", version=1, version_prefix="/api/v")
```
:---
----:1
-おそらく、より説得力のある使用法は、すべての「/api」ルートを単一の「BlueprintGroup」にロードすることです。
-:--:1
+---:1 おそらく、より説得力のある使用法は、すべての「/api」ルートを単一の「BlueprintGroup」にロードすることです。 :--:1 :--:1
```python
# /v1/my/path
app = Sanic(__name__)
@@ -147,8 +136,7 @@ app.blueprint(api)
version_prefix + version + url_prefix + URI definition
```
-::: tip
-`url_prefix`と同様に、`version_prefix`内にパスパラメータを定義することができます。これを行うことは完全に合法です。すべてのルートには、そのパラメータがハンドラーに注入されることを覚えておいてください。
+::: tip `url_prefix`と同様に、`version_prefix`内にパスパラメータを定義することができます。 これを行うことは完全に合法です。 すべてのルートには、そのパラメータがハンドラーに注入されることを覚えておいてください。
```python
version_prefix="//v"
From ab8ca227f17001613e2afd3bd9f5db6508d51fb3 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:39 +0300
Subject: [PATCH 042/776] New translations versioning.md (Korean)
---
src/ko/guide/advanced/versioning.md | 144 ++++++++++++++++++++++++++++
1 file changed, 144 insertions(+)
create mode 100644 src/ko/guide/advanced/versioning.md
diff --git a/src/ko/guide/advanced/versioning.md b/src/ko/guide/advanced/versioning.md
new file mode 100644
index 0000000000..8995683ed0
--- /dev/null
+++ b/src/ko/guide/advanced/versioning.md
@@ -0,0 +1,144 @@
+# Versioning
+
+It is standard practice in API building to add versions to your endpoints. This allows you to easily differentiate incompatible endpoints when you try and change your API down the road in a breaking manner.
+
+Adding a version will add a `/v{version}` url prefix to your endpoints.
+
+The version can be a `int`, `float`, or `str`. Acceptable values:
+
+- `1`, `2`, `3`
+- `1.1`, `2.25`, `3.0`
+- `"1"`, `"v1"`, `"v1.1"`
+
+## Per route
+
+---:1
+
+You can pass a version number to the routes directly. :--:1
+```python
+# /v1/text
+@app.route("/text", version=1)
+def handle_request(request):
+ return response.text("Hello world! Version 1")
+
+# /v2/text
+@app.route("/text", version=2)
+def handle_request(request):
+ return response.text("Hello world! Version 2")
+```
+:---
+
+## Per Blueprint
+
+---:1
+
+You can also pass a version number to the blueprint, which will apply to all routes in that blueprint. :--:1
+```python
+bp = Blueprint("test", url_prefix="/foo", version=1)
+
+# /v1/foo/html
+@bp.route("/html")
+def handle_request(request):
+ return response.html("
Hello world!
")
+```
+:---
+
+## Per Blueprint Group
+
+---:1 In order to simplify the management of the versioned blueprints, you can provide a version number in the blueprint group. The same will be inherited to all the blueprint grouped under it if the blueprints don't already override the same information with a value specified while creating a blueprint instance.
+
+When using blueprint groups for managing the versions, the following order is followed to apply the Version prefix to the routes being registered.
+
+1. Route Level configuration
+2. Blueprint level configuration
+3. Blueprint Group level configuration
+
+If we find a more pointed versioning specification, we will pick that over the more generic versioning specification provided under the Blueprint or Blueprint Group :--:1
+```python
+from sanic.blueprints import Blueprint
+from sanic.response import json
+
+bp1 = Blueprint(
+ name="blueprint-1",
+ url_prefix="/bp1",
+ version=1.25,
+)
+bp2 = Blueprint(
+ name="blueprint-2",
+ url_prefix="/bp2",
+)
+
+group = Blueprint.group(
+ [bp1, bp2],
+ url_prefix="/bp-group",
+ version="v2",
+)
+
+# GET /v1.25/bp-group/bp1/endpoint-1
+@bp1.get("/endpoint-1")
+async def handle_endpoint_1_bp1(request):
+ return json({"Source": "blueprint-1/endpoint-1"})
+
+# GET /v2/bp-group/bp2/endpoint-2
+@bp2.get("/endpoint-1")
+async def handle_endpoint_1_bp2(request):
+ return json({"Source": "blueprint-2/endpoint-1"})
+
+# GET /v1/bp-group/bp2/endpoint-2
+@bp2.get("/endpoint-2", version=1)
+async def handle_endpoint_2_bp2(request):
+ return json({"Source": "blueprint-2/endpoint-2"})
+```
+:---
+
+## Version prefix
+
+As seen above, the `version` that is applied to a route is **always** the first segment in the generated URI path. Therefore, to make it possible to add path segments before the version, every place that a `version` argument is passed, you can also pass `version_prefix`.
+
+The `version_prefix` argument can be defined in:
+
+- `app.route` and `bp.route` decorators (and all the convenience decorators also)
+- `Blueprint` instantiation
+- `Blueprint.group` constructor
+- `BlueprintGroup` instantiation
+- `app.blueprint` registration
+
+If there are definitions in multiple places, a more specific definition overrides a more general. This list provides that hierarchy.
+
+The default value of `version_prefix` is `/v`.
+
+---:1 An often requested feature is to be able to mount versioned routes on `/api`. This can easily be accomplished with `version_prefix`. :--:1
+```python
+# /v1/my/path
+app.route("/my/path", version=1, version_prefix="/api/v")
+```
+:---
+
+---:1 Perhaps a more compelling usage is to load all `/api` routes into a single `BlueprintGroup`. :--:1
+```python
+# /v1/my/path
+app = Sanic(__name__)
+v2ip = Blueprint("v2ip", url_prefix="/ip", version=2)
+api = Blueprint.group(v2ip, version_prefix="/api/version")
+
+# /api/version2/ip
+@v2ip.get("/")
+async def handler(request):
+ return text(request.ip)
+
+app.blueprint(api)
+```
+:---
+
+We can therefore learn that a route's URI is:
+
+```
+version_prefix + version + url_prefix + URI definition
+```
+
+::: tip Just like with `url_prefix`, it is possible to define path parameters inside a `version_prefix`. It is perfectly legitimate to do this. Just remember that every route will have that parameter injected into the handler.
+
+```python
+version_prefix="//v"
+```
+:::
From e146f7b6b197adeb9ca989735cc17963e2718db0 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:40 +0300
Subject: [PATCH 043/776] New translations versioning.md (Chinese Simplified)
---
src/zh/guide/advanced/versioning.md | 59 +++++++++--------------------
1 file changed, 17 insertions(+), 42 deletions(-)
diff --git a/src/zh/guide/advanced/versioning.md b/src/zh/guide/advanced/versioning.md
index 2d7fc81cc9..fe68c76db8 100644
--- a/src/zh/guide/advanced/versioning.md
+++ b/src/zh/guide/advanced/versioning.md
@@ -1,10 +1,10 @@
# 版本管理(Versioning)
-在 URL 中前添加版本信息是接口开发中的一种惯例。这样做可以让您在迭代您 API 功能时,保证旧版本 API 的兼容性。
+It is standard practice in API building to add versions to your endpoints. This allows you to easily differentiate incompatible endpoints when you try and change your API down the road in a breaking manner.
添加版本信息就是在 URL 上添加这样的 `/v{version}` 前缀。
-version 可以是 `int`,`float` 或 `str` 类型。下列值都为有效值:
+version 可以是 `int`,`float` 或 `str` 类型。 下列值都为有效值:
- `1`,`2`,`3`
- `1.1`,`2.25`,`3.0`
@@ -14,13 +14,13 @@ version 可以是 `int`,`float` 或 `str` 类型。下列值都为有效值:
---:1
-您可以在定义路由时直接传入版本号。
-
-:--:1
-
+You can pass a version number to the routes directly. :--:1
```python
# /v1/text
@app.route("/text", version=1)
+def handle_request(request):
+ return response.text("Hello world! # /v1/text
+@app.route("/text", version=1)
def handle_request(request):
return response.text("Hello world! Version 1")
@@ -28,19 +28,15 @@ def handle_request(request):
# /v2/text
@app.route("/text", version=2)
def handle_request(request):
- return response.text("Hello world! Version 2")
+ return response.text("Hello world! Version 2") Version 2")
```
-
:---
## 为蓝图添加版本前缀(Per Blueprint)
---:1
-您也可以在创建蓝图的时候传入版本号,这样蓝图下的所有路由都会拥有该版本号的前缀。
-
-:--:1
-
+您也可以在创建蓝图的时候传入版本号,这样蓝图下的所有路由都会拥有该版本号的前缀。 :--:1
```python
bp = Blueprint("test", url_prefix="/foo", version=1)
@@ -50,14 +46,11 @@ bp = Blueprint("test", url_prefix="/foo", version=1)
def handle_request(request):
return response.html("
Hello world!
")
```
-
:---
## 为蓝图组添加版本前缀(Per Blueprint Group)
----:1
-
-您可以在蓝图组中指定版本信息来简化蓝图版本的管理。如果蓝图组内的蓝图在创建时没有指定其他的版本,则将继承蓝图组所指定的版本信息。
+您可以在蓝图组中指定版本信息来简化蓝图版本的管理。 如果蓝图组内的蓝图在创建时没有指定其他的版本,则将继承蓝图组所指定的版本信息。
当您使用蓝图组来管理管本时,版本的前缀信息会按照以下顺序被自动添加在路由上。
@@ -65,10 +58,7 @@ def handle_request(request):
2. 蓝图上的配置
3. 蓝图组的配置
-一旦发现在定义路由时指定了版本信息,Sanic将会忽略蓝图和蓝图组中的版本信息。
-
-:--:1
-
+If we find a more pointed versioning specification, we will pick that over the more generic versioning specification provided under the Blueprint or Blueprint Group :--:1
```python
from sanic.blueprints import Blueprint
from sanic.response import json
@@ -106,15 +96,13 @@ async def handle_endpoint_1_bp2(request):
async def handle_endpoint_2_bp2(request):
return json({"Source": "blueprint-2/endpoint-2"})
```
-
:---
## 版本前缀(Version prefix)
-如上所述,路由的 `version` 参数 **总是** 会再在生成的 URI 路径最前面添加版本信息。为了在版本信息之前还能够增加其他路径信息,在接受 `version` 参数的函数中,您也可以传递 `version_prefix`
-参数。
+如上所述,路由的 `version` 参数 **总是** 会再在生成的 URI 路径最前面添加版本信息。 为了在版本信息之前还能够增加其他路径信息,在接受 `version` 参数的函数中,您也可以传递 `version_prefix` 参数。
-`version_prefix` 参数可以这么使用:
+一旦发现在定义路由时指定了版本信息,Sanic将会忽略蓝图和蓝图组中的版本信息。
- 使用 `app.route` 和 `bp.route` 装饰器(以及所有其他装饰器)时
- 创建 `Blueprint` 对象时
@@ -122,29 +110,18 @@ async def handle_endpoint_2_bp2(request):
- 创建 `BlueprintGroup` 对象时
- 使用 `app.blueprint` 注册蓝图
-如果在多个地方都有定义该参数了。根据上述列表顺序(从上至下),更加具体的定义将覆盖比之宽泛的定义。
+如果在多个地方都有定义该参数了。 This list provides that hierarchy.
`version_prefix` 的默认值时 `/v`。
----:1
-
-一个常见的场景就是在 `/api` 的前置后再添加 API 的版本信息。使用 `version_prefix` 可以轻松实现。
-
-:--:1
-
+---:1 An often requested feature is to be able to mount versioned routes on `/api`. 使用 `version_prefix` 可以轻松实现。 :--:1
```python
# /v1/my/path
app.route("/my/path", version=1, version_prefix="/api/v")
```
-
:---
----:1
-
-也许更好用法是将所有的 `/api` 开头路由添加到同一个 `BlueprintGroup` 中。
-
-:--:1
-
+也许更好用法是将所有的 `/api` 开头路由添加到同一个 `BlueprintGroup` 中。 :--:1
```python
# /v1/my/path
app = Sanic(__name__)
@@ -160,7 +137,6 @@ async def handler(request):
app.blueprint(api)
```
-
:---
URI 拼接的规则如下:
@@ -169,10 +145,9 @@ URI 拼接的规则如下:
version_prefix + version + url_prefix + URI definition
```
-::: tip
-
-就像 `url_prefix` 一样,您也可以在 `version_prefix` 中定义路径参数。这样做完全没问题。只要记住,每个路由对应的响应函数都会被传入该参数。
+就像 `url_prefix` 一样,您也可以在 `version_prefix` 中定义路径参数。 这样做完全没问题。 只要记住,每个路由对应的响应函数都会被传入该参数。
```python
version_prefix = "//v"
```
+:::
From 470dbb713c4f0c756fbf93b9f389be94a1c62c67 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:40 +0300
Subject: [PATCH 044/776] New translations versioning.md (Portuguese,
Brazilian)
---
src/pt/guide/advanced/versioning.md | 144 ++++++++++++++++++++++++++++
1 file changed, 144 insertions(+)
create mode 100644 src/pt/guide/advanced/versioning.md
diff --git a/src/pt/guide/advanced/versioning.md b/src/pt/guide/advanced/versioning.md
new file mode 100644
index 0000000000..8995683ed0
--- /dev/null
+++ b/src/pt/guide/advanced/versioning.md
@@ -0,0 +1,144 @@
+# Versioning
+
+It is standard practice in API building to add versions to your endpoints. This allows you to easily differentiate incompatible endpoints when you try and change your API down the road in a breaking manner.
+
+Adding a version will add a `/v{version}` url prefix to your endpoints.
+
+The version can be a `int`, `float`, or `str`. Acceptable values:
+
+- `1`, `2`, `3`
+- `1.1`, `2.25`, `3.0`
+- `"1"`, `"v1"`, `"v1.1"`
+
+## Per route
+
+---:1
+
+You can pass a version number to the routes directly. :--:1
+```python
+# /v1/text
+@app.route("/text", version=1)
+def handle_request(request):
+ return response.text("Hello world! Version 1")
+
+# /v2/text
+@app.route("/text", version=2)
+def handle_request(request):
+ return response.text("Hello world! Version 2")
+```
+:---
+
+## Per Blueprint
+
+---:1
+
+You can also pass a version number to the blueprint, which will apply to all routes in that blueprint. :--:1
+```python
+bp = Blueprint("test", url_prefix="/foo", version=1)
+
+# /v1/foo/html
+@bp.route("/html")
+def handle_request(request):
+ return response.html("
Hello world!
")
+```
+:---
+
+## Per Blueprint Group
+
+---:1 In order to simplify the management of the versioned blueprints, you can provide a version number in the blueprint group. The same will be inherited to all the blueprint grouped under it if the blueprints don't already override the same information with a value specified while creating a blueprint instance.
+
+When using blueprint groups for managing the versions, the following order is followed to apply the Version prefix to the routes being registered.
+
+1. Route Level configuration
+2. Blueprint level configuration
+3. Blueprint Group level configuration
+
+If we find a more pointed versioning specification, we will pick that over the more generic versioning specification provided under the Blueprint or Blueprint Group :--:1
+```python
+from sanic.blueprints import Blueprint
+from sanic.response import json
+
+bp1 = Blueprint(
+ name="blueprint-1",
+ url_prefix="/bp1",
+ version=1.25,
+)
+bp2 = Blueprint(
+ name="blueprint-2",
+ url_prefix="/bp2",
+)
+
+group = Blueprint.group(
+ [bp1, bp2],
+ url_prefix="/bp-group",
+ version="v2",
+)
+
+# GET /v1.25/bp-group/bp1/endpoint-1
+@bp1.get("/endpoint-1")
+async def handle_endpoint_1_bp1(request):
+ return json({"Source": "blueprint-1/endpoint-1"})
+
+# GET /v2/bp-group/bp2/endpoint-2
+@bp2.get("/endpoint-1")
+async def handle_endpoint_1_bp2(request):
+ return json({"Source": "blueprint-2/endpoint-1"})
+
+# GET /v1/bp-group/bp2/endpoint-2
+@bp2.get("/endpoint-2", version=1)
+async def handle_endpoint_2_bp2(request):
+ return json({"Source": "blueprint-2/endpoint-2"})
+```
+:---
+
+## Version prefix
+
+As seen above, the `version` that is applied to a route is **always** the first segment in the generated URI path. Therefore, to make it possible to add path segments before the version, every place that a `version` argument is passed, you can also pass `version_prefix`.
+
+The `version_prefix` argument can be defined in:
+
+- `app.route` and `bp.route` decorators (and all the convenience decorators also)
+- `Blueprint` instantiation
+- `Blueprint.group` constructor
+- `BlueprintGroup` instantiation
+- `app.blueprint` registration
+
+If there are definitions in multiple places, a more specific definition overrides a more general. This list provides that hierarchy.
+
+The default value of `version_prefix` is `/v`.
+
+---:1 An often requested feature is to be able to mount versioned routes on `/api`. This can easily be accomplished with `version_prefix`. :--:1
+```python
+# /v1/my/path
+app.route("/my/path", version=1, version_prefix="/api/v")
+```
+:---
+
+---:1 Perhaps a more compelling usage is to load all `/api` routes into a single `BlueprintGroup`. :--:1
+```python
+# /v1/my/path
+app = Sanic(__name__)
+v2ip = Blueprint("v2ip", url_prefix="/ip", version=2)
+api = Blueprint.group(v2ip, version_prefix="/api/version")
+
+# /api/version2/ip
+@v2ip.get("/")
+async def handler(request):
+ return text(request.ip)
+
+app.blueprint(api)
+```
+:---
+
+We can therefore learn that a route's URI is:
+
+```
+version_prefix + version + url_prefix + URI definition
+```
+
+::: tip Just like with `url_prefix`, it is possible to define path parameters inside a `version_prefix`. It is perfectly legitimate to do this. Just remember that every route will have that parameter injected into the handler.
+
+```python
+version_prefix="//v"
+```
+:::
From 935cc498f664c5faf49523e24545fddab3bd335f Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:42 +0300
Subject: [PATCH 045/776] New translations listeners.md (Korean)
---
src/ko/guide/basics/listeners.md | 81 ++++++++++++++++++--------------
1 file changed, 46 insertions(+), 35 deletions(-)
diff --git a/src/ko/guide/basics/listeners.md b/src/ko/guide/basics/listeners.md
index aa3e0b3b01..ef4ce101b9 100644
--- a/src/ko/guide/basics/listeners.md
+++ b/src/ko/guide/basics/listeners.md
@@ -1,6 +1,6 @@
# 리스너(Listeners)
-Sanic은 애플리케이션의 수명주기에 작업을 삽입 할 수있는 6번의 기회를 제공합니다.
+Sanic은 애플리케이션의 수명주기에 작업을 삽입 할 수있는 6번의 기회를 제공합니다. This does not include the [signals](../advanced/signals.md), which allow further injection customization.
기본 Sanic 프로세스에서 **만** 실행되는 2가지가 있습니다 (즉,`sanic server.app` 호출 당 한 번).
@@ -9,12 +9,19 @@ Sanic은 애플리케이션의 수명주기에 작업을 삽입 할 수있는 6
서버가 시작되거나 닫힐 때 시작/삭제 코드를 실행할 수 있는 4가지가 있습니다.
+- `reload_process_start`
+- `reload_process_stop`
+
+*`main_process_start` 및`main_process_stop`은 **무시됩니다***
+
+`before_server_start`는 가능한 한 빨리 실행되고`after_server_start` 이전에 실행되지만 기술적으로 서버는 이미 해당 지점에서 실행 중입니다.
+
- `before_server_start`
- `after_server_start`
- `before_server_stop`
- `after_server_stop`
-작업자 프로세스의 수명 주기는 다음과 같습니다.:
+함수를 리스너로 설정하는 프로세스는 경로(routes)를 선언하는 것과 유사합니다.
```mermaid
sequenceDiagram
@@ -61,15 +68,7 @@ end
Note over Process: exit
```
-## 리스너 연결(Attaching a listener)
-
----:1
-
-함수를 리스너로 설정하는 프로세스는 경로(routes)를 선언하는 것과 유사합니다.
-
-삽입 된 두 개의 인수는 현재 실행중인 `Sanic ()` 인스턴스와 현재 실행중인 루프입니다.
-
-:--:1
+The reloader process live outside of this worker process inside of a process that is responsible for starting and stopping the Sanic processes. Consider the following example:
```python
async def setup_db(app, loop):
@@ -78,45 +77,61 @@ async def setup_db(app, loop):
app.register_listener(setup_db, "before_server_start")
```
-:---
+If this application were run with auto-reload turned on, the `reload_start` function would be called once. This is contrasted with `main_start`, which would be run every time a file is save and the reloader restarts the applicaition process.
----:1
+## 리스너 연결(Attaching a listener)
-`Sanic` 앱 인스턴스에는 편리한 데코레이터도 있습니다.
+---:1
-:--:1
+The process to setup a function as a listener is similar to declaring a route.
+삽입 된 두 개의 인수는 현재 실행중인 `Sanic ()` 인스턴스와 현재 실행중인 루프입니다. :--:1
```python
@app.listener("before_server_start")
async def setup_db(app, loop):
app.db = await db_setup()
```
-
:---
---:1
-데코레이터를 더 줄일 수 있습니다. 자동 완성 기능이있는 IDE가있는 경우 유용합니다.
-:::
-:--:1
-
+`Sanic` 앱 인스턴스에는 편리한 데코레이터도 있습니다. :--:1
```python
@app.before_server_start
async def setup_db(app, loop):
app.db = await db_setup()
```
+:---
+
+---:1 Prior to v22.3, both the application instance and the current event loop were injected into the function. However, only the application instance is injected by default. If your function signature will accept both, then both the application and the loop will be injected as shown here. :--:1
+```python
+@app.listener("before_server_start")
+async def setup_db(app, loop):
+ app.ctx.db = await db_setup()
+```
+:---
+
+---:1
+
+데코레이터를 더 줄일 수 있습니다. 자동 완성 기능이있는 IDE가있는 경우 유용합니다.
+:--:1
+```python
+@app.before_server_start
+async def setup_db(app):
+ app.ctx.db = await db_setup()
+```
:---
## 실행 순서(Order of execution)
리스너는 시작시 선언 된 순서대로 실행되고 해체시 선언의 역순으로 실행됩니다.
-| | Phase | Order |
-| --------------------- | --------------- | -------------------------- |
-| `main_process_start` | main startup | regular :smiley: |
-| `before_server_start` | worker startup | regular :smiley: |
-| `after_server_start` | worker startup | regular :smiley: |
+| | Phase | Order |
+| --------------------- | --------------- | ---------------------------- |
+| `main_process_start` | main startup | regular :smiley: |
+| `before_server_start` | worker startup | regular :smiley: |
+| `after_server_start` | worker startup | regular :smiley: |
| `before_server_stop` | worker shutdown | reverse :upside_down_face: |
| `after_server_stop` | worker shutdown | reverse :upside_down_face: |
| `main_process_stop` | main shutdown | reverse :upside_down_face: |
@@ -158,9 +173,7 @@ async def listener_7(app, loop):
async def listener_8(app, loop):
print("listener_8")
```
-
:--:1
-
```bash{3-7,13,19-22}
[pid: 1000000] [INFO] Goin' Fast @ http://127.0.0.1:9999
[pid: 1000000] [INFO] listener_0
@@ -187,24 +200,22 @@ async def listener_8(app, loop):
[pid: 1000000] [INFO] listener_9
[pid: 1000000] [INFO] Server Stopped
```
-
위의 예에서는 세 가지 프로세스가 어떻게 실행 중인지 알아봅니다:
- `pid: 1000000` - The *main* process
- `pid: 1111111` - Worker 1
- `pid: 1222222` - Worker 2
-*이 예제에서는 한 작업자를 모두 그룹화 한 다음 다른 작업자를 모두 그룹화하기 때문에 실제로는 별도의 프로세스에서 실행되기 때문에 프로세스 간의 순서가 보장되지 않습니다. 그러나 한 명의 작업자가 **항상** 순서를 유지할 것임을 확신 할 수 있습니다.*
-:---
+*이 예제에서는 한 작업자를 모두 그룹화 한 다음 다른 작업자를 모두 그룹화하기 때문에 실제로는 별도의 프로세스에서 실행되기 때문에 프로세스 간의 순서가 보장되지 않습니다. 그러나 한 명의 작업자가 **항상** 순서를 유지할 것임을 확신 할 수 있습니다.* :---
+
-::: tip FYI
-실제로 사용하는 경우 데이터베이스 연결 함수를 정의하고 `before_server_start`의 첫 번째 리스너로 등록하면 그 이후에 등록 된 모든 리스너가 연결에 의존하여 활성 상태를 유지할 수 있습니다.
-:::
+::: tip FYI 실제로 사용하는 경우 데이터베이스 연결 함수를 정의하고 `before_server_start`의 첫 번째 리스너로 등록하면 그 이후에 등록 된 모든 리스너가 연결에 의존하여 활성 상태를 유지할 수 있습니다. :::
## ASGI 모드(ASGI Mode)
ASGI 서버에서 응용 프로그램을 실행하는 경우 다음 변경 사항을 기록하십시오:
-- `main_process_start` 및`main_process_stop`은 **무시됩니다**
-- `before_server_start`는 가능한 한 빨리 실행되고`after_server_start` 이전에 실행되지만 기술적으로 서버는 이미 해당 지점에서 실행 중입니다.
+- `reload_process_start` and `reload_process_stop` will be **ignored**
+- `main_process_start` and `main_process_stop` will be **ignored**
- `after_server_stop`은 가능한 한 늦게 실행되고 `before_server_stop` 이후에 실행되지만 기술적으로 서버는 여전히 그 시점에서 실행됩니다.
+- `after_server_stop` will run as late as it can, and will be after `before_server_stop`, but technically, the server is still running at that point
From 8eae0abe8c397e75e8e74de6d2b43114e8435b9e Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:43 +0300
Subject: [PATCH 046/776] New translations listeners.md (Chinese Simplified)
---
src/zh/guide/basics/listeners.md | 72 ++++++++++----------------------
1 file changed, 22 insertions(+), 50 deletions(-)
diff --git a/src/zh/guide/basics/listeners.md b/src/zh/guide/basics/listeners.md
index 67fd9cacce..e724952fc5 100644
--- a/src/zh/guide/basics/listeners.md
+++ b/src/zh/guide/basics/listeners.md
@@ -1,6 +1,6 @@
# 监听器(Listeners)
-在 Sanic 应用程序的生命周期中 8 个切入点,在这些关键节点上设置监听器可以让您可以完成一些注入操作。但是这里并不包括[信号](../advanced/signals.md),信号允许进一步的注入定制。
+在 Sanic 应用程序的生命周期中 8 个切入点,在这些关键节点上设置监听器可以让您可以完成一些注入操作。 但是这里并不包括[信号](../advanced/signals.md),信号允许进一步的注入定制。
有两 (2) 个切入点 _只_ 在您的主进程中触发(即,只会在 `sanic server.app` 中触发一次。)
@@ -9,21 +9,19 @@
::: new v22.3 新特性
-有两 (2) 个切入点 _只_ 在重新加载的过程中运行,前提是您开启了自动加载功能。
-
- `reload_process_start`
- `reload_process_stop`
-:::
+*Added `reload_process_start` and `reload_process_stop` in v22.3*
-有四(4)个切入点可以让您在服务器启动或者关闭前执行一些初始化或资源回收相关代码。
+:::
- `before_server_start`
- `after_server_start`
- `before_server_stop`
- `after_server_stop`
-工作流程的生命周期如下:
+有四(4)个切入点可以让您在服务器启动或者关闭前执行一些初始化或资源回收相关代码。
```mermaid
sequenceDiagram
@@ -70,7 +68,7 @@ end
Note over 进程: 退出
```
-重新加载程序的进程会存在于当前工作进程之外,位于负责启动和停止 Sanic 进程的进程之内。下面是例子:
+重新加载程序的进程会存在于当前工作进程之外,位于负责启动和停止 Sanic 进程的进程之内。 下面是例子:
```python
@app.reload_process_start
@@ -83,7 +81,7 @@ async def main_start(*_):
print(">>>>>> main_start <<<<<<")
```
-如果您的应用程序启用了自动重载功能,将会调用一次 `reload_start` 函数。与 `main_start` 不同,`main_start` 会在每次保存文件和重载器重新启动应用时调用一次。
+如果您的应用程序启用了自动重载功能,将会调用一次 `reload_start` 函数。 与 `main_start` 不同,`main_start` 会在每次保存文件和重载器重新启动应用时调用一次。
## 启用监听器(Attaching a listener)
@@ -91,77 +89,59 @@ async def main_start(*_):
将函数设置为侦听器的过程类似于声明路由。
-当前正在运行的应用程序将会注入到监听器中。
-
-:--:1
-
+The currently running `Sanic()` instance is injected into the listener. :--:1
```python
async def setup_db(app):
app.ctx.db = await db_setup()
app.register_listener(setup_db, "before_server_start")
```
-
:---
---:1
-您也可以通过装饰器的方式来将函数添加为监听器。
-
-:--:1
-
+The `Sanic` app instance also has a convenience decorator. :--:1
```python
@app.listener("before_server_start")
async def setup_db(app):
app.ctx.db = await db_setup()
```
-
:---
-::: new v22.3 新特性
-
----:1
-
-在 v22.3 版本之前,app 和 loop 都将被注入到函数中, 在 v22.3 版本之后默认只会将 app 进行注入,如果您的函数依旧想要接收两者,您可以按照下面的方式来进行操作:
-
-:--:1
-
+---:1 Prior to v22.3, both the application instance and the current event loop were injected into the function. However, only the application instance is injected by default. If your function signature will accept both, then both the application and the loop will be injected as shown here. :--:1
```python
@app.listener("before_server_start")
async def setup_db(app, loop):
app.ctx.db = await db_setup()
```
-
-:::
+:---
---:1
-您可以进一步缩短该装饰器的调用代码。如果您的 IDE 有自动补全的话会很方便。
+您可以进一步缩短该装饰器的调用代码。 如果您的 IDE 有自动补全的话会很方便。
:--:1
-
```python
@app.before_server_start
async def setup_db(app):
app.ctx.db = await db_setup()
```
-
:---
## 执行顺序(Order of execution)
监听器按启动期间声明的顺序正向执行,并在拆解期间按照注册顺序反向执行。
-| | 执行阶段 | 执行顺序 |
-| :-------------------: | :--------: | :---------------------: |
-| `main_process_start` | 主程序启动 | 正向 :smiley: |
-| `before_server_start` | 子程序启动 | 正向 :smiley: |
-| `after_server_start` | 子程序启动 | 正向 :smiley: |
+| | 执行阶段 | 执行顺序 |
+| --------------------- | ----- | ----------------------- |
+| `main_process_start` | 主程序启动 | 正向 :smiley: |
+| `before_server_start` | 子程序启动 | 正向 :smiley: |
+| `after_server_start` | 子程序启动 | 正向 :smiley: |
| `before_server_stop` | 子程序关闭 | 反向 :upside_down_face: |
-| `after_server_stop` | 子程序关闭 | 反向 :upside_down_face: |
-| `main_process_stop` | 主程序关闭 | 反向 :upside_down_face: |
+| `after_server_stop` | 子程序关闭 | 反向 :upside_down_face: |
+| `main_process_stop` | 主程序关闭 | 反向 :upside_down_face: |
-以下列代码为例,我们在启动两个子程序并执行之后看到的输出内容应该是这样的:
+:::
---:1
@@ -198,9 +178,7 @@ async def listener_7(app, loop):
async def listener_8(app, loop):
print("listener_8")
```
-
:--:1
-
```bash{3-7,13,19-22}
[pid: 1000000] [INFO] Goin' Fast @ http://127.0.0.1:9999
[pid: 1000000] [INFO] listener_0
@@ -227,26 +205,20 @@ async def listener_8(app, loop):
[pid: 1000000] [INFO] listener_9
[pid: 1000000] [INFO] Server Stopped
```
-
在上面的例子中,注意这三个进程是如何运行的:
- `pid: 1000000` - _主_ 程序
- `pid: 1111111` - 子程序 1
- `pid: 1222222` - 子程序 2
-_只是为了举例,我们将两个子程序看做两组,分别顺序打印。但在实际情况下,这些都程序都运行在不同的进程中,进程执行的顺序是无法保证的。但是,可以确定的是,在只有一个子程序的情况下,**一直** 会保持上述顺序。_
-
-:---
-
-::: tip 小提示:
+*Just because our example groups all of one worker and then all of another, in reality since these are running on separate processes, the ordering between processes is not guaranteed. 但是,可以确定的是,在只有一个子程序的情况下,**一直** 会保持上述顺序。
-在实际的使用过程中,如果您定义了一个数据库连接函数,并将其注册为 `before_server_start` 的第一个监听器,那么在此之后注册的所有监听器都可以依靠该连接保持活跃状态。
-:::
+在实际的使用过程中,如果您定义了一个数据库连接函数,并将其注册为 `before_server_start` 的第一个监听器,那么在此之后注册的所有监听器都可以依靠该连接保持活跃状态。 :::
## ASGI 模式 (ASGI Mode)
-如果您正在使用 ASGI 服务器来运行您的应用,那么需要关注一下以下的变化:
+以下列代码为例,我们在启动两个子程序并执行之后看到的输出内容应该是这样的:
- `reload_process_start` 和 `reload_process_stop` 将会被 **忽略**
- `main_process_start` 和 `main_process_stop` 将会被 **忽略**
From 38d5226b053259dc907e78e0b71108b49055d859 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:44 +0300
Subject: [PATCH 047/776] New translations exceptions.md (Portuguese,
Brazilian)
---
src/pt/guide/best-practices/exceptions.md | 487 ++++++++++++++++++++++
1 file changed, 487 insertions(+)
create mode 100644 src/pt/guide/best-practices/exceptions.md
diff --git a/src/pt/guide/best-practices/exceptions.md b/src/pt/guide/best-practices/exceptions.md
new file mode 100644
index 0000000000..806dd08e9c
--- /dev/null
+++ b/src/pt/guide/best-practices/exceptions.md
@@ -0,0 +1,487 @@
+# Exceptions
+
+## Using Sanic exceptions
+
+Sometimes you just need to tell Sanic to halt execution of a handler and send back a status code response. You can raise a `SanicException` for this and Sanic will do the rest for you.
+
+You can pass an optional `status_code` argument. By default, a SanicException will return an internal server error 500 response.
+
+```python
+from sanic.exceptions import SanicException
+
+@app.route("/youshallnotpass")
+async def no_no(request):
+ raise SanicException("Something went wrong.", status_code=501)
+```
+
+Sanic provides a number of standard exceptions. They each automatically will raise the appropriate HTTP status code in your response. [Check the API reference](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#module-sanic.exceptions) for more details.
+
+---:1
+
+The more common exceptions you _should_ implement yourself include:
+
+- `InvalidUsage` (400)
+- `Unauthorized` (401)
+- `Forbidden` (403)
+- `NotFound` (404)
+- `ServerError` (500)
+
+:--:1
+
+```python
+from sanic import exceptions
+
+@app.route("/login")
+async def login(request):
+ user = await some_login_func(request)
+ if not user:
+ raise exceptions.NotFound(
+ f"Could not find user with username={request.json.username}"
+ )
+ ...
+```
+
+:---
+
+## Exception properties
+
+All exceptions in Sanic derive from `SanicException`. That class has a few properties on it that assist the developer in consistently reporting their exceptions across an application.
+
+- `message`
+- `status_code`
+- `quiet`
+- `context`
+- `extra`
+
+All of these properties can be passed to the exception when it is created, but the first three can also be used as class variables as we will see.
+
+---:1
+### `message`
+
+The `message` property obviously controls the message that will be displayed as with any other exception in Python. What is particularly useful is that you can set the `message` property on the class definition allowing for easy standardization of language across an application :--:1
+```python
+class CustomError(SanicException):
+ message = "Something bad happened"
+
+raise CustomError
+# or
+raise CustomError("Override the default message with something else")
+```
+:---
+
+---:1
+### `status_code`
+
+This property is used to set the response code when the exception is raised. This can particularly be useful when creating custom 400 series exceptions that are usually in response to bad information coming from the client. :--:1
+```python
+class TeapotError(SanicException):
+ status_code = 418
+ message = "Sorry, I cannot brew coffee"
+
+raise TeapotError
+# or
+raise TeapotError(status_code=400)
+```
+:---
+
+---:1
+### `quiet`
+
+By default, exceptions will be output by Sanic to the `error_logger`. Sometimes this may not be desirable, especially if you are using exceptions to trigger events in exception handlers (see [the following section](./exceptions.md#handling)). You can suppress the log output using `quiet=True`. :--:1
+```python
+class SilentError(SanicException):
+ message = "Something happened, but not shown in logs"
+ quiet = True
+
+raise SilentError
+# or
+raise InvalidUsage("blah blah", quiet=True)
+```
+:---
+
+---:1
+
+Sometimes while debugging you may want to globally ignore the `quiet=True` property. You can force Sanic to log out all exceptions regardless of this property using `NOISY_EXCEPTIONS`
+
+:--:1
+```python
+app.config.NOISY_EXCEPTIONS = True
+```
+:---
+
+---:1
+
+### `extra`
+
+See [contextual exceptions](./exceptions.md#contextual-exceptions)
+
+:--:1
+```python
+raise SanicException(..., extra={"name": "Adam"})
+```
+:---
+
+---:1
+
+### `context`
+
+See [contextual exceptions](./exceptions.md#contextual-exceptions)
+
+:--:1
+```python
+raise SanicException(..., context={"foo": "bar"})
+```
+:---
+
+
+## Handling
+
+Sanic handles exceptions automatically by rendering an error page, so in many cases you don't need to handle them yourself. However, if you would like more control on what to do when an exception is raised, you can implement a handler yourself.
+
+Sanic provides a decorator for this, which applies to not only the Sanic standard exceptions, but **any** exception that your application might throw.
+
+---:1
+
+The easiest method to add a handler is to use `@app.exception()` and pass it one or more exceptions.
+
+:--:1
+
+```python
+from sanic.exceptions import NotFound
+
+@app.exception(NotFound, SomeCustomException)
+async def ignore_404s(request, exception):
+ return text("Yep, I totally found the page: {}".format(request.url))
+```
+
+:---
+
+---:1
+
+You can also create a catchall handler by catching `Exception`.
+
+:--:1
+
+```python
+@app.exception(Exception)
+async def catch_anything(request, exception):
+ ...
+```
+
+:---
+
+---:1
+
+You can also use `app.error_handler.add()` to add error handlers.
+
+:--:1
+
+```python
+async def server_error_handler(request, exception):
+ return text("Oops, server error", status=500)
+
+app.error_handler.add(Exception, server_error_handler)
+```
+
+:---
+
+## Built-in error handling
+
+Sanic ships with three formats for exceptions: HTML, JSON, and text. You can see examples of them below in the [Fallback handler](#fallback-handler) section.
+
+---:1
+
+You can control _per route_ which format to use with the `error_format` keyword argument.
+
+:--:1
+
+```python
+@app.request("/", error_format="text")
+async def handler(request):
+ ...
+```
+
+:---
+
+
+## Custom error handling
+
+In some cases, you might want to add some more error handling functionality to what is provided by default. In that case, you can subclass Sanic's default error handler as such:
+
+```python
+from sanic.handlers import ErrorHandler
+
+class CustomErrorHandler(ErrorHandler):
+ def default(self, request, exception):
+ ''' handles errors that have no error handlers assigned '''
+ # You custom error handling logic...
+ return super().default(request, exception)
+
+app.error_handler = CustomErrorHandler()
+```
+
+## Fallback handler
+
+Sanic comes with three fallback exception handlers:
+
+1. HTML (*default*)
+2. Text
+3. JSON
+
+These handlers present differing levels of detail depending upon whether your application is in [debug mode](/guide/deployment/development.md) or not.
+
+### HTML
+
+```python
+app.config.FALLBACK_ERROR_FORMAT = "html"
+```
+
+---:1
+
+```python
+app.config.DEBUG = True
+```
+
+
+
+:--:1
+
+```python
+app.config.DEBUG = False
+```
+
+
+
+:---
+
+### Text
+
+```python
+app.config.FALLBACK_ERROR_FORMAT = "text"
+```
+
+---:1
+
+```python
+app.config.DEBUG = True
+```
+
+```bash
+$ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 590
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+⚠️ 500 — Internal Server Error
+==============================
+That time when that thing broke that other thing? That happened.
+
+ServerError: That time when that thing broke that other thing? That happened. while handling path /exc
+Traceback of __BASE__ (most recent call last):
+
+ ServerError: That time when that thing broke that other thing? That happened.
+ File /path/to/sanic/app.py, line 986, in handle_request
+ response = await response
+
+ File /path/to/server.py, line 222, in exc
+ raise ServerError(
+```
+
+:--:1
+
+```python
+app.config.DEBUG = False
+```
+
+```bash
+$ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 134
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+⚠️ 500 — Internal Server Error
+==============================
+That time when that thing broke that other thing? That happened.
+```
+
+:---
+
+### JSON
+
+```python
+app.config.FALLBACK_ERROR_FORMAT = "json"
+```
+
+---:1
+
+```python
+app.config.DEBUG = True
+```
+
+```bash
+$ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 129
+connection: keep-alive
+content-type: application/json
+
+{
+ "description": "Internal Server Error",
+ "status": 500,
+ "message": "That time when that thing broke that other thing? That happened.",
+ "path": "/exc",
+ "args": {},
+ "exceptions": [
+ {
+ "type": "ServerError",
+ "exception": "That time when that thing broke that other thing? That happened.",
+ "frames": [
+ {
+ "file": "/path/to/sanic/app.py",
+ "line": 986,
+ "name": "handle_request",
+ "src": "response = await response"
+ },
+ {
+ "file": "/path/to/server.py",
+ "line": 222,
+ "name": "exc",
+ "src": "raise ServerError("
+ }
+ ]
+ }
+ ]
+}
+
+
+```
+
+:--:1
+
+```python
+app.config.DEBUG = False
+```
+
+```bash
+$ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 530
+connection: keep-alive
+content-type: application/json
+
+{
+ "description": "Internal Server Error",
+ "status": 500,
+ "message": "That time when that thing broke that other thing? That happened."
+}
+
+```
+
+:---
+
+### Auto
+
+Sanic also provides an option for guessing which fallback option to use. This is still an **experimental feature**.
+
+```python
+app.config.FALLBACK_ERROR_FORMAT = "auto"
+```
+## Contextual Exceptions
+
+Default exception messages that simplify the ability to consistently raise exceptions throughout your application.
+
+```python
+class TeapotError(SanicException):
+ status_code = 418
+ message = "Sorry, I cannot brew coffee"
+
+raise TeapotError
+```
+
+But this lacks two things:
+
+1. A dynamic and predictable message format
+2. The ability to add additional context to an error message (more on this in a moment)
+
+### Dynamic and predictable message using `extra`
+
+Sanic exceptions can be raised using `extra` keyword arguments to provide additional information to a raised exception instance.
+
+```python
+class TeapotError(SanicException):
+ status_code = 418
+
+ @property
+ def message(self):
+ return f"Sorry {self.extra['name']}, I cannot make you coffee"
+
+raise TeapotError(extra={"name": "Adam"})
+```
+
+The new feature allows the passing of `extra` meta to the exception instance, which can be particularly useful as in the above example to pass dynamic data into the message text. This `extra` info object **will be suppressed** when in `PRODUCTION` mode, but displayed in `DEVELOPMENT` mode.
+
+---:1 **PRODUCTION**
+
+ :--:1 **DEVELOPMENT**
+
+ :---
+
+### Additional `context` to an error message
+
+Sanic exceptions can also be raised with a `context` argument to pass intended information along to the user about what happened. This is particularly useful when creating microservices or an API intended to pass error messages in JSON format. In this use case, we want to have some context around the exception beyond just a parseable error message to return details to the client.
+
+```python
+raise TeapotError(context={"foo": "bar"})
+```
+
+This is information **that we want** to always be passed in the error (when it is available). Here is what it should look like:
+
+---:1 **PRODUCTION**
+
+```json
+{
+ "description": "I'm a teapot",
+ "status": 418,
+ "message": "Sorry Adam, I cannot make you coffee",
+ "context": {
+ "foo": "bar"
+ }
+}
+```
+:--:1 **DEVELOPMENT**
+
+```json
+{
+ "description": "I'm a teapot",
+ "status": 418,
+ "message": "Sorry Adam, I cannot make you coffee",
+ "context": {
+ "foo": "bar"
+ },
+ "path": "/",
+ "args": {},
+ "exceptions": [
+ {
+ "type": "TeapotError",
+ "exception": "Sorry Adam, I cannot make you coffee",
+ "frames": [
+ {
+ "file": "handle_request",
+ "line": 83,
+ "name": "handle_request",
+ "src": ""
+ },
+ {
+ "file": "/tmp/p.py",
+ "line": 17,
+ "name": "handler",
+ "src": "raise TeapotError("
+ }
+ ]
+ }
+ ]
+}
+```
+:---
From 02f46dd7b0bed7578d5a752833f5bdceb20d4395 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:45 +0300
Subject: [PATCH 048/776] New translations blueprints.md (Chinese Simplified)
---
src/zh/guide/best-practices/blueprints.md | 105 +++++-----------------
1 file changed, 22 insertions(+), 83 deletions(-)
diff --git a/src/zh/guide/best-practices/blueprints.md b/src/zh/guide/best-practices/blueprints.md
index 5d31e03de8..05fa050c09 100644
--- a/src/zh/guide/best-practices/blueprints.md
+++ b/src/zh/guide/best-practices/blueprints.md
@@ -2,18 +2,15 @@
## 概述(Overview)
-蓝图是应用中可以作为子路由的对象。蓝图定义了同样的添加路由的方式,您可以将一系列路由注册到蓝图上而不是直接注册到应用上,然后再以可插拔的方式将蓝图注册到到应用程序。
+蓝图是应用中可以作为子路由的对象。 蓝图定义了同样的添加路由的方式,您可以将一系列路由注册到蓝图上而不是直接注册到应用上,然后再以可插拔的方式将蓝图注册到到应用程序。
-蓝图对于大型应用特别有用。在大型应用中,您可以将应用代码根据不同的业务分解成多个蓝图。
+Blueprints are especially useful for larger applications, where your application logic can be broken down into several groups or areas of responsibility.
## 创建和注册蓝图(Creating and registering)
---:1
-首先,您必须先创建一个蓝图。蓝图对象有着和 `Sanic` 对象十分相似的方法,它也提供了相同的装饰器来注册路由。
-
-:--:1
-
+首先,您必须先创建一个蓝图。 It has a very similar API as the `Sanic()` app instance with many of the same decorators. :--:1
```python
# ./my_blueprint.py
from sanic.response import json
@@ -26,15 +23,12 @@ bp = Blueprint("my_blueprint")
async def bp_root(request):
return json({"my": "blueprint"})
```
-
:---
----:1
-
-接下来,您可以将蓝图注册到 Sanic 应用上。
-:--:1
+---:1
+Next, you register it with the app instance. :--:1
```python
from sanic import Sanic
from my_blueprint import bp
@@ -42,17 +36,13 @@ from my_blueprint import bp
app = Sanic(__name__)
app.blueprint(bp)
```
-
:---
蓝图也提供了 `websocket()` 装饰器和 `add_websocket_route` 方法来实现 websocket 通讯。
---:1
-从 v21.12 开始,您可以在向蓝图中添加响应函数之前或之后注册蓝图。以前,只有在注册时附加到蓝图的响应函数才会被加载到应用程序实例中。
-
-:--:1
-
+从 v21.12 开始,您可以在向蓝图中添加响应函数之前或之后注册蓝图。 Previously, only objects attached to the Blueprint at the time of registration would be loaded into application instance. :--:1
```python
app.blueprint(bp)
@@ -60,14 +50,12 @@ app.blueprint(bp)
async def bp_root(request):
...
```
-
:---
-
## 复制蓝图(Copying)
---:1
-使用 `copy()` 方法可以将蓝图以及附加到其上的所有内容复制到新实例中。唯一需要的参数是给它传递一个新的 `name`。当然,您也可以使用它来覆盖旧蓝图中的任何值。
+使用 `copy()` 方法可以将蓝图以及附加到其上的所有内容复制到新实例中。 唯一需要的参数是给它传递一个新的 `name`。 当然,您也可以使用它来覆盖旧蓝图中的任何值。
:--:1
@@ -95,7 +83,7 @@ Available routes:
## 蓝图组(Blueprint groups)
-蓝图也可以以列表或者元组的形式进行注册,在这种情况下,注册时会递归地遍历当前序列,在序列中或者在子序列中的所有蓝图对象都会被注册到应用上。`Blueprint.group` 方法允许模拟一个后端目录结构来简化上述问题。请看这个例子:
+蓝图也可以以列表或者元组的形式进行注册,在这种情况下,注册时会递归地遍历当前序列,在序列中或者在子序列中的所有蓝图对象都会被注册到应用上。 `Blueprint.group` 方法允许模拟一个后端目录结构来简化上述问题。 请看这个例子:
```text
api/
@@ -113,14 +101,12 @@ app.py
#### 第一个蓝图(First blueprint)
:--:1
-
```python
# api/content/authors.py
from sanic import Blueprint
authors = Blueprint("content_authors", url_prefix="/authors")
```
-
:---
---:1
@@ -128,14 +114,12 @@ authors = Blueprint("content_authors", url_prefix="/authors")
#### 第二个蓝图(Second blueprint)
:--:1
-
```python
# api/content/static.py
from sanic import Blueprint
static = Blueprint("content_static", url_prefix="/static")
```
-
:---
---:1
@@ -143,7 +127,6 @@ static = Blueprint("content_static", url_prefix="/static")
#### 蓝图组(Blueprint group)
:--:1
-
```python
# api/content/__init__.py
from sanic import Blueprint
@@ -152,7 +135,6 @@ from .authors import authors
content = Blueprint.group(static, authors, url_prefix="/content")
```
-
:---
---:1
@@ -160,14 +142,12 @@ content = Blueprint.group(static, authors, url_prefix="/content")
#### 第三个蓝图(Third blueprint)
:--:1
-
```python
# api/info.py
from sanic import Blueprint
info = Blueprint("info", url_prefix="/info")
```
-
:---
---:1
@@ -175,7 +155,6 @@ info = Blueprint("info", url_prefix="/info")
#### 另一个蓝图组(Another blueprint group)
:--:1
-
```python
# api/__init__.py
from sanic import Blueprint
@@ -184,7 +163,6 @@ from .info import info
api = Blueprint.group(content, info, url_prefix="/api")
```
-
:---
---:1
@@ -194,7 +172,6 @@ api = Blueprint.group(content, info, url_prefix="/api")
所有的蓝图都会被注册。
:--:1
-
```python
# app.py
from sanic import Sanic
@@ -203,17 +180,13 @@ from .api import api
app = Sanic(__name__)
app.blueprint(api)
```
-
:---
## 中间件(Middleware)
---:1
-蓝图也可以有自己的中间件,这些中间件只会影响到注册到该蓝图上的路由。
-
-:--:1
-
+Blueprints can also have middleware that is specifically registered for its endpoints only. :--:1
```python
@bp.middleware
async def print_on_request(request):
@@ -229,15 +202,11 @@ async def halt_request(request):
async def halt_response(request, response):
return text("I halted the response")
```
-
:---
---:1
-同样的,使用蓝图组能够将中间件应用给同组中的所用蓝图。
-
-:--:1
-
+同样的,使用蓝图组能够将中间件应用给同组中的所用蓝图。 :--:1
```python
bp1 = Blueprint("bp1", url_prefix="/bp1")
bp2 = Blueprint("bp2", url_prefix="/bp2")
@@ -269,23 +238,18 @@ async def group_middleware(request):
# Register Blueprint group under the app
app.blueprint(group)
```
-
:---
## 异常(Exceptions)
---:1
-正如 [异常处理](./exceptions.md) 一章所述,您可以定义蓝图特定的异常响应函数。
-
-:--:1
-
+正如 [异常处理](./exceptions.md) 一章所述,您可以定义蓝图特定的异常响应函数。 :--:1
```python
@bp.exception(NotFound)
def ignore_404s(request, exception):
return text("Yep, I totally found the page: {}".format(request.url))
```
-
:---
## 静态文件(Static files)
@@ -293,38 +257,27 @@ def ignore_404s(request, exception):
---:1
蓝图也可以单独指定需要代理的静态文件。
-
-:--:1
-
```python
bp = Blueprint("bp", url_prefix="/bp")
bp.static("/web/path", "/folder/to/serve")
bp.static("/web/path", "/folder/to/server", name="uploads")
```
-
:---
---:1
-然后文件可以使用 `url_for()` 函数来获取。详见 [路由](/zh/guide/basics/routing.md) 章节。
-
-:--:1
-
+然后文件可以使用 `url_for()` 函数来获取。 详见 [路由](/zh/guide/basics/routing.md) 章节。 :--:1
```python
>>> print(app.url_for("static", name="bp.uploads", filename="file.txt"))
'/bp/web/path/file.txt'
```
-
:---
## 监听器(Listeners)
---:1
-蓝图也可以实现 [监听器](/zh/guide/basics/listeners.md)。
-
-:--:1
-
+蓝图也可以实现 [监听器](/zh/guide/basics/listeners.md)。 :--:1
```python
@bp.listener("before_server_start")
async def before_server_start(app, loop):
@@ -334,8 +287,11 @@ async def before_server_start(app, loop):
@bp.listener("after_server_stop")
async def after_server_stop(app, loop):
...
-```
+@bp.listener("after_server_stop")
+async def after_server_stop(app, loop):
+ ...
+```
:---
## 版本管理(Versioning)
@@ -345,22 +301,15 @@ async def after_server_stop(app, loop):
---:1
`version` 参数会被作为前缀添加到路由上,如 `/v1`,`/v2` 等等。
-
-:--:1
-
```python
auth1 = Blueprint("auth", url_prefix="/auth", version=1)
auth2 = Blueprint("auth", url_prefix="/auth", version=2)
```
-
:---
---:1
-当我们将蓝图注册到APP上时,`/v1/auth` 和 `/v2/auth` 路由将指向两个不同的蓝图,这就允许您为每个 API 版本创建子路由。
-
-:--:1
-
+当我们将蓝图注册到APP上时,`/v1/auth` 和 `/v2/auth` 路由将指向两个不同的蓝图,这就允许您为每个 API 版本创建子路由。 :--:1
```python
from auth_blueprints import auth1, auth2
@@ -368,15 +317,11 @@ app = Sanic(__name__)
app.blueprint(auth1)
app.blueprint(auth2)
```
-
:---
---:1
-您也可以将多个蓝图放在一个蓝图组下然后同时为他们添加上版本信息。
-
-:--:1
-
+It is also possible to group the blueprints under a `BlueprintGroup` entity and version multiple of them together at the same time. :--:1
```python
auth = Blueprint("auth", url_prefix="/auth")
metrics = Blueprint("metrics", url_prefix="/metrics")
@@ -386,19 +331,13 @@ group = Blueprint.group(auth, metrics, version="v1")
# This will provide APIS prefixed with the following URL path
# /v1/auth/ and /v1/metrics
```
-
:---
## 组合(Composable)
-一个蓝图对象可以被多个蓝图组注册,且蓝图组之间可以进行嵌套注册。这样就消除了蓝图之间组合的限制。
-
----:1
-
-请看下面的例子,看看两个响应函数是如何被注册到不同的五个路由上的。
-
-:--:1
+A `Blueprint` may be registered to multiple groups, and each of `BlueprintGroup` itself could be registered and nested further. This creates a limitless possibility `Blueprint` composition.
+---:1 Take a look at this example and see how the two handlers are actually mounted as five (5) distinct routes. :--:1
```python
app = Sanic(__name__)
blueprint_1 = Blueprint("blueprint_1", url_prefix="/bp1")
@@ -436,9 +375,9 @@ app.blueprint(blueprint_1)
# /bp1
```
-
:---
+
## URL 生成(Generating a URL)
当使用 `url_for()` 来生成 URL 时,端点的名称将以以下格式来组织:
From 7231d5e7576e0f4ed5826e713ea28816e3ba14fc Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:46 +0300
Subject: [PATCH 049/776] New translations blueprints.md (Portuguese,
Brazilian)
---
src/pt/guide/best-practices/blueprints.md | 373 ++++++++++++++++++++++
1 file changed, 373 insertions(+)
create mode 100644 src/pt/guide/best-practices/blueprints.md
diff --git a/src/pt/guide/best-practices/blueprints.md b/src/pt/guide/best-practices/blueprints.md
new file mode 100644
index 0000000000..1070c85673
--- /dev/null
+++ b/src/pt/guide/best-practices/blueprints.md
@@ -0,0 +1,373 @@
+# Blueprints
+
+## Overview
+
+Blueprints are objects that can be used for sub-routing within an application. Instead of adding routes to the application instance, blueprints define similar methods for adding routes, which are then registered with the application in a flexible and pluggable manner.
+
+Blueprints are especially useful for larger applications, where your application logic can be broken down into several groups or areas of responsibility.
+
+## Creating and registering
+
+---:1
+
+First, you must create a blueprint. It has a very similar API as the `Sanic()` app instance with many of the same decorators. :--:1
+```python
+# ./my_blueprint.py
+from sanic.response import json
+from sanic import Blueprint
+
+bp = Blueprint("my_blueprint")
+
+@bp.route("/")
+async def bp_root(request):
+ return json({"my": "blueprint"})
+```
+:---
+
+
+---:1
+
+Next, you register it with the app instance. :--:1
+```python
+from sanic import Sanic
+from my_blueprint import bp
+
+app = Sanic(__name__)
+app.blueprint(bp)
+```
+:---
+
+Blueprints also have the same `websocket()` decorator and `add_websocket_route` method for implementing websockets.
+
+---:1
+
+Beginning in v21.12, a Blueprint may be registered before or after adding objects to it. Previously, only objects attached to the Blueprint at the time of registration would be loaded into application instance. :--:1
+```python
+app.blueprint(bp)
+
+@bp.route("/")
+async def bp_root(request):
+ ...
+```
+:---
+## Copying
+
+---:1
+
+Blueprints along with everything that is attached to them can be copied to new instances using the `copy()` method. The only required argument is to pass it a new `name`. However, you could also use this to override any of the values from the old blueprint.
+
+:--:1
+
+```python
+v1 = Blueprint("Version1", version=1)
+
+@v1.route("/something")
+def something(request):
+ pass
+
+v2 = v1.copy("Version2", version=2)
+
+app.blueprint(v1)
+app.blueprint(v2)
+```
+
+```
+Available routes:
+/v1/something
+/v2/something
+
+```
+
+:---
+
+## Blueprint groups
+
+Blueprints may also be registered as part of a list or tuple, where the registrar will recursively cycle through any sub-sequences of blueprints and register them accordingly. The Blueprint.group method is provided to simplify this process, allowing a ‘mock’ backend directory structure mimicking what’s seen from the front end. Consider this (quite contrived) example:
+
+```text
+api/
+├──content/
+│ ├──authors.py
+│ ├──static.py
+│ └──__init__.py
+├──info.py
+└──__init__.py
+app.py
+```
+
+---:1
+
+#### First blueprint
+
+:--:1
+```python
+# api/content/authors.py
+from sanic import Blueprint
+
+authors = Blueprint("content_authors", url_prefix="/authors")
+```
+:---
+
+---:1
+
+#### Second blueprint
+
+:--:1
+```python
+# api/content/static.py
+from sanic import Blueprint
+
+static = Blueprint("content_static", url_prefix="/static")
+```
+:---
+
+---:1
+
+#### Blueprint group
+
+:--:1
+```python
+# api/content/__init__.py
+from sanic import Blueprint
+from .static import static
+from .authors import authors
+
+content = Blueprint.group(static, authors, url_prefix="/content")
+```
+:---
+
+---:1
+
+#### Third blueprint
+
+:--:1
+```python
+# api/info.py
+from sanic import Blueprint
+
+info = Blueprint("info", url_prefix="/info")
+```
+:---
+
+---:1
+
+#### Another blueprint group
+
+:--:1
+```python
+# api/__init__.py
+from sanic import Blueprint
+from .content import content
+from .info import info
+
+api = Blueprint.group(content, info, url_prefix="/api")
+```
+:---
+
+---:1
+
+#### Main server
+
+All blueprints are now registered
+
+:--:1
+```python
+# app.py
+from sanic import Sanic
+from .api import api
+
+app = Sanic(__name__)
+app.blueprint(api)
+```
+:---
+
+## Middleware
+
+---:1
+
+Blueprints can also have middleware that is specifically registered for its endpoints only. :--:1
+```python
+@bp.middleware
+async def print_on_request(request):
+ print("I am a spy")
+
+@bp.middleware("request")
+async def halt_request(request):
+ return text("I halted the request")
+
+@bp.middleware("response")
+async def halt_response(request, response):
+ return text("I halted the response")
+```
+:---
+
+---:1
+
+Similarly, using blueprint groups, it is possible to apply middleware to an entire group of nested blueprints. :--:1
+```python
+bp1 = Blueprint("bp1", url_prefix="/bp1")
+bp2 = Blueprint("bp2", url_prefix="/bp2")
+
+@bp1.middleware("request")
+async def bp1_only_middleware(request):
+ print("applied on Blueprint : bp1 Only")
+
+@bp1.route("/")
+async def bp1_route(request):
+ return text("bp1")
+
+@bp2.route("/")
+async def bp2_route(request, param):
+ return text(param)
+
+group = Blueprint.group(bp1, bp2)
+
+@group.middleware("request")
+async def group_middleware(request):
+ print("common middleware applied for both bp1 and bp2")
+
+# Register Blueprint group under the app
+app.blueprint(group)
+```
+:---
+
+## Exceptions
+
+---:1
+
+Just like other [exception handling](./exceptions.md), you can define blueprint specific handlers. :--:1
+```python
+@bp.exception(NotFound)
+def ignore_404s(request, exception):
+ return text("Yep, I totally found the page: {}".format(request.url))
+```
+:---
+
+## Static files
+
+---:1
+
+Blueprints can also have their own static handlers :--:1
+```python
+bp = Blueprint("bp", url_prefix="/bp")
+bp.static("/web/path", "/folder/to/serve")
+bp.static("/web/path", "/folder/to/server", name="uploads")
+```
+:---
+
+---:1
+
+Which can then be retrieved using `url_for()`. See [routing](/guide/basics/routing.md) for more information. :--:1
+```python
+>>> print(app.url_for("static", name="bp.uploads", filename="file.txt"))
+'/bp/web/path/file.txt'
+```
+:---
+
+## Listeners
+
+---:1
+
+Blueprints can also implement [listeners](/guide/basics/listeners.md). :--:1
+```python
+@bp.listener("before_server_start")
+async def before_server_start(app, loop):
+ ...
+
+@bp.listener("after_server_stop")
+async def after_server_stop(app, loop):
+ ...
+```
+:---
+
+## Versioning
+
+As discussed in the [versioning section](/guide/advanced/versioning.md), blueprints can be used to implement different versions of a web API.
+
+---:1
+
+The `version` will be prepended to the routes as `/v1` or `/v2`, etc. :--:1
+```python
+auth1 = Blueprint("auth", url_prefix="/auth", version=1)
+auth2 = Blueprint("auth", url_prefix="/auth", version=2)
+```
+:---
+
+---:1
+
+When we register our blueprints on the app, the routes `/v1/auth` and `/v2/auth` will now point to the individual blueprints, which allows the creation of sub-sites for each API version. :--:1
+```python
+from auth_blueprints import auth1, auth2
+
+app = Sanic(__name__)
+app.blueprint(auth1)
+app.blueprint(auth2)
+```
+:---
+
+---:1
+
+It is also possible to group the blueprints under a `BlueprintGroup` entity and version multiple of them together at the same time. :--:1
+```python
+auth = Blueprint("auth", url_prefix="/auth")
+metrics = Blueprint("metrics", url_prefix="/metrics")
+
+group = Blueprint.group(auth, metrics, version="v1")
+
+# This will provide APIs prefixed with the following URL path
+# /v1/auth/ and /v1/metrics
+```
+:---
+
+## Composable
+
+A `Blueprint` may be registered to multiple groups, and each of `BlueprintGroup` itself could be registered and nested further. This creates a limitless possibility `Blueprint` composition.
+
+---:1 Take a look at this example and see how the two handlers are actually mounted as five (5) distinct routes. :--:1
+```python
+app = Sanic(__name__)
+blueprint_1 = Blueprint("blueprint_1", url_prefix="/bp1")
+blueprint_2 = Blueprint("blueprint_2", url_prefix="/bp2")
+group = Blueprint.group(
+ blueprint_1,
+ blueprint_2,
+ version=1,
+ version_prefix="/api/v",
+ url_prefix="/grouped",
+ strict_slashes=True,
+)
+primary = Blueprint.group(group, url_prefix="/primary")
+
+
+@blueprint_1.route("/")
+def blueprint_1_default_route(request):
+ return text("BP1_OK")
+
+
+@blueprint_2.route("/")
+def blueprint_2_default_route(request):
+ return text("BP2_OK")
+
+
+app.blueprint(group)
+app.blueprint(primary)
+app.blueprint(blueprint_1)
+
+# The mounted paths:
+# /api/v1/grouped/bp1/
+# /api/v1/grouped/bp2/
+# /api/v1/primary/grouped/bp1
+# /api/v1/primary/grouped/bp2
+# /bp1
+
+```
+:---
+
+
+## Generating a URL
+
+When generating a url with `url_for()`, the endpoint name will be in the form:
+
+```text
+{blueprint_name}.{handler_name}
+```
From b53b70ddc8e3d8cd5bfe40a30748c9d8740630a4 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:47 +0300
Subject: [PATCH 050/776] New translations decorators.md (Japanese)
---
src/ja/guide/best-practices/decorators.md | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/ja/guide/best-practices/decorators.md b/src/ja/guide/best-practices/decorators.md
index 2f5016fe28..5bd9b4bf10 100644
--- a/src/ja/guide/best-practices/decorators.md
+++ b/src/ja/guide/best-practices/decorators.md
@@ -4,8 +4,7 @@
---:1
-そのため、複数のデコレータを持つSanicビューハンドラが表示されることがよくあります。
-:--:1
+そのため、複数のデコレータを持つSanicビューハンドラが表示されることがよくあります。 :--:1 :--:1
```python
@app.get("/orders")
@authorized("view_order")
@@ -21,7 +20,7 @@ async def get_order_details(request, params, user):
ここに、デコレーターの作成に役立つ初期テンプレートがあります。
-この例では、ユーザーが特定のエンドポイントへのアクセスを許可されていることを確認するとします。ハンドラー関数をラップし、クライアントがリソースへのアクセスを許可されているかどうか要求を検査し、適切な応答を送信するデコレータを作成できます。
+この例では、ユーザーが特定のエンドポイントへのアクセスを許可されていることを確認するとします。 ハンドラー関数をラップし、クライアントがリソースへのアクセスを許可されているかどうか要求を検査し、適切な応答を送信するデコレータを作成できます。
```python
from functools import wraps
from sanic.response import json
@@ -54,7 +53,7 @@ async def test(request):
## テンプレート
-デコレーターは、Sanicでアプリケーションを構築するための**基本**です。これにより、コードの移植性と保守性が向上します。
+デコレーターは、Sanicでアプリケーションを構築するための**基本**です。 これにより、コードの移植性と保守性が向上します。
Pythonの禅を言い換えてこう言います: 「 (装飾家は) 素晴らしいアイデアの一つです--もっといろいろやってみましょう!"
@@ -62,7 +61,7 @@ Pythonの禅を言い換えてこう言います: 「 (装飾家は) 素晴ら
---:1
-これらのインポート文を忘れずに追加してください。必要ではありませんが、`@wraps`を使用すると、ファンクションのメタデータの一部をそのまま保持できます。[docs](https://docs.python.org/3/library/functools.html#functools.wraps) を参照してください。また、ここでは 「isawaitable」 パターンを使用して、通常の関数または非同期関数によるルートハンドラの実行を許可します。
+これらのインポート文を忘れずに追加してください。 必要ではありませんが、`@wraps`を使用すると、ファンクションのメタデータの一部をそのまま保持できます。 [docs](https://docs.python.org/3/library/functools.html#functools.wraps) を参照してください。 また、ここでは 「isawaitable」 パターンを使用して、通常の関数または非同期関数によるルートハンドラの実行を許可します。
:--:1
@@ -77,7 +76,7 @@ from functools import wraps
---:1
-多くの場合、*常に*引数を必要とするデコレータが必要になります。したがって、この関数が実装されると、常に関数を呼び出します。
+多くの場合、*常に*引数を必要とするデコレータが必要になります。 したがって、この関数が実装されると、常に関数を呼び出します。
```python
@app.get("/")
@@ -111,7 +110,7 @@ def foobar(arg1, arg2):
---:1
-引数を取らないデコレータが必要な場合もあります。このような場合、それを呼び出す必要がないのは便利です。
+引数を取らないデコレータが必要な場合もあります。 このような場合、それを呼び出す必要がないのは便利です。
```python
@app.get("/")
@@ -145,7 +144,7 @@ def foobar(func):
---:1
-呼び出し可能かどうかを指定できるデコレータが必要な場合は、このパターンに従います。キーワードのみの引数を使用する必要はありませんが、実装が簡単になる場合があります。
+呼び出し可能かどうかを指定できるデコレータが必要な場合は、このパターンに従います。 キーワードのみの引数を使用する必要はありませんが、実装が簡単になる場合があります。
```python
@app.get("/")
From 25cf0dd335a49a46d75c458ba896b7efa308c695 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:48 +0300
Subject: [PATCH 051/776] New translations decorators.md (Korean)
---
src/ko/guide/best-practices/decorators.md | 182 ++++++++++++++++++++++
1 file changed, 182 insertions(+)
create mode 100644 src/ko/guide/best-practices/decorators.md
diff --git a/src/ko/guide/best-practices/decorators.md b/src/ko/guide/best-practices/decorators.md
new file mode 100644
index 0000000000..42a90495bb
--- /dev/null
+++ b/src/ko/guide/best-practices/decorators.md
@@ -0,0 +1,182 @@
+# Decorators
+
+One of the best ways to create a consistent and DRY web API is to make use of decorators to remove functionality from the handlers, and make it repeatable across your views.
+
+---:1
+
+Therefore, it is very common to see a Sanic view handler with several decorators on it. :--:1
+```python
+@app.get("/orders")
+@authorized("view_order")
+@validate_list_params()
+@inject_user()
+async def get_order_details(request, params, user):
+ ...
+```
+:---
+
+
+## Example
+
+Here is a starter template to help you create decorators.
+
+In this example, let’s say you want to check that a user is authorized to access a particular endpoint. You can create a decorator that wraps a handler function, checks a request if the client is authorized to access a resource, and sends the appropriate response.
+```python
+from functools import wraps
+from sanic.response import json
+
+def authorized():
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+ # run some method that checks the request
+ # for the client's authorization status
+ is_authorized = await check_request_for_authorization_status(request)
+
+ if is_authorized:
+ # the user is authorized.
+ # run the handler method and return the response
+ response = await f(request, *args, **kwargs)
+ return response
+ else:
+ # the user is not authorized.
+ return json({"status": "not_authorized"}, 403)
+ return decorated_function
+ return decorator
+
+
+@app.route("/")
+@authorized()
+async def test(request):
+ return json({"status": "authorized"})
+```
+
+## Templates
+
+Decorators are **fundamental** to building applications with Sanic. They increase the portability and maintainablity of your code.
+
+In paraphrasing the Zen of Python: "[decorators] are one honking great idea -- let's do more of those!"
+
+To make it easier to implement them, here are three examples of copy/pastable code to get you started.
+
+---:1
+
+Don't forget to add these import statements. Although it is *not* necessary, using `@wraps` helps keep some of the metadata of your function in tact. [See docs](https://docs.python.org/3/library/functools.html#functools.wraps). Also, we use the `isawaitable` pattern here to allow the route handlers to by regular or asynchronous functions.
+
+:--:1
+
+```python
+from inspect import isawaitable
+from functools import wraps
+```
+
+:---
+
+### With args
+
+---:1
+
+Often, you will want a decorator that will *always* need arguments. Therefore, when it is implemented you will always be calling it.
+
+```python
+@app.get("/")
+@foobar(1, 2)
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
+
+```python
+def foobar(arg1, arg2):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+
+ response = f(request, *args, **kwargs)
+ if isawaitable(response):
+ response = await response
+
+ return response
+
+ return decorated_function
+
+ return decorator
+```
+
+:---
+
+### Without args
+
+---:1
+
+Sometimes you want a decorator that will not take arguments. When this is the case, it is a nice convenience not to have to call it
+
+```python
+@app.get("/")
+@foobar
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
+
+```python
+def foobar(func):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+
+ response = f(request, *args, **kwargs)
+ if isawaitable(response):
+ response = await response
+
+ return response
+
+ return decorated_function
+
+ return decorator(func)
+```
+
+:---
+
+### With or Without args
+
+---:1
+
+If you want a decorator with the ability to be called or not, you can follow this pattern. Using keyword only arguments is not necessary, but might make implementation simpler.
+
+```python
+@app.get("/")
+@foobar(arg1=1, arg2=2)
+async def handler(request: Request):
+ return text("hi")
+```
+
+```python
+@app.get("/")
+@foobar
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
+
+```python
+def foobar(maybe_func=None, *, arg1=None, arg2=None):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+
+ response = f(request, *args, **kwargs)
+ if isawaitable(response):
+ response = await response
+
+ return response
+
+ return decorated_function
+
+ return decorator(maybe_func) if maybe_func else decorator
+```
+
+:---
From fa2417e611473d8e94fb73f1eb256256a4067d28 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:49 +0300
Subject: [PATCH 052/776] New translations decorators.md (Chinese Simplified)
---
src/zh/guide/best-practices/decorators.md | 152 +++++++++++++++++++++-
1 file changed, 145 insertions(+), 7 deletions(-)
diff --git a/src/zh/guide/best-practices/decorators.md b/src/zh/guide/best-practices/decorators.md
index 6d7ad6bf41..492371f149 100644
--- a/src/zh/guide/best-practices/decorators.md
+++ b/src/zh/guide/best-practices/decorators.md
@@ -4,10 +4,7 @@
---:1
-因此,在 Sanic 的视图函数上使用多个装饰器是十分常见的。
-
-:--:1
-
+因此,在 Sanic 的视图函数上使用多个装饰器是十分常见的。 :--:1
```python
@app.get("/orders")
@authorized("view_order")
@@ -16,15 +13,79 @@
async def get_order_details(request, params, user):
...
```
-
:---
-### 例子(Example)
+## 例子(Example)
这里有一个入门模板来帮助您创建装饰器。
-在下面的例子中,假设您想去检查某个用户是否对特定的路由有访问的权限。您可以创建一个装饰器来装饰一个响应函数,检查发送请求的客户端是否有权限来访问该资源,并返回正确的响应。
+在下面的例子中,假设您想去检查某个用户是否对特定的路由有访问的权限。 您可以创建一个装饰器来装饰一个响应函数,检查发送请求的客户端是否有权限来访问该资源,并返回正确的响应。
+```python
+from functools import wraps
+from sanic.response import json
+
+def authorized():
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+ # run some method that checks the request
+ # for the client's authorization status
+ is_authorized = await check_request_for_authorization_status(request)
+
+ if is_authorized:
+ # the user is authorized.
+ # run the handler method and return the response
+ response = await f(request, *args, **kwargs)
+ return response
+ else:
+ # the user is not authorized.
+ return json({"status": "not_authorized"}, 403)
+ return decorated_function
+ return decorator
+
+
+@app.route("/")
+@authorized()
+async def test(request):
+ return json({"status": "authorized"})
+```
+
+## Templates
+
+Decorators are **fundamental** to building applications with Sanic. They increase the portability and maintainablity of your code.
+
+In paraphrasing the Zen of Python: "[decorators] are one honking great idea -- let's do more of those!"
+
+To make it easier to implement them, here are three examples of copy/pastable code to get you started.
+
+---:1
+
+Don't forget to add these import statements. Although it is *not* necessary, using `@wraps` helps keep some of the metadata of your function in tact. [See docs](https://docs.python.org/3/library/functools.html#functools.wraps). Also, we use the `isawaitable` pattern here to allow the route handlers to by regular or asynchronous functions.
+
+:--:1
+
+```python
+from inspect import isawaitable
+from functools import wraps
+```
+
+:---
+
+### With args
+
+---:1
+
+Often, you will want a decorator that will *always* need arguments. Therefore, when it is implemented you will always be calling it.
+
+```python
+@app.get("/")
+@foobar(1, 2)
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
```python
from functools import wraps
@@ -55,3 +116,80 @@ def authorized():
async def test(request):
return json({"status": "authorized"})
```
+
+:---
+
+### Without args
+
+---:1
+
+Sometimes you want a decorator that will not take arguments. When this is the case, it is a nice convenience not to have to call it
+
+```python
+@app.get("/")
+@foobar
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
+
+```python
+def foobar(func):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+
+ response = f(request, *args, **kwargs)
+ if isawaitable(response):
+ response = await response
+
+ return response
+
+ return decorated_function
+
+ return decorator(func)
+```
+
+:---
+
+### With or Without args
+
+---:1
+
+If you want a decorator with the ability to be called or not, you can follow this pattern. Using keyword only arguments is not necessary, but might make implementation simpler.
+
+```python
+@app.get("/")
+@foobar(arg1=1, arg2=2)
+async def handler(request: Request):
+ return text("hi")
+```
+
+```python
+@app.get("/")
+@foobar
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
+
+```python
+def foobar(maybe_func=None, *, arg1=None, arg2=None):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+
+ response = f(request, *args, **kwargs)
+ if isawaitable(response):
+ response = await response
+
+ return response
+
+ return decorated_function
+
+ return decorator(maybe_func) if maybe_func else decorator
+```
+
+:---
From 13438465761c03c3e9d01cb35c5ce3046eefe082 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:50 +0300
Subject: [PATCH 053/776] New translations decorators.md (Portuguese,
Brazilian)
---
src/pt/guide/best-practices/decorators.md | 182 ++++++++++++++++++++++
1 file changed, 182 insertions(+)
create mode 100644 src/pt/guide/best-practices/decorators.md
diff --git a/src/pt/guide/best-practices/decorators.md b/src/pt/guide/best-practices/decorators.md
new file mode 100644
index 0000000000..42a90495bb
--- /dev/null
+++ b/src/pt/guide/best-practices/decorators.md
@@ -0,0 +1,182 @@
+# Decorators
+
+One of the best ways to create a consistent and DRY web API is to make use of decorators to remove functionality from the handlers, and make it repeatable across your views.
+
+---:1
+
+Therefore, it is very common to see a Sanic view handler with several decorators on it. :--:1
+```python
+@app.get("/orders")
+@authorized("view_order")
+@validate_list_params()
+@inject_user()
+async def get_order_details(request, params, user):
+ ...
+```
+:---
+
+
+## Example
+
+Here is a starter template to help you create decorators.
+
+In this example, let’s say you want to check that a user is authorized to access a particular endpoint. You can create a decorator that wraps a handler function, checks a request if the client is authorized to access a resource, and sends the appropriate response.
+```python
+from functools import wraps
+from sanic.response import json
+
+def authorized():
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+ # run some method that checks the request
+ # for the client's authorization status
+ is_authorized = await check_request_for_authorization_status(request)
+
+ if is_authorized:
+ # the user is authorized.
+ # run the handler method and return the response
+ response = await f(request, *args, **kwargs)
+ return response
+ else:
+ # the user is not authorized.
+ return json({"status": "not_authorized"}, 403)
+ return decorated_function
+ return decorator
+
+
+@app.route("/")
+@authorized()
+async def test(request):
+ return json({"status": "authorized"})
+```
+
+## Templates
+
+Decorators are **fundamental** to building applications with Sanic. They increase the portability and maintainablity of your code.
+
+In paraphrasing the Zen of Python: "[decorators] are one honking great idea -- let's do more of those!"
+
+To make it easier to implement them, here are three examples of copy/pastable code to get you started.
+
+---:1
+
+Don't forget to add these import statements. Although it is *not* necessary, using `@wraps` helps keep some of the metadata of your function in tact. [See docs](https://docs.python.org/3/library/functools.html#functools.wraps). Also, we use the `isawaitable` pattern here to allow the route handlers to by regular or asynchronous functions.
+
+:--:1
+
+```python
+from inspect import isawaitable
+from functools import wraps
+```
+
+:---
+
+### With args
+
+---:1
+
+Often, you will want a decorator that will *always* need arguments. Therefore, when it is implemented you will always be calling it.
+
+```python
+@app.get("/")
+@foobar(1, 2)
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
+
+```python
+def foobar(arg1, arg2):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+
+ response = f(request, *args, **kwargs)
+ if isawaitable(response):
+ response = await response
+
+ return response
+
+ return decorated_function
+
+ return decorator
+```
+
+:---
+
+### Without args
+
+---:1
+
+Sometimes you want a decorator that will not take arguments. When this is the case, it is a nice convenience not to have to call it
+
+```python
+@app.get("/")
+@foobar
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
+
+```python
+def foobar(func):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+
+ response = f(request, *args, **kwargs)
+ if isawaitable(response):
+ response = await response
+
+ return response
+
+ return decorated_function
+
+ return decorator(func)
+```
+
+:---
+
+### With or Without args
+
+---:1
+
+If you want a decorator with the ability to be called or not, you can follow this pattern. Using keyword only arguments is not necessary, but might make implementation simpler.
+
+```python
+@app.get("/")
+@foobar(arg1=1, arg2=2)
+async def handler(request: Request):
+ return text("hi")
+```
+
+```python
+@app.get("/")
+@foobar
+async def handler(request: Request):
+ return text("hi")
+```
+
+:--:1
+
+```python
+def foobar(maybe_func=None, *, arg1=None, arg2=None):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+
+ response = f(request, *args, **kwargs)
+ if isawaitable(response):
+ response = await response
+
+ return response
+
+ return decorated_function
+
+ return decorator(maybe_func) if maybe_func else decorator
+```
+
+:---
From 9a28c9c32f20fb2e9d8c65f05a21912309c3c8bd Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:51 +0300
Subject: [PATCH 054/776] New translations exceptions.md (Japanese)
---
src/ja/guide/best-practices/exceptions.md | 83 ++++++++++-------------
1 file changed, 36 insertions(+), 47 deletions(-)
diff --git a/src/ja/guide/best-practices/exceptions.md b/src/ja/guide/best-practices/exceptions.md
index 5a512390b3..283c6bc1a0 100644
--- a/src/ja/guide/best-practices/exceptions.md
+++ b/src/ja/guide/best-practices/exceptions.md
@@ -2,9 +2,9 @@
## Sanicの例外を使う
-場合によっては、ハンドラの実行を停止し、ステータスコード応答を返すようにSanicに指示する必要があります。このために 「SanicException」 を発生させることができ、残りはSanicが行います。
+場合によっては、ハンドラの実行を停止し、ステータスコード応答を返すようにSanicに指示する必要があります。 このために 「SanicException」 を発生させることができ、残りはSanicが行います。
-オプションの`status_code`引数を渡すことができます。デフォルトでは、SanicExceptionは内部サーバエラー500応答を返します。
+オプションの`status_code`引数を渡すことができます。 デフォルトでは、SanicExceptionは内部サーバエラー500応答を返します。
```python
from sanic.exceptions import SanicException
@@ -14,7 +14,7 @@ async def no_no(request):
raise SanicException("Something went wrong.", status_code=501)
```
-Sanicはいくつかの標準的な例外を提供しています。これらはそれぞれ、応答で適切なHTTPステータスコードを自動的に生成します。詳しくは[APIリファレンスを確認](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#module-sanic.exceptions)を参照してください。
+Sanicはいくつかの標準的な例外を提供しています。 これらはそれぞれ、応答で適切なHTTPステータスコードを自動的に生成します。 詳しくは[APIリファレンスを確認](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#module-sanic.exceptions)を参照してください。
---:1
@@ -45,7 +45,7 @@ async def login(request):
## 例外プロパティ
-Sanicのすべての例外は `SanicException` から派生します。このクラスにはいくつかのプロパティがあり、開発者がアプリケーション全体で一貫して例外を報告できるように支援します。
+Sanicのすべての例外は `SanicException` から派生します。 このクラスにはいくつかのプロパティがあり、開発者がアプリケーション全体で一貫して例外を報告できるように支援します。
- `message`
- `status_code`
@@ -58,8 +58,7 @@ Sanicのすべての例外は `SanicException` から派生します。このク
---:1
### `message`
-`message` プロパティは、Python の他の例外と同様に、表示されるメッセージを制御します。特に便利なのは、クラス定義で `message` プロパティを設定できることで、アプリケーション全体の言語を簡単に標準化することができることです。
-:--:1
+`message` プロパティは、Python の他の例外と同様に、表示されるメッセージを制御します。 特に便利なのは、クラス定義で `message` プロパティを設定できることで、アプリケーション全体の言語を簡単に標準化することができることです。 :--:1
```python
class CustomError(SanicException):
message = "Something bad happened"
@@ -73,8 +72,7 @@ raise CustomError("Override the default message with something else")
---:1
### `status_code`
-このプロパティは、例外が発生したときの応答コードを設定するために用います。これは、通常クライアントから来る悪い情報への対応である、カスタムの400シリーズ例外を作成するときに特に有用です。
-:--:1
+このプロパティは、例外が発生したときの応答コードを設定するために用います。 これは、通常クライアントから来る悪い情報への対応である、カスタムの400シリーズ例外を作成するときに特に有用です。 :--:1 :--:1
```python
class TeapotError(SanicException):
status_code = 418
@@ -89,8 +87,7 @@ raise TeapotError(status_code=400)
---:1
### `quiet`
-デフォルトでは、例外は Sanic によって `error_logger` に出力されます。特に例外ハンドラでイベントのトリガとして例外を使っている場合、これは望ましくないことがあります ([次のセクションを参照してください](./exceptions.md#handling))。`quiet=True`を使用すると、ログ出力を抑制することができます。
-:--:1
+デフォルトでは、例外は Sanic によって `error_logger` に出力されます。 特に例外ハンドラでイベントのトリガとして例外を使っている場合、これは望ましくないことがあります ([次のセクションを参照してください](./exceptions.md#handling))。 `quiet=True`を使用すると、ログ出力を抑制することができます。 :--:1 :--:1
```python
class SilentError(SanicException):
message = "Something happened, but not shown in logs"
@@ -103,9 +100,9 @@ raise InvalidUsage("blah blah", quiet=True)
:---
---:1
-::: new NEW in v21.12
-デバッグ中に、`quiet=True` プロパティをグローバルに無視したいことがあるかもしれません。このプロパティに関係なく、Sanicにすべての例外をログアウトさせるには、 `NOISY_EXCEPTIONS` を使用します。
-:::
+
+---:1 ::: new NEW in v21.12 デバッグ中に、`quiet=True` プロパティをグローバルに無視したいことがあるかもしれません。 このプロパティに関係なく、Sanicにすべての例外をログアウトさせるには、 `NOISY_EXCEPTIONS` を使用します。 ::: :--:1
+
:--:1
```python
app.config.NOISY_EXCEPTIONS = True
@@ -113,11 +110,11 @@ app.config.NOISY_EXCEPTIONS = True
:---
---:1
-::: new NEW in v21.12
+
### `extra`
-[文脈上の例外](./exceptions.md#contextual-exceptions)を参照してください。
-:::
+---:1 ::: new NEW in v21.12
+
:--:1
```python
raise SanicException(..., extra={"name": "Adam"})
@@ -125,11 +122,11 @@ raise SanicException(..., extra={"name": "Adam"})
:---
---:1
-::: new NEW in v21.12
+
### `context`
-[文脈上の例外](./exceptions.md#contextual-exceptions)を参照してください。
-:::
+Sanicはこのためのデコレータを提供しており、これはSanic標準の例外だけでなく、アプリケーションがスローする可能性のある**任意の**例外にも適用されます。
+
:--:1
```python
raise SanicException(..., context={"foo": "bar"})
@@ -139,13 +136,13 @@ raise SanicException(..., context={"foo": "bar"})
## 取り扱い
-Sanicはエラーページを表示することで例外を自動的に処理するので、多くの場合、ユーザ自身が処理する必要はありません。ただし、例外が発生したときの処理をより詳細に制御したい場合は、ハンドラを自分で実装できます。
+Sanicはエラーページを表示することで例外を自動的に処理するので、多くの場合、ユーザ自身が処理する必要はありません。 ただし、例外が発生したときの処理をより詳細に制御したい場合は、ハンドラを自分で実装できます。
-Sanicはこのためのデコレータを提供しており、これはSanic標準の例外だけでなく、アプリケーションがスローする可能性のある**任意の**例外にも適用されます。
+Sanic provides a decorator for this, which applies to not only the Sanic standard exceptions, but **any** exception that your application might throw.
---:1
-ハンドラを追加する最も簡単な方法は、`@app.exception()`を使用して1つ以上の例外を渡すことです。
+`Exception`をキャッチすることで、catchallハンドラを作成することもできます。
:--:1
@@ -161,7 +158,7 @@ async def ignore_404s(request, exception):
---:1
-`Exception`をキャッチすることで、catchallハンドラを作成することもできます。
+`app.error_handler.add()`を使用してエラー・ハンドラを追加することもできます。
:--:1
@@ -175,7 +172,7 @@ async def catch_anything(request, exception):
---:1
-`app.error_handler.add()`を使用してエラー・ハンドラを追加することもできます。
+ハンドラを追加する最も簡単な方法は、`@app.exception()`を使用して1つ以上の例外を渡すことです。
:--:1
@@ -190,11 +187,11 @@ app.error_handler.add(Exception, server_error_handler)
## 組み込みのエラー処理
-Sanicには、例外用にHTML、JSON、およびテキストの3つの形式が用意されています。以下の [Fallback handler](#fallback-handler) セクションに例があります。
+Sanicには、例外用にHTML、JSON、およびテキストの3つの形式が用意されています。 以下の [Fallback handler](#fallback-handler) セクションに例があります。
---:1
-route_which形式を使用するには、`error_format`キーワード引数を使用します。
+Sanicには3つのフォールバック例外ハンドラがあります。
:--:1
@@ -209,7 +206,7 @@ async def handler(request):
## カスタムエラー処理
-場合によっては、デフォルトで提供される機能にさらにエラー処理機能を追加する必要があります。この場合、次のようにSanicのデフォルトのエラーハンドラをサブクラス化できます。
+場合によっては、デフォルトで提供される機能にさらにエラー処理機能を追加する必要があります。 この場合、次のようにSanicのデフォルトのエラーハンドラをサブクラス化できます。
```python
from sanic.handlers import ErrorHandler
@@ -225,7 +222,7 @@ app.error_handler = CustomErrorHandler()
## ハンドルフォールバック
-Sanicには3つのフォールバック例外ハンドラがあります。
+Sanic comes with three fallback exception handlers:
1. HTML (*default*)
2. Text
@@ -386,15 +383,14 @@ content-type: application/json
### 自動
-Sanicには、使用するフォールバックオプションを推測するためのオプションも用意されています。これはまだ**実験的な機能です**.
+Sanicには、使用するフォールバックオプションを推測するためのオプションも用意されています。 これはまだ**実験的な機能です**.
```python
app.config.FALLBACK_ERROR_FORMAT = "auto"
```
## 文脈上の例外
-::: new NEW in v21.12
-デフォルトの例外メッセージにより、アプリケーション全体で一貫して例外を発生させる機能を簡素化できます。
+---:1 **制作**
```python
class TeapotError(SanicException):
@@ -404,7 +400,7 @@ class TeapotError(SanicException):
raise TeapotError
```
-しかし、これには2つのことが欠けています。
+:--:1 **開発**
1. ダイナミックで予測可能なメッセージのフォーマット
2. エラーメッセージに追加のコンテキストを追加する機能(詳細は後述します)
@@ -424,30 +420,25 @@ class TeapotError(SanicException):
raise TeapotError(extra={"name": "Adam"})
```
-この新しい機能では、例外インスタンスに `extra` メタを渡すことができます。これは、上記の例のように、メッセージテキストに動的なデータを渡すのに特に便利です。この `extra` 情報オブジェクトは、 `PRODUCTION` モードでは抑制され**、 `DEVELOPMENT` モードでは表示されます。
+この新しい機能では、例外インスタンスに `extra` メタを渡すことができます。 これは、上記の例のように、メッセージテキストに動的なデータを渡すのに特に便利です。 この `extra` 情報オブジェクトは、 `PRODUCTION` モードでは抑制され**、 `DEVELOPMENT` モードでは表示されます。
----:1
-**制作**
+:--:1 **開発**
-
-:--:1
-**開発**
+ ---:1 **制作**
-
-:---
+ :---
### エラーメッセージに `context` を追加する
-Sanic の例外は、 `context` 引数とともに発生させて、何が起こったのかについてユーザーに意図した情報を渡すこともできます。これは、マイクロサービスや、JSON形式のエラーメッセージを渡すことを目的としたAPIを作成するときに特に便利です。この使用例では、クライアントに詳細を返すために、解析可能なエラーメッセージだけでなく、例外の周りにいくつかのコンテキストを持ちたいと思います。
+Sanic の例外は、 `context` 引数とともに発生させて、何が起こったのかについてユーザーに意図した情報を渡すこともできます。 これは、マイクロサービスや、JSON形式のエラーメッセージを渡すことを目的としたAPIを作成するときに特に便利です。 この使用例では、クライアントに詳細を返すために、解析可能なエラーメッセージだけでなく、例外の周りにいくつかのコンテキストを持ちたいと思います。
```python
raise TeapotError(context={"foo": "bar"})
```
-これは、(利用可能であれば)常にエラーで渡される**ようにしたい**情報です。以下のような感じです。
+これは、(利用可能であれば)常にエラーで渡される**ようにしたい**情報です。 以下のような感じです。
----:1
-**制作**
+---:1 **PRODUCTION**
```json
{
@@ -459,8 +450,7 @@ raise TeapotError(context={"foo": "bar"})
}
}
```
-:--:1
-**開発**
+:--:1 **DEVELOPMENT**
```json
{
@@ -495,4 +485,3 @@ raise TeapotError(context={"foo": "bar"})
}
```
:---
-:::
From b18a59c6a88da3fc7a850b70c3afbb5ca5f45a4c Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:52 +0300
Subject: [PATCH 055/776] New translations exceptions.md (Korean)
---
src/ko/guide/best-practices/exceptions.md | 487 ++++++++++++++++++++++
1 file changed, 487 insertions(+)
create mode 100644 src/ko/guide/best-practices/exceptions.md
diff --git a/src/ko/guide/best-practices/exceptions.md b/src/ko/guide/best-practices/exceptions.md
new file mode 100644
index 0000000000..806dd08e9c
--- /dev/null
+++ b/src/ko/guide/best-practices/exceptions.md
@@ -0,0 +1,487 @@
+# Exceptions
+
+## Using Sanic exceptions
+
+Sometimes you just need to tell Sanic to halt execution of a handler and send back a status code response. You can raise a `SanicException` for this and Sanic will do the rest for you.
+
+You can pass an optional `status_code` argument. By default, a SanicException will return an internal server error 500 response.
+
+```python
+from sanic.exceptions import SanicException
+
+@app.route("/youshallnotpass")
+async def no_no(request):
+ raise SanicException("Something went wrong.", status_code=501)
+```
+
+Sanic provides a number of standard exceptions. They each automatically will raise the appropriate HTTP status code in your response. [Check the API reference](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#module-sanic.exceptions) for more details.
+
+---:1
+
+The more common exceptions you _should_ implement yourself include:
+
+- `InvalidUsage` (400)
+- `Unauthorized` (401)
+- `Forbidden` (403)
+- `NotFound` (404)
+- `ServerError` (500)
+
+:--:1
+
+```python
+from sanic import exceptions
+
+@app.route("/login")
+async def login(request):
+ user = await some_login_func(request)
+ if not user:
+ raise exceptions.NotFound(
+ f"Could not find user with username={request.json.username}"
+ )
+ ...
+```
+
+:---
+
+## Exception properties
+
+All exceptions in Sanic derive from `SanicException`. That class has a few properties on it that assist the developer in consistently reporting their exceptions across an application.
+
+- `message`
+- `status_code`
+- `quiet`
+- `context`
+- `extra`
+
+All of these properties can be passed to the exception when it is created, but the first three can also be used as class variables as we will see.
+
+---:1
+### `message`
+
+The `message` property obviously controls the message that will be displayed as with any other exception in Python. What is particularly useful is that you can set the `message` property on the class definition allowing for easy standardization of language across an application :--:1
+```python
+class CustomError(SanicException):
+ message = "Something bad happened"
+
+raise CustomError
+# or
+raise CustomError("Override the default message with something else")
+```
+:---
+
+---:1
+### `status_code`
+
+This property is used to set the response code when the exception is raised. This can particularly be useful when creating custom 400 series exceptions that are usually in response to bad information coming from the client. :--:1
+```python
+class TeapotError(SanicException):
+ status_code = 418
+ message = "Sorry, I cannot brew coffee"
+
+raise TeapotError
+# or
+raise TeapotError(status_code=400)
+```
+:---
+
+---:1
+### `quiet`
+
+By default, exceptions will be output by Sanic to the `error_logger`. Sometimes this may not be desirable, especially if you are using exceptions to trigger events in exception handlers (see [the following section](./exceptions.md#handling)). You can suppress the log output using `quiet=True`. :--:1
+```python
+class SilentError(SanicException):
+ message = "Something happened, but not shown in logs"
+ quiet = True
+
+raise SilentError
+# or
+raise InvalidUsage("blah blah", quiet=True)
+```
+:---
+
+---:1
+
+Sometimes while debugging you may want to globally ignore the `quiet=True` property. You can force Sanic to log out all exceptions regardless of this property using `NOISY_EXCEPTIONS`
+
+:--:1
+```python
+app.config.NOISY_EXCEPTIONS = True
+```
+:---
+
+---:1
+
+### `extra`
+
+See [contextual exceptions](./exceptions.md#contextual-exceptions)
+
+:--:1
+```python
+raise SanicException(..., extra={"name": "Adam"})
+```
+:---
+
+---:1
+
+### `context`
+
+See [contextual exceptions](./exceptions.md#contextual-exceptions)
+
+:--:1
+```python
+raise SanicException(..., context={"foo": "bar"})
+```
+:---
+
+
+## Handling
+
+Sanic handles exceptions automatically by rendering an error page, so in many cases you don't need to handle them yourself. However, if you would like more control on what to do when an exception is raised, you can implement a handler yourself.
+
+Sanic provides a decorator for this, which applies to not only the Sanic standard exceptions, but **any** exception that your application might throw.
+
+---:1
+
+The easiest method to add a handler is to use `@app.exception()` and pass it one or more exceptions.
+
+:--:1
+
+```python
+from sanic.exceptions import NotFound
+
+@app.exception(NotFound, SomeCustomException)
+async def ignore_404s(request, exception):
+ return text("Yep, I totally found the page: {}".format(request.url))
+```
+
+:---
+
+---:1
+
+You can also create a catchall handler by catching `Exception`.
+
+:--:1
+
+```python
+@app.exception(Exception)
+async def catch_anything(request, exception):
+ ...
+```
+
+:---
+
+---:1
+
+You can also use `app.error_handler.add()` to add error handlers.
+
+:--:1
+
+```python
+async def server_error_handler(request, exception):
+ return text("Oops, server error", status=500)
+
+app.error_handler.add(Exception, server_error_handler)
+```
+
+:---
+
+## Built-in error handling
+
+Sanic ships with three formats for exceptions: HTML, JSON, and text. You can see examples of them below in the [Fallback handler](#fallback-handler) section.
+
+---:1
+
+You can control _per route_ which format to use with the `error_format` keyword argument.
+
+:--:1
+
+```python
+@app.request("/", error_format="text")
+async def handler(request):
+ ...
+```
+
+:---
+
+
+## Custom error handling
+
+In some cases, you might want to add some more error handling functionality to what is provided by default. In that case, you can subclass Sanic's default error handler as such:
+
+```python
+from sanic.handlers import ErrorHandler
+
+class CustomErrorHandler(ErrorHandler):
+ def default(self, request, exception):
+ ''' handles errors that have no error handlers assigned '''
+ # You custom error handling logic...
+ return super().default(request, exception)
+
+app.error_handler = CustomErrorHandler()
+```
+
+## Fallback handler
+
+Sanic comes with three fallback exception handlers:
+
+1. HTML (*default*)
+2. Text
+3. JSON
+
+These handlers present differing levels of detail depending upon whether your application is in [debug mode](/guide/deployment/development.md) or not.
+
+### HTML
+
+```python
+app.config.FALLBACK_ERROR_FORMAT = "html"
+```
+
+---:1
+
+```python
+app.config.DEBUG = True
+```
+
+
+
+:--:1
+
+```python
+app.config.DEBUG = False
+```
+
+
+
+:---
+
+### Text
+
+```python
+app.config.FALLBACK_ERROR_FORMAT = "text"
+```
+
+---:1
+
+```python
+app.config.DEBUG = True
+```
+
+```bash
+$ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 590
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+⚠️ 500 — Internal Server Error
+==============================
+That time when that thing broke that other thing? That happened.
+
+ServerError: That time when that thing broke that other thing? That happened. while handling path /exc
+Traceback of __BASE__ (most recent call last):
+
+ ServerError: That time when that thing broke that other thing? That happened.
+ File /path/to/sanic/app.py, line 986, in handle_request
+ response = await response
+
+ File /path/to/server.py, line 222, in exc
+ raise ServerError(
+```
+
+:--:1
+
+```python
+app.config.DEBUG = False
+```
+
+```bash
+$ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 134
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+⚠️ 500 — Internal Server Error
+==============================
+That time when that thing broke that other thing? That happened.
+```
+
+:---
+
+### JSON
+
+```python
+app.config.FALLBACK_ERROR_FORMAT = "json"
+```
+
+---:1
+
+```python
+app.config.DEBUG = True
+```
+
+```bash
+$ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 129
+connection: keep-alive
+content-type: application/json
+
+{
+ "description": "Internal Server Error",
+ "status": 500,
+ "message": "That time when that thing broke that other thing? That happened.",
+ "path": "/exc",
+ "args": {},
+ "exceptions": [
+ {
+ "type": "ServerError",
+ "exception": "That time when that thing broke that other thing? That happened.",
+ "frames": [
+ {
+ "file": "/path/to/sanic/app.py",
+ "line": 986,
+ "name": "handle_request",
+ "src": "response = await response"
+ },
+ {
+ "file": "/path/to/server.py",
+ "line": 222,
+ "name": "exc",
+ "src": "raise ServerError("
+ }
+ ]
+ }
+ ]
+}
+
+
+```
+
+:--:1
+
+```python
+app.config.DEBUG = False
+```
+
+```bash
+$ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 530
+connection: keep-alive
+content-type: application/json
+
+{
+ "description": "Internal Server Error",
+ "status": 500,
+ "message": "That time when that thing broke that other thing? That happened."
+}
+
+```
+
+:---
+
+### Auto
+
+Sanic also provides an option for guessing which fallback option to use. This is still an **experimental feature**.
+
+```python
+app.config.FALLBACK_ERROR_FORMAT = "auto"
+```
+## Contextual Exceptions
+
+Default exception messages that simplify the ability to consistently raise exceptions throughout your application.
+
+```python
+class TeapotError(SanicException):
+ status_code = 418
+ message = "Sorry, I cannot brew coffee"
+
+raise TeapotError
+```
+
+But this lacks two things:
+
+1. A dynamic and predictable message format
+2. The ability to add additional context to an error message (more on this in a moment)
+
+### Dynamic and predictable message using `extra`
+
+Sanic exceptions can be raised using `extra` keyword arguments to provide additional information to a raised exception instance.
+
+```python
+class TeapotError(SanicException):
+ status_code = 418
+
+ @property
+ def message(self):
+ return f"Sorry {self.extra['name']}, I cannot make you coffee"
+
+raise TeapotError(extra={"name": "Adam"})
+```
+
+The new feature allows the passing of `extra` meta to the exception instance, which can be particularly useful as in the above example to pass dynamic data into the message text. This `extra` info object **will be suppressed** when in `PRODUCTION` mode, but displayed in `DEVELOPMENT` mode.
+
+---:1 **PRODUCTION**
+
+ :--:1 **DEVELOPMENT**
+
+ :---
+
+### Additional `context` to an error message
+
+Sanic exceptions can also be raised with a `context` argument to pass intended information along to the user about what happened. This is particularly useful when creating microservices or an API intended to pass error messages in JSON format. In this use case, we want to have some context around the exception beyond just a parseable error message to return details to the client.
+
+```python
+raise TeapotError(context={"foo": "bar"})
+```
+
+This is information **that we want** to always be passed in the error (when it is available). Here is what it should look like:
+
+---:1 **PRODUCTION**
+
+```json
+{
+ "description": "I'm a teapot",
+ "status": 418,
+ "message": "Sorry Adam, I cannot make you coffee",
+ "context": {
+ "foo": "bar"
+ }
+}
+```
+:--:1 **DEVELOPMENT**
+
+```json
+{
+ "description": "I'm a teapot",
+ "status": 418,
+ "message": "Sorry Adam, I cannot make you coffee",
+ "context": {
+ "foo": "bar"
+ },
+ "path": "/",
+ "args": {},
+ "exceptions": [
+ {
+ "type": "TeapotError",
+ "exception": "Sorry Adam, I cannot make you coffee",
+ "frames": [
+ {
+ "file": "handle_request",
+ "line": 83,
+ "name": "handle_request",
+ "src": ""
+ },
+ {
+ "file": "/tmp/p.py",
+ "line": 17,
+ "name": "handler",
+ "src": "raise TeapotError("
+ }
+ ]
+ }
+ ]
+}
+```
+:---
From 51cf78f09e50722ec2d2bb5c4a1ca87dfd3cd216 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:54 +0300
Subject: [PATCH 056/776] New translations exceptions.md (Chinese Simplified)
---
src/zh/guide/best-practices/exceptions.md | 113 ++++++++++------------
1 file changed, 49 insertions(+), 64 deletions(-)
diff --git a/src/zh/guide/best-practices/exceptions.md b/src/zh/guide/best-practices/exceptions.md
index 3c6cabd4ed..8e1664b551 100644
--- a/src/zh/guide/best-practices/exceptions.md
+++ b/src/zh/guide/best-practices/exceptions.md
@@ -2,9 +2,9 @@
## 使用 Sanic 内置异常(Using Sanic exceptions)
-有时,您只需要告诉 Sanic 终止执行响应函数,并返回一个状态码。此时,您可以抛出 `SanicException` 异常,之后,Sanic 将为您自动完成剩下的工作。
+有时,您只需要告诉 Sanic 终止执行响应函数,并返回一个状态码。 此时,您可以抛出 `SanicException` 异常,之后,Sanic 将为您自动完成剩下的工作。
-您可以选择传递一个参数 `status_code`。默认情况下,如果您不传递该参数,SanicException 将会返回一个 HTTP 500 内部服务错误的响应
+您可以选择传递一个参数 `status_code`。 默认情况下,如果您不传递该参数,SanicException 将会返回一个 HTTP 500 内部服务错误的响应
```python
from sanic.exceptions import SanicException
@@ -14,7 +14,7 @@ async def no_no(request):
raise SanicException("Something went wrong.", status_code=501)
```
-Sanic 预置了许多标准异常。它们每个都会在您的响应中自动触发适当的 HTTP 状态代码。查看 [接口文档](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#module-sanic.exceptions) 了解更多详细信息。
+Sanic 预置了许多标准异常。 它们每个都会在您的响应中自动触发适当的 HTTP 状态代码。 查看 [接口文档](https://sanic.readthedocs.io/en/latest/sanic/api_reference.html#module-sanic.exceptions) 了解更多详细信息。
---:1
@@ -45,7 +45,7 @@ async def login(request):
## 异常属性(Exception properties)
-在 Sanic 中,所有异常都继承自 `SanicException`。该类有一些属性,可以帮助开发人员在整个应用程序中一致地报告异常。
+在 Sanic 中,所有异常都继承自 `SanicException`。 该类有一些属性,可以帮助开发人员在整个应用程序中一致地报告异常。
- `message`
- `status_code`
@@ -56,13 +56,9 @@ async def login(request):
所有这些属性都可以在异常创建时传递给它,但是前三个将会作为可见的信息被返回出来。
---:1
+### `message`
-### 信息属性(`message`)
-
-`message` 属性控制着 Python 中任何其他异常显示的消息。您可以在类定义上设置 `message` 属性,以便在整个应用程序中轻松实现语言的标准化。
-
-:--:1
-
+`message` 属性控制着 Python 中任何其他异常显示的消息。 您可以在类定义上设置 `message` 属性,以便在整个应用程序中轻松实现语言的标准化。
```python
class CustomError(SanicException):
message = "Something bad happened"
@@ -71,17 +67,12 @@ raise CustomError
# or
raise CustomError("Override the default message with something else")
```
-
:---
---:1
+### `status_code`
-### 状态码属性(`status_code`)
-
-该属性用于设置异常时的响应码。这在创建自定义 400 系列异常时特别有用,这些异常通常是为了响应来自客户端的错误信息。
-
-:--:1
-
+该属性用于设置异常时的响应码。 这在创建自定义 400 系列异常时特别有用,这些异常通常是为了响应来自客户端的错误信息。 :--:1
```python
class TeapotError(SanicException):
status_code = 418
@@ -91,17 +82,12 @@ raise TeapotError
# or
raise TeapotError(status_code=400)
```
-
:---
---:1
+### `quiet`
-### 静默输出(`quiet`)
-
-默认情况下,Sanic 会将异常输出到 `error_logger`。有时这可能并不理想,尤其是当您使用异常来触发异常处理程序中的事件时(参见[下一节](./exceptions.md#handling))。您可以使用`quiet=True` 来禁止日志输出。
-
-:--:1
-
+默认情况下,Sanic 会将异常输出到 `error_logger`。 有时这可能并不理想,尤其是当您使用异常来触发异常处理程序中的事件时(参见[下一节](./exceptions.md#handling))。 您可以使用`quiet=True` 来禁止日志输出。 :--:1
```python
class SilentError(SanicException):
message = "Something happened, but not shown in logs"
@@ -111,52 +97,46 @@ raise SilentError
# or
raise InvalidUsage("blah blah", quiet=True)
```
-
:---
---:1
-有时在调试时,您可能希望全局忽略 `quiet=True` 属性。您可以使用 `NOISY_EXCEPTIONS` 来忽略 `quiet` 的设置,强制 Sanic 注销所有异常。
+有时在调试时,您可能希望全局忽略 `quiet=True` 属性。 您可以使用 `NOISY_EXCEPTIONS` 来忽略 `quiet` 的设置,强制 Sanic 注销所有异常。
:--:1
-
```python
app.config.NOISY_EXCEPTIONS = True
```
-
:---
---:1
-### 额外属性(`extra`)
+### `extra`
请参考 [上下文异常](./exceptions.md#contextual-exceptions)
:--:1
-
```python
raise SanicException(..., extra={"name": "Adam"})
```
-
:---
---:1
-### 上下文(`context`)
+### `context`
请参考 [上下文异常](./exceptions.md#contextual-exceptions)
:--:1
-
```python
raise SanicException(..., context={"foo": "bar"})
```
-
:---
+
## 处理(Handling)
-Sanic 通过呈现错误页面来自动处理异常,因此在许多情况下,您不需要自己处理它们。但是,如果您希望在引发异常时更多地控制该做什么,您同样可以自己实现一个处理程序。
+Sanic 通过呈现错误页面来自动处理异常,因此在许多情况下,您不需要自己处理它们。 但是,如果您希望在引发异常时更多地控制该做什么,您同样可以自己实现一个处理程序。
Sanic 为此提供了一个装饰器,它不仅适用于 Sanic 标准异常,还适用于您的应用程序可能抛出的**任何**异常。
@@ -207,7 +187,7 @@ app.error_handler.add(Exception, server_error_handler)
## 内置异常处理(Built-in error handling)
-Sanic 支持三种不同的异常格式: HTML、JSON 和 TEXT。您可以在下面的 [异常格式](#fallback-handler) 一节中看到它们的示例。
+Sanic 支持三种不同的异常格式: HTML、JSON 和 TEXT。 您可以在下面的 [异常格式](#fallback-handler) 一节中看到它们的示例。
---:1
@@ -223,9 +203,10 @@ async def handler(request):
:---
+
## 自定义异常处理(Custom error handling)
-在某些情况下,您可能希望在默认设置的基础上增加更多的错误处理功能。在这种情况下,您可以将 Sanic 的默认错误处理程序子类化,例如:
+在某些情况下,您可能希望在默认设置的基础上增加更多的错误处理功能。 在这种情况下,您可以将 Sanic 的默认错误处理程序子类化,例如:
```python
from sanic.handlers import ErrorHandler
@@ -236,13 +217,15 @@ class CustomErrorHandler(ErrorHandler):
# You custom error handling logic...
return super().default(request, exception)
+app.error_handler = CustomErrorHandler()
+ return super().default(request, exception)
+
app.error_handler = CustomErrorHandler()
```
## 异常格式(Fallback handler)
-Sanic comes with three fallback exception handlers:
-Sanic 自带了三种异常格式。
+Sanic comes with three fallback exception handlers: Sanic 自带了三种异常格式。
1. HTML (_default_)
2. Text
@@ -297,6 +280,20 @@ content-type: text/plain; charset=utf-8
==============================
That time when that thing broke that other thing? That happened.
+ServerError: That time when that thing broke that other thing? That happened. while handling path /exc
+Traceback of __BASE__ (most recent call last):
+
+ ServerError: That time when that thing broke that other thing? That happened.
+ $ curl localhost:8000/exc -i
+HTTP/1.1 500 Internal Server Error
+content-length: 590
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+⚠️ 500 — Internal Server Error
+==============================
+That time when that thing broke that other thing? That happened.
+
ServerError: That time when that thing broke that other thing? That happened. while handling path /exc
Traceback of __BASE__ (most recent call last):
@@ -323,7 +320,7 @@ content-type: text/plain; charset=utf-8
⚠️ 500 — Internal Server Error
==============================
-That time when that thing broke that other thing? That happened.
+That time when that thing broke that other thing? That happened. That happened.
```
:---
@@ -395,6 +392,7 @@ content-type: application/json
"description": "Internal Server Error",
"status": 500,
"message": "That time when that thing broke that other thing? That happened."
+} That happened."
}
```
@@ -403,12 +401,11 @@ content-type: application/json
### Auto
-Sanic 还提供了一个选项,用于猜测使用哪种异常格式。该功能依旧处于 **试验阶段**。
+Sanic 还提供了一个选项,用于猜测使用哪种异常格式。 该功能依旧处于 **试验阶段**。
```python
app.config.FALLBACK_ERROR_FORMAT = "auto"
```
-
## 上下文异常(Contextual Exceptions)
默认异常消息简化了在整个应用程序中一致引发异常的能力。
@@ -421,14 +418,14 @@ class TeapotError(SanicException):
raise TeapotError
```
-但这样会忽视两个非常重要的问题:
+But this lacks two things:
1. 如何设置动态且可预测的消息格式
2. 如何向错误消息中添加额外上下文内容(稍后将详细介绍)
### 使用 `extra` 来设置动态且可预测的消息(Dynamic and predictable message using `extra`)
-Sanic 异常可以使用 `extra` 属性来获取传入的额外信息,例如:
+Sanic exceptions can be raised using `extra` keyword arguments to provide additional information to a raised exception instance.
```python
class TeapotError(SanicException):
@@ -441,35 +438,25 @@ class TeapotError(SanicException):
raise TeapotError(extra={"name": "Adam"})
```
-这个新特性允许将 `extra` 元传递给异常实例,这在上面的例子中将动态数据传递给消息文本时非常有用。在生产模式下,`extra` 信息对象 **将被隐藏**,但在开发模式下将s显示。
-
----:1
-
-**生产模式**
-
-
-
-:--:1
+这个新特性允许将 `extra` 元传递给异常实例,这在上面的例子中将动态数据传递给消息文本时非常有用。 在生产模式下,`extra` 信息对象 **将被隐藏**,但在开发模式下将s显示。
-**开发模式**
+但这样会忽视两个非常重要的问题:
-
+ Sanic 异常可以使用 `extra` 属性来获取传入的额外信息,例如:
-:---
+ :---
### 在异常信息中附加上下文内容(Additional `context` to an error message)
-Sanic 异常也可以通过 `context` 参数来引发,方便告诉开发者发生了什么。这对微服务或旨在以 JSON 格式传递错误消息的 API 特别有用。在这个用例中,我们希望有一些关于异常的上下文,而不仅仅是一个可解析的错误消息,以便向客户端返回详细信息。
+Sanic 异常也可以通过 `context` 参数来引发,方便告诉开发者发生了什么。 这对微服务或旨在以 JSON 格式传递错误消息的 API 特别有用。 在这个用例中,我们希望有一些关于异常的上下文,而不仅仅是一个可解析的错误消息,以便向客户端返回详细信息。
```python
raise TeapotError(context={"foo": "bar"})
```
-`context` 将始终被传递到异常信息中,这正是我们想要看到的,它看起来就像这样:
-
----:1
+This is information **that we want** to always be passed in the error (when it is available). Here is what it should look like:
-**生产模式**
+---:1 **PRODUCTION**
```json
{
@@ -481,9 +468,7 @@ raise TeapotError(context={"foo": "bar"})
}
}
```
-:--:1
-
-**开发模式**
+:--:1 **DEVELOPMENT**
```json
{
From f3f827e2f84a1bbd1a16d8f4b889f58f9f791e60 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:55 +0300
Subject: [PATCH 057/776] New translations logging.md (Japanese)
---
src/ja/guide/best-practices/logging.md | 38 ++++++++++++--------------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/src/ja/guide/best-practices/logging.md b/src/ja/guide/best-practices/logging.md
index 1b308c3930..b4909ab716 100644
--- a/src/ja/guide/best-practices/logging.md
+++ b/src/ja/guide/best-practices/logging.md
@@ -1,13 +1,12 @@
# Logging
-Sanicでは、[Python logging API](https://docs.python.org/3/howto/logging.html)に基づいて、さまざまなタイプのロギング(アクセスログ、エラーログ)を要求に対して実行できます。新しい設定を作成する場合は、Pythonロギングに関する基本的な知識が必要です。
+Sanicでは、[Python logging API](https://docs.python.org/3/howto/logging.html)に基づいて、さまざまなタイプのロギング(アクセスログ、エラーログ)を要求に対して実行できます。 新しい設定を作成する場合は、Pythonロギングに関する基本的な知識が必要です。
## クイックスタート
---:1
-デフォルト設定を使用する簡単な例を次に示します。
-:--:1
+デフォルト設定を使用する簡単な例を次に示します。 :--:1
```python
from sanic import Sanic
from sanic.log import logger
@@ -48,27 +47,24 @@ if __name__ == "__main__":
app.run(access_log=False)
```
-::: tip FYI
-Pythonでのロギングは比較的安価な操作です。ただし、多数の要求を処理していて、パフォーマンスが懸念される場合は、アクセスログをログアウトする時間が増え、非常にコストがかかります。
+::: tip FYI Pythonでのロギングは比較的安価な操作です。 ただし、多数の要求を処理していて、パフォーマンスが懸念される場合は、アクセスログをログアウトする時間が増え、非常にコストがかかります。
-これは、 (nginxのような) プロキシの背後にSanicを置き、そこでアクセスログを取る良い機会です。`access_log`を無効にすると、全体的なパフォーマンスが*大幅に*向上します。
+これは、 (nginxのような) プロキシの背後にSanicを置き、そこでアクセスログを取る良い機会です。 `access_log`を無効にすると、全体的なパフォーマンスが*大幅に*向上します。
-最適な運用パフォーマンスを得るには、`debug`と`access_log`を無効にした状態で、`app.run(debug=False、access_log=False)`でSanicを実行することをお勧めします。
-:::
+最適な運用パフォーマンスを得るには、`debug`と`access_log`を無効にした状態で、`app.run(debug=False、access_log=False)`でSanicを実行することをお勧めします。 :::
## 構成
-Sanicのデフォルトのロギング設定は、`sanic.log。LOGGING_CONFIG_DEFAULTS`を参照してください。
+Sanicのデフォルトのロギング設定は、`sanic.log。 LOGGING_CONFIG_DEFAULTS`を参照してください。
----:1
-sanicで使用されるロガーは3つあり、独自のロギング設定を作成する場合は定義する必要があります。
+---:1 sanicで使用されるロガーは3つあり、独自のロギング設定を作成する場合は定義する必要があります。
-| **Logger Name** | **Use Case** |
-|-----------------|-------------------------------|
+| **Logger Name** | **Use Case** |
+| --------------- | ------------------ |
| `sanic.root` | 内部メッセージのログに使用されます。 |
-| `sanic.error` | エラーログの記録に使用されます。 |
+| `sanic.error` | エラーログの記録に使用されます。 |
| `sanic.access` | アクセスログの記録に使用されます。 |
-:--:1
+ :--:1
:---
@@ -76,12 +72,12 @@ sanicで使用されるロガーは3つあり、独自のロギング設定を
Pythonが提供するデフォルトのパラメータ(`asctime`,`levelname`,`message`)に加えて、SanicはAccess Loggerに追加のパラメータを提供します。
-| Log Context Parameter | Parameter Value | Datatype |
-|-----------------------|---------------------------------------|----------|
-| `host` | `request.ip` | `str` |
-| `request` | `request.method + " " + request.url` | `str` |
-| `status` | `response` | `int` |
-| `byte` | `len(response.body)` | `int` |
+| Log Context Parameter | Parameter Value | Datatype |
+| --------------------- | ------------------------------------ | -------- |
+| `host` | `request.ip` | `str` |
+| `request` | `request.method + " " + request.url` | `str` |
+| `status` | `response` | `int` |
+| `byte` | `len(response.body)` | `int` |
From e19ba205646bc96c233aff0902da04cb5fae06e0 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:56 +0300
Subject: [PATCH 058/776] New translations blueprints.md (Japanese)
---
src/ja/guide/best-practices/blueprints.md | 49 ++++++++---------------
1 file changed, 17 insertions(+), 32 deletions(-)
diff --git a/src/ja/guide/best-practices/blueprints.md b/src/ja/guide/best-practices/blueprints.md
index 41c2547f70..0c2482672e 100644
--- a/src/ja/guide/best-practices/blueprints.md
+++ b/src/ja/guide/best-practices/blueprints.md
@@ -2,7 +2,7 @@
## 概要
-設計図は、アプリケーション内のサブルーティングに使用できるオブジェクトです。設計図では、アプリケーション・インスタンスにルートを追加する代わりに、ルートを追加するための同様のメソッドを定義し、それを柔軟でプラグ可能な方法でアプリケーションに登録します。
+設計図は、アプリケーション内のサブルーティングに使用できるオブジェクトです。 設計図では、アプリケーション・インスタンスにルートを追加する代わりに、ルートを追加するための同様のメソッドを定義し、それを柔軟でプラグ可能な方法でアプリケーションに登録します。
設計図は、アプリケーション・ロジックを複数のグループまたは責任領域に分けることができる大規模なアプリケーションに特に役立ちます。
@@ -10,8 +10,7 @@
---:1
-まず、設計図を作成する必要があります。これは、多くの同じデコレータを持つ`Sanic()`アプリケーションインスタンスと非常に似たAPIを持っています。
-:--:1
+まず、設計図を作成する必要があります。 これは、多くの同じデコレータを持つ`Sanic()`アプリケーションインスタンスと非常に似たAPIを持っています。 :--:1 :--:1
```python
# ./my_blueprint.py
from sanic.response import json
@@ -28,8 +27,7 @@ async def bp_root(request):
---:1
-次に、アプリケーションインスタンスに登録します。
-:--:1
+次に、アプリケーションインスタンスに登録します。 :--:1 :--:1
```python
from sanic import Sanic
from my_blueprint import bp
@@ -43,9 +41,7 @@ Blueprintには、websocketsを実装するための同じ`websocket()`デコレ
---:1
-::: new NEW in v21.12
-v21.12 以降では、ブループリントはオブジェクトを追加する前でも後でも登録することができます。以前は、登録時にブループリントにアタッチされたオブジェクトのみがアプリケーション インスタンスにロードされました。
-:--:1
+::: new NEW in v21.12 v21.12 以降では、ブループリントはオブジェクトを追加する前でも後でも登録することができます。 以前は、登録時にブループリントにアタッチされたオブジェクトのみがアプリケーション インスタンスにロードされました。 :--:1 :--:1
```python
app.blueprint(bp)
@@ -58,7 +54,7 @@ async def bp_root(request):
---:1
-`copy()`メソッドを使用すると、設計図とそれにアタッチされているすべてのものを新しいインスタンスにコピーできます。唯一必要な引数は、新しい`name`を渡すことです。ただし、これを使用して、古い設計図の値をオーバーライドすることもできます。
+`copy()`メソッドを使用すると、設計図とそれにアタッチされているすべてのものを新しいインスタンスにコピーできます。 唯一必要な引数は、新しい`name`を渡すことです。 ただし、これを使用して、古い設計図の値をオーバーライドすることもできます。
:--:1
@@ -86,7 +82,7 @@ Available routes:
## Blueprintグループ
-設計図は、リストまたはタプルの一部として登録することもでき、レジストラは、設計図のサブシーケンスを再帰的に巡回し、それに従って登録する。Blueprint.groupメソッドは、このプロセスを単純化するために提供されており、フロントエンドから見えるものを模倣する`モック`バックエンドディレクトリ構造を可能にする。次の (かなり不自然な) 例を考えてみましょう。
+設計図は、リストまたはタプルの一部として登録することもでき、レジストラは、設計図のサブシーケンスを再帰的に巡回し、それに従って登録する。 Blueprint.groupメソッドは、このプロセスを単純化するために提供されており、フロントエンドから見えるものを模倣する`モック`バックエンドディレクトリ構造を可能にする。 次の (かなり不自然な) 例を考えてみましょう。
```text
api/
@@ -189,8 +185,7 @@ app.blueprint(api)
---:1
-Blueprintsは、エンドポイント専用に登録されたミドルウェアを持つこともできます。
-:--:1
+Blueprintsは、エンドポイント専用に登録されたミドルウェアを持つこともできます。 :--:1 :--:1
```python
@bp.middleware
async def print_on_request(request):
@@ -208,8 +203,7 @@ async def halt_response(request, response):
---:1
-同様に、設計図グループを使用すると、ネストされた設計図グループ全体にミドルウェアを適用できます。
-:--:1
+同様に、設計図グループを使用すると、ネストされた設計図グループ全体にミドルウェアを適用できます。 :--:1 :--:1
```python
bp1 = Blueprint("bp1", url_prefix="/bp1")
bp2 = Blueprint("bp2", url_prefix="/bp2")
@@ -241,8 +235,7 @@ app.blueprint(group)
---:1
-他の[例外処理](./exceptions.md)を使用して、設計図固有のハンドラーを定義できます。
-:--:1
+他の[例外処理](./exceptions.md)を使用して、設計図固有のハンドラーを定義できます。 :--:1 :--:1
```python
@bp.exception(NotFound)
def ignore_404s(request, exception):
@@ -254,8 +247,7 @@ def ignore_404s(request, exception):
---:1
-Blueprintsは独自の静的ハンドラを持つこともできます。
-:--:1
+Blueprintsは独自の静的ハンドラを持つこともできます。 :--:1
```python
bp = Blueprint("bp", url_prefix="/bp")
bp.static("/web/path", "/folder/to/serve")
@@ -265,8 +257,7 @@ bp.static("/web/path", "/folder/to/server", name="uploads")
---:1
-これは、`url_for()`を使用して取得できます。詳細については、[ルーティング](/guide/basics/routing.md) を参照してください。
-:--:1
+これは、`url_for()`を使用して取得できます。 詳細については、[ルーティング](/guide/basics/routing.md) を参照してください。 :--:1 :--:1
```python
>>> print(app.url_for("static", name="bp.uploads", filename="file.txt"))
'/bp/web/path/file.txt'
@@ -277,8 +268,7 @@ bp.static("/web/path", "/folder/to/server", name="uploads")
---:1
-Blueprintsは[listeners](/guide/basics/listeners.md)も実装できます。
-:--:1
+Blueprintsは[listeners](/guide/basics/listeners.md)も実装できます。 :--:1 :--:1
```python
@bp.listener("before_server_start")
async def before_server_start(app, loop):
@@ -296,8 +286,7 @@ async def after_server_stop(app, loop):
---:1
-`version`は、ルートの前に`/v1`または`/v2`のように付加されます。
-:--:1
+`version`は、ルートの前に`/v1`または`/v2`のように付加されます。 :--:1
```python
auth1 = Blueprint("auth", url_prefix="/auth", version=1)
auth2 = Blueprint("auth", url_prefix="/auth", version=2)
@@ -306,8 +295,7 @@ auth2 = Blueprint("auth", url_prefix="/auth", version=2)
---:1
-アプリケーションに設計図を登録すると、ルート`/v1/auth`と`/v2/auth`は個々の設計図を指すようになり、各APIバージョンのサブサイトを作成できるようになります。
-:--:1
+アプリケーションに設計図を登録すると、ルート`/v1/auth`と`/v2/auth`は個々の設計図を指すようになり、各APIバージョンのサブサイトを作成できるようになります。 :--:1 :--:1
```python
from auth_blueprints import auth1, auth2
@@ -319,8 +307,7 @@ app.blueprint(auth2)
---:1
-設計図を`BlueprintGroup`エンティティの下にグループ化し、同じ時間。
-:--:1
+設計図を`BlueprintGroup`エンティティの下にグループ化し、同じ時間。 :--:1 :--:1
```python
auth = Blueprint("auth", url_prefix="/auth")
metrics = Blueprint("metrics", url_prefix="/metrics")
@@ -334,11 +321,9 @@ group = Blueprint.group([auth, metrics], version="v1")
## 合成可能
-`Blueprint`は複数のグループに登録することができ、`BlueprintGroup`自体もそれぞれ登録してさらにネストすることができる。これにより、無限の可能性を持つ`Blueprint`コンポジションが作成されます。
+`Blueprint`は複数のグループに登録することができ、`BlueprintGroup`自体もそれぞれ登録してさらにネストすることができる。 これにより、無限の可能性を持つ`Blueprint`コンポジションが作成されます。
----:1
-この例を見て、2つのハンドラーが実際には5つの異なるルートとしてマウントされていることを確認してください。
-:--:1
+---:1 この例を見て、2つのハンドラーが実際には5つの異なるルートとしてマウントされていることを確認してください。 :--:1 :--:1
```python
app = Sanic(__name__)
blueprint_1 = Blueprint("blueprint_1", url_prefix="/bp1")
From 1077c33cce479399e48b8bc4a7c442c9ec7f74f7 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:57 +0300
Subject: [PATCH 059/776] New translations logging.md (Korean)
---
src/ko/guide/best-practices/logging.md | 89 ++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
create mode 100644 src/ko/guide/best-practices/logging.md
diff --git a/src/ko/guide/best-practices/logging.md b/src/ko/guide/best-practices/logging.md
new file mode 100644
index 0000000000..427244df96
--- /dev/null
+++ b/src/ko/guide/best-practices/logging.md
@@ -0,0 +1,89 @@
+# Logging
+
+Sanic allows you to do different types of logging (access log, error log) on the requests based on the [Python logging API](https://docs.python.org/3/howto/logging.html). You should have some basic knowledge on Python logging if you want to create a new configuration.
+
+## Quick Start
+
+---:1
+
+A simple example using default settings would be like this: :--:1
+```python
+from sanic import Sanic
+from sanic.log import logger
+from sanic.response import text
+
+app = Sanic('logging_example')
+
+@app.route('/')
+async def test(request):
+ logger.info('Here is your log')
+ return text('Hello World!')
+
+if __name__ == "__main__":
+ app.run(debug=True, access_log=True)
+```
+:---
+
+After the server is running, you should see logs like this.
+```text
+[2021-01-04 15:26:26 +0200] [1929659] [INFO] Goin' Fast @ http://127.0.0.1:8000
+[2021-01-04 15:26:26 +0200] [1929659] [INFO] Starting worker [1929659]
+```
+
+You can send a request to server and it will print the log messages.
+```text
+[2021-01-04 15:26:28 +0200] [1929659] [INFO] Here is your log
+[2021-01-04 15:26:28 +0200] - (sanic.access)[INFO][127.0.0.1:44228]: GET http://localhost:8000/ 200 -1
+```
+
+## Changing Sanic loggers
+
+To use your own logging config, simply use `logging.config.dictConfig`, or pass `log_config` when you initialize Sanic app.
+
+```python
+app = Sanic('logging_example', log_config=LOGGING_CONFIG)
+
+if __name__ == "__main__":
+ app.run(access_log=False)
+```
+
+::: tip FYI Logging in Python is a relatively cheap operation. However, if you are serving a high number of requests and performance is a concern, all of that time logging out access logs adds up and becomes quite expensive.
+
+This is a good opportunity to place Sanic behind a proxy (like nginx) and to do your access logging there. You will see a *significant* increase in overall performance by disabling the `access_log`.
+
+For optimal production performance, it is advised to run Sanic with `debug` and `access_log` disabled: `app.run(debug=False, access_log=False)` :::
+
+## Configuration
+
+Sanic's default logging configuration is: `sanic.log.LOGGING_CONFIG_DEFAULTS`.
+
+---:1 There are three loggers used in sanic, and must be defined if you want to create your own logging configuration:
+
+| **Logger Name** | **Use Case** |
+| --------------- | ------------------------------ |
+| `sanic.root` | Used to log internal messages. |
+| `sanic.error` | Used to log error logs. |
+| `sanic.access` | Used to log access logs. |
+ :--:1
+
+:---
+
+### Log format
+
+In addition to default parameters provided by Python (`asctime`, `levelname`, `message`), Sanic provides additional parameters for access logger with.
+
+| Log Context Parameter | Parameter Value | Datatype |
+| --------------------- | ------------------------------------ | -------- |
+| `host` | `request.ip` | `str` |
+| `request` | `request.method + " " + request.url` | `str` |
+| `status` | `response` | `int` |
+| `byte` | `len(response.body)` | `int` |
+
+
+
+
+The default access log format is:
+
+```text
+%(asctime)s - (%(name)s)[%(levelname)s][%(host)s]: %(request)s %(message)s %(status)d %(byte)d
+```
From c6ee5e838863fc2e2076f3759cecd85b11b16216 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:58 +0300
Subject: [PATCH 060/776] New translations logging.md (Chinese Simplified)
---
src/zh/guide/best-practices/logging.md | 52 +++++++++++---------------
1 file changed, 21 insertions(+), 31 deletions(-)
diff --git a/src/zh/guide/best-practices/logging.md b/src/zh/guide/best-practices/logging.md
index 1c13349c9c..87880f9f9a 100644
--- a/src/zh/guide/best-practices/logging.md
+++ b/src/zh/guide/best-practices/logging.md
@@ -1,15 +1,12 @@
# 日志(Logging)
-Sanic 允许您根据请求进行不同类型的记录(访问日志、错误日志)[Python 日志 API](https://docs.python.org/3/howto/logging.html)。如果您想创建一个新的配置,您应该有一些关于 Python logging 的基础知识。
+Sanic 允许您根据请求进行不同类型的记录(访问日志、错误日志)[Python 日志 API](https://docs.python.org/3/howto/logging.html)。 如果您想创建一个新的配置,您应该有一些关于 Python logging 的基础知识。
## 快速开始(Quick Start)
---:1
使用默认配置的简单示例如下:
-
-:--:1
-
```python
from sanic import Sanic
from sanic.log import logger
@@ -24,19 +21,19 @@ async def test(request):
if __name__ == "__main__":
app.run(debug=True, access_log=True)
-```
+if __name__ == "__main__":
+ app.run(debug=True, access_log=True)
+```
:---
-在服务器运行后,您应该看到以下的日志信息:
-
+After the server is running, you should see logs like this.
```text
[2021-01-04 15:26:26 +0200] [1929659] [INFO] Goin' Fast @ http://127.0.0.1:8000
[2021-01-04 15:26:26 +0200] [1929659] [INFO] Starting worker [1929659]
```
-您可以尝试向服务器发送请求,之后,您会看到输出如下的日志信息:
-
+在服务器运行后,您应该看到以下的日志信息:
```text
[2021-01-04 15:26:28 +0200] [1929659] [INFO] Here is your log
[2021-01-04 15:26:28 +0200] - (sanic.access)[INFO][127.0.0.1:44228]: GET http://localhost:8000/ 200 -1
@@ -44,7 +41,7 @@ if __name__ == "__main__":
## 自定义日志(Changing Sanic loggers)
-如果要使用自己的日志配置,只需使用 `logging.config.dictConfig`,或者在初始化 Sanic app 时传递 `log_config` 即可。
+您可以尝试向服务器发送请求,之后,您会看到输出如下的日志信息:
```python
app = Sanic('logging_example', log_config=LOGGING_CONFIG)
@@ -53,44 +50,37 @@ if __name__ == "__main__":
app.run(access_log=False)
```
-::: tip FYI 小提示
+在 Python 中处理日志是一个比较轻松的操作,但是如果您需要处理大量的请求,那么性能可能回成为一个瓶颈。 添加访问日志的耗时将会增加,这将会增大您的系统开销。
-在 Python 中处理日志是一个比较轻松的操作,但是如果您需要处理大量的请求,那么性能可能回成为一个瓶颈。添加访问日志的耗时将会增加,这将会增大您的系统开销。
+This is a good opportunity to place Sanic behind a proxy (like nginx) and to do your access logging there. You will see a *significant* increase in overall performance by disabling the `access_log`.
-使用 Nginx 记录访问日志是一个减轻系统开销的好办法,将 Sanic 部署在 Nginx 代理之后,并禁用 Sanic 的 `access_log`,您将能够看到性能的显著提升
-
-为了在生产环境下获得最佳性能,建议在禁用 `debug` 和 `access_log` 的情况下运行Sanic:`app.run(debug=False, access_log=False)`
-
-:::
+如果要使用自己的日志配置,只需使用 `logging.config.dictConfig`,或者在初始化 Sanic app 时传递 `log_config` 即可。
## 配置(Configuration)
-Sanic 的默认认知配置为:`sanic.log.LOGGING_CONFIG_DEFAULTS`。
-
----:1
+使用 Nginx 记录访问日志是一个减轻系统开销的好办法,将 Sanic 部署在 Nginx 代理之后,并禁用 Sanic 的 `access_log`,您将能够看到性能的显著提升
-Sanic 使用了三个日志器,如果您想要创建并使用自己的日志配置,则您需要自定义该配置:
+为了在生产环境下获得最佳性能,建议在禁用 `debug` 和 `access_log` 的情况下运行Sanic:`app.run(debug=False, access_log=False)`
| **Logger Name** | **Use Case** |
-|-----------------|-------------------------------|
+| --------------- | ----------------------------- |
| `sanic.root` | Used to log inernal messages. |
| `sanic.error` | Used to log error logs. |
| `sanic.access` | Used to log access logs. |
-
-:--:1
+ :--:1
:---
### 日志格式(Log format)
-除了 Python 提供的默认参数(`asctime`、`levelname`、`message`)之外,Sanic 还为日志器提供了附加参数:
+Sanic 的默认认知配置为:`sanic.log.LOGGING_CONFIG_DEFAULTS`。
-| 参数名称 | 参数值 | 参数类型 |
-|-----------------------|---------------------------------------|----------|
-| `host` | `request.ip` | `str` |
-| `request` | `request.method + " " + request.url` | `str` |
-| `status` | `response` | `int` |
-| `byte` | `len(response.body)` | `int` |
+| 参数名称 | 参数值 | 参数类型 |
+| --------- | ------------------------------------ | ----- |
+| `host` | `request.ip` | `str` |
+| `request` | `request.method + " " + request.url` | `str` |
+| `status` | `response` | `int` |
+| `byte` | `len(response.body)` | `int` |
From 12bfb325e3ff09de50ceddc21ae7aa3a5a144ca3 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:43:59 +0300
Subject: [PATCH 061/776] New translations logging.md (Portuguese, Brazilian)
---
src/pt/guide/best-practices/logging.md | 89 ++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
create mode 100644 src/pt/guide/best-practices/logging.md
diff --git a/src/pt/guide/best-practices/logging.md b/src/pt/guide/best-practices/logging.md
new file mode 100644
index 0000000000..427244df96
--- /dev/null
+++ b/src/pt/guide/best-practices/logging.md
@@ -0,0 +1,89 @@
+# Logging
+
+Sanic allows you to do different types of logging (access log, error log) on the requests based on the [Python logging API](https://docs.python.org/3/howto/logging.html). You should have some basic knowledge on Python logging if you want to create a new configuration.
+
+## Quick Start
+
+---:1
+
+A simple example using default settings would be like this: :--:1
+```python
+from sanic import Sanic
+from sanic.log import logger
+from sanic.response import text
+
+app = Sanic('logging_example')
+
+@app.route('/')
+async def test(request):
+ logger.info('Here is your log')
+ return text('Hello World!')
+
+if __name__ == "__main__":
+ app.run(debug=True, access_log=True)
+```
+:---
+
+After the server is running, you should see logs like this.
+```text
+[2021-01-04 15:26:26 +0200] [1929659] [INFO] Goin' Fast @ http://127.0.0.1:8000
+[2021-01-04 15:26:26 +0200] [1929659] [INFO] Starting worker [1929659]
+```
+
+You can send a request to server and it will print the log messages.
+```text
+[2021-01-04 15:26:28 +0200] [1929659] [INFO] Here is your log
+[2021-01-04 15:26:28 +0200] - (sanic.access)[INFO][127.0.0.1:44228]: GET http://localhost:8000/ 200 -1
+```
+
+## Changing Sanic loggers
+
+To use your own logging config, simply use `logging.config.dictConfig`, or pass `log_config` when you initialize Sanic app.
+
+```python
+app = Sanic('logging_example', log_config=LOGGING_CONFIG)
+
+if __name__ == "__main__":
+ app.run(access_log=False)
+```
+
+::: tip FYI Logging in Python is a relatively cheap operation. However, if you are serving a high number of requests and performance is a concern, all of that time logging out access logs adds up and becomes quite expensive.
+
+This is a good opportunity to place Sanic behind a proxy (like nginx) and to do your access logging there. You will see a *significant* increase in overall performance by disabling the `access_log`.
+
+For optimal production performance, it is advised to run Sanic with `debug` and `access_log` disabled: `app.run(debug=False, access_log=False)` :::
+
+## Configuration
+
+Sanic's default logging configuration is: `sanic.log.LOGGING_CONFIG_DEFAULTS`.
+
+---:1 There are three loggers used in sanic, and must be defined if you want to create your own logging configuration:
+
+| **Logger Name** | **Use Case** |
+| --------------- | ------------------------------ |
+| `sanic.root` | Used to log internal messages. |
+| `sanic.error` | Used to log error logs. |
+| `sanic.access` | Used to log access logs. |
+ :--:1
+
+:---
+
+### Log format
+
+In addition to default parameters provided by Python (`asctime`, `levelname`, `message`), Sanic provides additional parameters for access logger with.
+
+| Log Context Parameter | Parameter Value | Datatype |
+| --------------------- | ------------------------------------ | -------- |
+| `host` | `request.ip` | `str` |
+| `request` | `request.method + " " + request.url` | `str` |
+| `status` | `response` | `int` |
+| `byte` | `len(response.body)` | `int` |
+
+
+
+
+The default access log format is:
+
+```text
+%(asctime)s - (%(name)s)[%(levelname)s][%(host)s]: %(request)s %(message)s %(status)d %(byte)d
+```
From c4bd02b9c89956a6218c6b11ba9f8ed3f2ed9ee3 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:00 +0300
Subject: [PATCH 062/776] New translations testing.md (Korean)
---
src/ko/guide/best-practices/testing.md | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 src/ko/guide/best-practices/testing.md
diff --git a/src/ko/guide/best-practices/testing.md b/src/ko/guide/best-practices/testing.md
new file mode 100644
index 0000000000..a7ac6fdaf6
--- /dev/null
+++ b/src/ko/guide/best-practices/testing.md
@@ -0,0 +1,3 @@
+# Testing
+
+See [sanic-testing](../../plugins/sanic-testing/getting-started.md)
From 3acf32392de83fc879b38772590fe670a400d4f5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:02 +0300
Subject: [PATCH 063/776] New translations testing.md (Portuguese, Brazilian)
---
src/pt/guide/best-practices/testing.md | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 src/pt/guide/best-practices/testing.md
diff --git a/src/pt/guide/best-practices/testing.md b/src/pt/guide/best-practices/testing.md
new file mode 100644
index 0000000000..a7ac6fdaf6
--- /dev/null
+++ b/src/pt/guide/best-practices/testing.md
@@ -0,0 +1,3 @@
+# Testing
+
+See [sanic-testing](../../plugins/sanic-testing/getting-started.md)
From 0d48f658c2b186052a561c5bd22b41263f3d5eb5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:04 +0300
Subject: [PATCH 064/776] New translations README.md (Korean)
---
src/ko/guide/deployment/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/deployment/README.md
diff --git a/src/ko/guide/deployment/README.md b/src/ko/guide/deployment/README.md
new file mode 100644
index 0000000000..d36c65e59e
--- /dev/null
+++ b/src/ko/guide/deployment/README.md
@@ -0,0 +1 @@
+# Deployment
From c79176fa9901721dff917bc37007be78737a44b6 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:06 +0300
Subject: [PATCH 065/776] New translations blueprints.md (Korean)
---
src/ko/guide/best-practices/blueprints.md | 373 ++++++++++++++++++++++
1 file changed, 373 insertions(+)
create mode 100644 src/ko/guide/best-practices/blueprints.md
diff --git a/src/ko/guide/best-practices/blueprints.md b/src/ko/guide/best-practices/blueprints.md
new file mode 100644
index 0000000000..1070c85673
--- /dev/null
+++ b/src/ko/guide/best-practices/blueprints.md
@@ -0,0 +1,373 @@
+# Blueprints
+
+## Overview
+
+Blueprints are objects that can be used for sub-routing within an application. Instead of adding routes to the application instance, blueprints define similar methods for adding routes, which are then registered with the application in a flexible and pluggable manner.
+
+Blueprints are especially useful for larger applications, where your application logic can be broken down into several groups or areas of responsibility.
+
+## Creating and registering
+
+---:1
+
+First, you must create a blueprint. It has a very similar API as the `Sanic()` app instance with many of the same decorators. :--:1
+```python
+# ./my_blueprint.py
+from sanic.response import json
+from sanic import Blueprint
+
+bp = Blueprint("my_blueprint")
+
+@bp.route("/")
+async def bp_root(request):
+ return json({"my": "blueprint"})
+```
+:---
+
+
+---:1
+
+Next, you register it with the app instance. :--:1
+```python
+from sanic import Sanic
+from my_blueprint import bp
+
+app = Sanic(__name__)
+app.blueprint(bp)
+```
+:---
+
+Blueprints also have the same `websocket()` decorator and `add_websocket_route` method for implementing websockets.
+
+---:1
+
+Beginning in v21.12, a Blueprint may be registered before or after adding objects to it. Previously, only objects attached to the Blueprint at the time of registration would be loaded into application instance. :--:1
+```python
+app.blueprint(bp)
+
+@bp.route("/")
+async def bp_root(request):
+ ...
+```
+:---
+## Copying
+
+---:1
+
+Blueprints along with everything that is attached to them can be copied to new instances using the `copy()` method. The only required argument is to pass it a new `name`. However, you could also use this to override any of the values from the old blueprint.
+
+:--:1
+
+```python
+v1 = Blueprint("Version1", version=1)
+
+@v1.route("/something")
+def something(request):
+ pass
+
+v2 = v1.copy("Version2", version=2)
+
+app.blueprint(v1)
+app.blueprint(v2)
+```
+
+```
+Available routes:
+/v1/something
+/v2/something
+
+```
+
+:---
+
+## Blueprint groups
+
+Blueprints may also be registered as part of a list or tuple, where the registrar will recursively cycle through any sub-sequences of blueprints and register them accordingly. The Blueprint.group method is provided to simplify this process, allowing a ‘mock’ backend directory structure mimicking what’s seen from the front end. Consider this (quite contrived) example:
+
+```text
+api/
+├──content/
+│ ├──authors.py
+│ ├──static.py
+│ └──__init__.py
+├──info.py
+└──__init__.py
+app.py
+```
+
+---:1
+
+#### First blueprint
+
+:--:1
+```python
+# api/content/authors.py
+from sanic import Blueprint
+
+authors = Blueprint("content_authors", url_prefix="/authors")
+```
+:---
+
+---:1
+
+#### Second blueprint
+
+:--:1
+```python
+# api/content/static.py
+from sanic import Blueprint
+
+static = Blueprint("content_static", url_prefix="/static")
+```
+:---
+
+---:1
+
+#### Blueprint group
+
+:--:1
+```python
+# api/content/__init__.py
+from sanic import Blueprint
+from .static import static
+from .authors import authors
+
+content = Blueprint.group(static, authors, url_prefix="/content")
+```
+:---
+
+---:1
+
+#### Third blueprint
+
+:--:1
+```python
+# api/info.py
+from sanic import Blueprint
+
+info = Blueprint("info", url_prefix="/info")
+```
+:---
+
+---:1
+
+#### Another blueprint group
+
+:--:1
+```python
+# api/__init__.py
+from sanic import Blueprint
+from .content import content
+from .info import info
+
+api = Blueprint.group(content, info, url_prefix="/api")
+```
+:---
+
+---:1
+
+#### Main server
+
+All blueprints are now registered
+
+:--:1
+```python
+# app.py
+from sanic import Sanic
+from .api import api
+
+app = Sanic(__name__)
+app.blueprint(api)
+```
+:---
+
+## Middleware
+
+---:1
+
+Blueprints can also have middleware that is specifically registered for its endpoints only. :--:1
+```python
+@bp.middleware
+async def print_on_request(request):
+ print("I am a spy")
+
+@bp.middleware("request")
+async def halt_request(request):
+ return text("I halted the request")
+
+@bp.middleware("response")
+async def halt_response(request, response):
+ return text("I halted the response")
+```
+:---
+
+---:1
+
+Similarly, using blueprint groups, it is possible to apply middleware to an entire group of nested blueprints. :--:1
+```python
+bp1 = Blueprint("bp1", url_prefix="/bp1")
+bp2 = Blueprint("bp2", url_prefix="/bp2")
+
+@bp1.middleware("request")
+async def bp1_only_middleware(request):
+ print("applied on Blueprint : bp1 Only")
+
+@bp1.route("/")
+async def bp1_route(request):
+ return text("bp1")
+
+@bp2.route("/")
+async def bp2_route(request, param):
+ return text(param)
+
+group = Blueprint.group(bp1, bp2)
+
+@group.middleware("request")
+async def group_middleware(request):
+ print("common middleware applied for both bp1 and bp2")
+
+# Register Blueprint group under the app
+app.blueprint(group)
+```
+:---
+
+## Exceptions
+
+---:1
+
+Just like other [exception handling](./exceptions.md), you can define blueprint specific handlers. :--:1
+```python
+@bp.exception(NotFound)
+def ignore_404s(request, exception):
+ return text("Yep, I totally found the page: {}".format(request.url))
+```
+:---
+
+## Static files
+
+---:1
+
+Blueprints can also have their own static handlers :--:1
+```python
+bp = Blueprint("bp", url_prefix="/bp")
+bp.static("/web/path", "/folder/to/serve")
+bp.static("/web/path", "/folder/to/server", name="uploads")
+```
+:---
+
+---:1
+
+Which can then be retrieved using `url_for()`. See [routing](/guide/basics/routing.md) for more information. :--:1
+```python
+>>> print(app.url_for("static", name="bp.uploads", filename="file.txt"))
+'/bp/web/path/file.txt'
+```
+:---
+
+## Listeners
+
+---:1
+
+Blueprints can also implement [listeners](/guide/basics/listeners.md). :--:1
+```python
+@bp.listener("before_server_start")
+async def before_server_start(app, loop):
+ ...
+
+@bp.listener("after_server_stop")
+async def after_server_stop(app, loop):
+ ...
+```
+:---
+
+## Versioning
+
+As discussed in the [versioning section](/guide/advanced/versioning.md), blueprints can be used to implement different versions of a web API.
+
+---:1
+
+The `version` will be prepended to the routes as `/v1` or `/v2`, etc. :--:1
+```python
+auth1 = Blueprint("auth", url_prefix="/auth", version=1)
+auth2 = Blueprint("auth", url_prefix="/auth", version=2)
+```
+:---
+
+---:1
+
+When we register our blueprints on the app, the routes `/v1/auth` and `/v2/auth` will now point to the individual blueprints, which allows the creation of sub-sites for each API version. :--:1
+```python
+from auth_blueprints import auth1, auth2
+
+app = Sanic(__name__)
+app.blueprint(auth1)
+app.blueprint(auth2)
+```
+:---
+
+---:1
+
+It is also possible to group the blueprints under a `BlueprintGroup` entity and version multiple of them together at the same time. :--:1
+```python
+auth = Blueprint("auth", url_prefix="/auth")
+metrics = Blueprint("metrics", url_prefix="/metrics")
+
+group = Blueprint.group(auth, metrics, version="v1")
+
+# This will provide APIs prefixed with the following URL path
+# /v1/auth/ and /v1/metrics
+```
+:---
+
+## Composable
+
+A `Blueprint` may be registered to multiple groups, and each of `BlueprintGroup` itself could be registered and nested further. This creates a limitless possibility `Blueprint` composition.
+
+---:1 Take a look at this example and see how the two handlers are actually mounted as five (5) distinct routes. :--:1
+```python
+app = Sanic(__name__)
+blueprint_1 = Blueprint("blueprint_1", url_prefix="/bp1")
+blueprint_2 = Blueprint("blueprint_2", url_prefix="/bp2")
+group = Blueprint.group(
+ blueprint_1,
+ blueprint_2,
+ version=1,
+ version_prefix="/api/v",
+ url_prefix="/grouped",
+ strict_slashes=True,
+)
+primary = Blueprint.group(group, url_prefix="/primary")
+
+
+@blueprint_1.route("/")
+def blueprint_1_default_route(request):
+ return text("BP1_OK")
+
+
+@blueprint_2.route("/")
+def blueprint_2_default_route(request):
+ return text("BP2_OK")
+
+
+app.blueprint(group)
+app.blueprint(primary)
+app.blueprint(blueprint_1)
+
+# The mounted paths:
+# /api/v1/grouped/bp1/
+# /api/v1/grouped/bp2/
+# /api/v1/primary/grouped/bp1
+# /api/v1/primary/grouped/bp2
+# /bp1
+
+```
+:---
+
+
+## Generating a URL
+
+When generating a url with `url_for()`, the endpoint name will be in the form:
+
+```text
+{blueprint_name}.{handler_name}
+```
From 779338c0ef976d842f9c80df2baef604facb400f Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:07 +0300
Subject: [PATCH 066/776] New translations README.md (Portuguese, Brazilian)
---
src/pt/guide/best-practices/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/best-practices/README.md
diff --git a/src/pt/guide/best-practices/README.md b/src/pt/guide/best-practices/README.md
new file mode 100644
index 0000000000..874ca7f3c6
--- /dev/null
+++ b/src/pt/guide/best-practices/README.md
@@ -0,0 +1 @@
+# Best Practices
From f8ee5f1cf3855c086f4a464e43611a9a9c9262f1 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:07 +0300
Subject: [PATCH 067/776] New translations listeners.md (Portuguese, Brazilian)
---
src/pt/guide/basics/listeners.md | 226 +++++++++++++++++++++++++++++++
1 file changed, 226 insertions(+)
create mode 100644 src/pt/guide/basics/listeners.md
diff --git a/src/pt/guide/basics/listeners.md b/src/pt/guide/basics/listeners.md
new file mode 100644
index 0000000000..c524e11121
--- /dev/null
+++ b/src/pt/guide/basics/listeners.md
@@ -0,0 +1,226 @@
+# Listeners
+
+Sanic provides you with eight (8) opportunities to inject an operation into the life cycle of your application server. This does not include the [signals](../advanced/signals.md), which allow further injection customization.
+
+There are two (2) that run **only** on your main Sanic process (ie, once per call to `sanic server.app`.)
+
+- `main_process_start`
+- `main_process_stop`
+
+There are also two (2) that run **only** in a reloader process if auto-reload has been turned on.
+
+- `reload_process_start`
+- `reload_process_stop`
+
+*Added `reload_process_start` and `reload_process_stop` in v22.3*
+
+There are four (4) that enable you to execute startup/teardown code as your server starts or closes.
+
+- `before_server_start`
+- `after_server_start`
+- `before_server_stop`
+- `after_server_stop`
+
+The life cycle of a worker process looks like this:
+
+```mermaid
+sequenceDiagram
+autonumber
+participant Process
+participant Worker
+participant Listener
+participant Handler
+Note over Process: sanic server.app
+loop
+ Process->>Listener: @app.main_process_start
+ Listener->>Handler: Invoke event handler
+end
+Process->>Worker: Run workers
+loop Start each worker
+ loop
+ Worker->>Listener: @app.before_server_start
+ Listener->>Handler: Invoke event handler
+ end
+ Note over Worker: Server status: started
+ loop
+ Worker->>Listener: @app.after_server_start
+ Listener->>Handler: Invoke event handler
+ end
+ Note over Worker: Server status: ready
+end
+Process->>Worker: Graceful shutdown
+loop Stop each worker
+ loop
+ Worker->>Listener: @app.before_server_stop
+ Listener->>Handler: Invoke event handler
+ end
+ Note over Worker: Server status: stopped
+ loop
+ Worker->>Listener: @app.after_server_stop
+ Listener->>Handler: Invoke event handler
+ end
+ Note over Worker: Server status: closed
+end
+loop
+ Process->>Listener: @app.main_process_stop
+ Listener->>Handler: Invoke event handler
+end
+Note over Process: exit
+```
+
+The reloader process live outside of this worker process inside of a process that is responsible for starting and stopping the Sanic processes. Consider the following example:
+
+```python
+@app.reload_process_start
+async def reload_start(*_):
+ print(">>>>>> reload_start <<<<<<")
+
+
+@app.main_process_start
+async def main_start(*_):
+ print(">>>>>> main_start <<<<<<")
+```
+
+If this application were run with auto-reload turned on, the `reload_start` function would be called once. This is contrasted with `main_start`, which would be run every time a file is save and the reloader restarts the applicaition process.
+
+## Attaching a listener
+
+---:1
+
+The process to setup a function as a listener is similar to declaring a route.
+
+The currently running `Sanic()` instance is injected into the listener. :--:1
+```python
+async def setup_db(app):
+ app.ctx.db = await db_setup()
+
+app.register_listener(setup_db, "before_server_start")
+```
+:---
+
+---:1
+
+The `Sanic` app instance also has a convenience decorator. :--:1
+```python
+@app.listener("before_server_start")
+async def setup_db(app):
+ app.ctx.db = await db_setup()
+```
+:---
+
+---:1 Prior to v22.3, both the application instance and the current event loop were injected into the function. However, only the application instance is injected by default. If your function signature will accept both, then both the application and the loop will be injected as shown here. :--:1
+```python
+@app.listener("before_server_start")
+async def setup_db(app, loop):
+ app.ctx.db = await db_setup()
+```
+:---
+
+---:1
+
+You can shorten the decorator even further. This is helpful if you have an IDE with autocomplete.
+
+:--:1
+```python
+@app.before_server_start
+async def setup_db(app):
+ app.ctx.db = await db_setup()
+```
+:---
+
+## Order of execution
+
+Listeners are executed in the order they are declared during startup, and reverse order of declaration during teardown
+
+| | Phase | Order |
+| --------------------- | --------------- | ---------------------------- |
+| `main_process_start` | main startup | regular :smiley: |
+| `before_server_start` | worker startup | regular :smiley: |
+| `after_server_start` | worker startup | regular :smiley: |
+| `before_server_stop` | worker shutdown | reverse :upside_down_face: |
+| `after_server_stop` | worker shutdown | reverse :upside_down_face: |
+| `main_process_stop` | main shutdown | reverse :upside_down_face: |
+
+Given the following setup, we should expect to see this in the console if we run two workers.
+
+---:1
+
+```python
+@app.listener("before_server_start")
+async def listener_1(app, loop):
+ print("listener_1")
+
+@app.before_server_start
+async def listener_2(app, loop):
+ print("listener_2")
+
+@app.listener("after_server_start")
+async def listener_3(app, loop):
+ print("listener_3")
+
+@app.after_server_start
+async def listener_4(app, loop):
+ print("listener_4")
+
+@app.listener("before_server_stop")
+async def listener_5(app, loop):
+ print("listener_5")
+
+@app.before_server_stop
+async def listener_6(app, loop):
+ print("listener_6")
+
+@app.listener("after_server_stop")
+async def listener_7(app, loop):
+ print("listener_7")
+
+@app.after_server_stop
+async def listener_8(app, loop):
+ print("listener_8")
+```
+:--:1
+```bash{3-7,13,19-22}
+[pid: 1000000] [INFO] Goin' Fast @ http://127.0.0.1:9999
+[pid: 1000000] [INFO] listener_0
+[pid: 1111111] [INFO] listener_1
+[pid: 1111111] [INFO] listener_2
+[pid: 1111111] [INFO] listener_3
+[pid: 1111111] [INFO] listener_4
+[pid: 1111111] [INFO] Starting worker [1111111]
+[pid: 1222222] [INFO] listener_1
+[pid: 1222222] [INFO] listener_2
+[pid: 1222222] [INFO] listener_3
+[pid: 1222222] [INFO] listener_4
+[pid: 1222222] [INFO] Starting worker [1222222]
+[pid: 1111111] [INFO] Stopping worker [1111111]
+[pid: 1222222] [INFO] Stopping worker [1222222]
+[pid: 1222222] [INFO] listener_6
+[pid: 1222222] [INFO] listener_5
+[pid: 1222222] [INFO] listener_8
+[pid: 1222222] [INFO] listener_7
+[pid: 1111111] [INFO] listener_6
+[pid: 1111111] [INFO] listener_5
+[pid: 1111111] [INFO] listener_8
+[pid: 1111111] [INFO] listener_7
+[pid: 1000000] [INFO] listener_9
+[pid: 1000000] [INFO] Server Stopped
+```
+In the above example, notice how there are three processes running:
+
+- `pid: 1000000` - The *main* process
+- `pid: 1111111` - Worker 1
+- `pid: 1222222` - Worker 2
+
+*Just because our example groups all of one worker and then all of another, in reality since these are running on separate processes, the ordering between processes is not guaranteed. But, you can be sure that a single worker will **always** maintain its order.* :---
+
+
+::: tip FYI The practical result of this is that if the first listener in `before_server_start` handler setups a database connection, listeners that are registered after it can rely upon that connection being alive both when they are started and stopped. :::
+
+## ASGI Mode
+
+If you are running your application with an ASGI server, then make note of the following changes:
+
+- `reload_process_start` and `reload_process_stop` will be **ignored**
+- `main_process_start` and `main_process_stop` will be **ignored**
+- `before_server_start` will run as early as it can, and will be before `after_server_start`, but technically, the server is already running at that point
+- `after_server_stop` will run as late as it can, and will be after `before_server_stop`, but technically, the server is still running at that point
From 188cf66814d363b9f54146a005df47b3a3e7d4e9 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:09 +0300
Subject: [PATCH 068/776] New translations response.md (Chinese Simplified)
---
src/zh/guide/basics/response.md | 106 ++++++--------------------------
1 file changed, 20 insertions(+), 86 deletions(-)
diff --git a/src/zh/guide/basics/response.md b/src/zh/guide/basics/response.md
index 33d6427378..3dc1fb7671 100644
--- a/src/zh/guide/basics/response.md
+++ b/src/zh/guide/basics/response.md
@@ -12,8 +12,6 @@ Sanic 内置了 9 种常用的返回类型,您可以通过以下方式中的
**响应类型**: `text/plain; charset=utf-8`
-**响应说明**: 返回纯文本内容。
-
```python
from sanic.response import text
@@ -21,15 +19,10 @@ from sanic.response import text
async def handler(request):
return text("Hi 😎")
```
+**响应说明**: 返回纯文本内容。
:::
-::: tab HTML
-
-**响应类型**: `text/html; charset=utf-8`
-
-**响应说明**: 返回 HTML 文档
-
```python
from sanic.response import html
@@ -37,14 +30,9 @@ from sanic.response import html
async def handler(request):
return html('
Hi 😎
')
```
+::: tab HTML
-:::
-
-::: tab JSON
-
-**响应类型**: `application/json`
-
-**响应说明**: 返回 JSON 内容
+**响应类型**: `text/html; charset=utf-8`
```python
from sanic.response import json
@@ -54,7 +42,7 @@ async def handler(request):
return json({"foo": "bar"})
```
-在默认情况下, Sanic 使用 [`ujson`](https://github.com/ultrajson/ultrajson) 作为 JSON 编码器, 更改此配置非常简单,只需如下操作:
+在默认情况下, Sanic 使用 [`ujson`](https://github.com/ultrajson/ultrajson) 作为 JSON 编码器, 更改此配置非常简单,只需如下操作: It is super simple to change this if you want.
```python
from orjson import dumps
@@ -62,23 +50,19 @@ from orjson import dumps
json({"foo": "bar"}, dumps=dumps)
```
-如果没有安装 `ujson` , 它就会使用 Python 自带的 `json` 模块。
+:::
-您可以在应用初始化时申明全局的 Json 序列化函数:
+::: tab JSON
```python
from orjson import dumps
app = Sanic(..., dumps=dumps)
```
+**响应类型**: `application/json`
-:::
-
-::: tab File
-
-**响应类型**: N/A
+**响应说明**: 返回 JSON 内容
-**响应说明**: 返回一个文件
```python
from sanic.response import file
@@ -88,54 +72,21 @@ async def handler(request):
return await file("/path/to/whatever.png")
```
-Sanic 将会自动检查文件,并猜测其可能的 mine 类型,并且为响应类型设置合适的值。
-
-如果您愿意指定响应类型,只需如下操作:
+Sanic will examine the file, and try and guess its mime type and use an appropriate value for the content type. You could be explicit, if you would like:
```python
file("/path/to/whatever.png", mime_type="image/png")
```
-您也可以选择重命名文件:
+如果没有安装 `ujson` , 它就会使用 Python 自带的 `json` 模块。
```python
file("/path/to/whatever.png", filename="super-awesome-incredible.png")
```
+您可以在应用初始化时申明全局的 Json 序列化函数:
:::
-::: tab Streaming
-
-**响应类型**: `text/plain; charset=utf-8`
-
-**响应说明**: 数据流到客户端
-
-```python
-from sanic.response import stream
-
-@app.route("/")
-async def handler(request):
- return stream(streaming_fn)
-
-async def streaming_fn(response):
- await response.write('foo')
- await response.write('bar')
-```
-
-默认情况下,如果客户端支持,Sanic 将使用分块编码传输到客户端。 您可以禁用此功能:
-
-```python
-stream(streaming_fn, chunked=False)
-```
-
-:::
-
-::: tab "File Streaming"
-
-**响应类型**: N/A
-
-**响应说明**: 将文件流传输到客户端,在传输大文件(例如视频)的时候非常有用:
-
```python
from sanic.response import file_stream
@@ -144,15 +95,9 @@ async def handler(request):
return await file_stream("/path/to/whatever.mp4")
```
-和 `file()` 一样,`file_stream()` 也将主动确定您的 mine 类型,并为响应类型进行自动设置。
-
-:::
-
-::: tab Raw
+Like the `file()` method, `file_stream()` will attempt to determine the mime type of the file. ::: tab File
-**响应类型**: `application/octet-stream`
-
-**响应说明**: 发送未进行编码的原始字节。
+**响应类型**: N/A
```python
from sanic.response import raw
@@ -161,14 +106,9 @@ from sanic.response import raw
async def handler(request):
return raw(b"raw bytes")
```
+**响应说明**: 返回一个文件
-:::
-
-::: tab Redirect
-
-**响应类型**: `text/html; charset=utf-8`
-
-**响应说明**: 发送状态码 `302` 以将客户端重定向到其他路由
+Sanic 将会自动检查文件,并猜测其可能的 mine 类型,并且为响应类型设置合适的值。
```python
from sanic.response import redirect
@@ -178,13 +118,9 @@ async def handler(request):
return redirect("/login")
```
-:::
-
-::: tab Empty
-
-**响应类型**: N/A
+如果您愿意指定响应类型,只需如下操作:
-**响应说明**: 用于响应定义的空消息,遵循 [RFC 2616](https://tools.ietf.org/search/rfc2616#section-7.2.1)
+您也可以选择重命名文件:
```python
from sanic.response import empty
@@ -194,15 +130,13 @@ async def handler(request):
return empty()
```
-默认返回状态码 `204`
-
-:::
-
+默认返回状态码 `204` :::
::::
## 默认状态码(Default Status)
-响应的默认 HTTP 状态码是 `200`,如果您需要更改状态码,可以通过下面的方式进行更改:
+响应的默认 HTTP 状态码是 `200`,如果您需要更改状态码,可以通过下面的方式进行更改: If you need to change it, it can be done by the response method.
+
```python
@app.post("/")
From 60a32961d53b30597e8d7f94b8f8de6bebf2f033 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:10 +0300
Subject: [PATCH 069/776] New translations middleware.md (Japanese)
---
src/ja/guide/basics/middleware.md | 30 ++++++++++--------------------
1 file changed, 10 insertions(+), 20 deletions(-)
diff --git a/src/ja/guide/basics/middleware.md b/src/ja/guide/basics/middleware.md
index da8f1449be..060b7adf71 100644
--- a/src/ja/guide/basics/middleware.md
+++ b/src/ja/guide/basics/middleware.md
@@ -32,8 +32,7 @@ Note over Worker: Deliver response
---:1
-これはもう見慣れたものになっているはずです。必要なのは、 「リクエスト」 または 「レスポンス」 のどちらでミドルウェアを実行するかを宣言することだけです。
-:--:1
+これはもう見慣れたものになっているはずです。 All you need to do is declare when you would like the middleware to execute: on the `request` or on the `response`. :--:1
```python
async def extract_user(request):
request.ctx.user = await extract_user_from_request(request)
@@ -44,8 +43,7 @@ app.register_middleware(extract_user, "request")
---:1
-ここでも、`Sanic`アプリインスタンスには便利なデコレーターもある。
-:--:1
+ここでも、`Sanic`アプリインスタンスには便利なデコレーターもある。 :--:1 :--:1
```python
@app.middleware("request")
async def extract_user(request):
@@ -55,8 +53,7 @@ async def extract_user(request):
---:1
-レスポンス・ミドルウェアは`request`と`response`の両方の引数を受け取ります。
-:--:1
+レスポンス・ミドルウェアは`request`と`response`の両方の引数を受け取ります。 :--:1 :--:1
```python
@app.middleware('response')
async def prevent_xss(request, response):
@@ -66,8 +63,7 @@ async def prevent_xss(request, response):
---:1
-デコレーターをさらに短くすることができます。これは、オートコンプリート機能を備えたIDEがある場合に便利です。
-:--:1
+デコレーターをさらに短くすることができます。 これは、オートコンプリート機能を備えたIDEがある場合に便利です。 :--:1 :--:1
```python
@app.on_request
async def extract_user(request):
@@ -90,8 +86,7 @@ async def prevent_xss(request, response):
1. Request middleware: `add_key`
2. Route handler: `index`
3. Response middleware: `prevent_xss`
-4. Response middleware: `custom_banner`
-:--:1
+4. Response middleware: `custom_banner` :--:1
```python
@app.middleware("request")
async def add_key(request):
@@ -117,9 +112,7 @@ async def index(request):
:---
----:1
-`request.match_info`を変更できます。たとえば、ミドルウェアで`a-slug`を`a_slug`に変換するために使用できる便利な機能。
-:--:1
+---:1 `request.match_info`を変更できます。 たとえば、ミドルウェアで`a-slug`を`a_slug`に変換するために使用できる便利な機能。 :--:1 :--:1
```python
@app.on_request
def convert_slug_to_underscore(request: Request):
@@ -139,12 +132,9 @@ foo_bar_baz
---:1
-ミドルウェアが`HTTPResponse`オブジェクトを返す場合、リクエストは処理を停止し、レスポンスが返されます。これがルートハンドラに到達する前のリクエストで発生した場合、ハンドラは**not**呼び出されます。レスポンスを返すと、それ以降のミドルウェアの実行も妨げられます。
+ミドルウェアが`HTTPResponse`オブジェクトを返す場合、リクエストは処理を停止し、レスポンスが返されます。 これがルートハンドラに到達する前のリクエストで発生した場合、ハンドラは**not**呼び出されます。 レスポンスを返すと、それ以降のミドルウェアの実行も妨げられます。
-::: tip
-`None`値を返すと、ミドルウェアハンドラの実行を停止して、リクエストを通常どおりに処理できます。これは、アーリー・リターンを使用して、そのミドルウェア・ハンドラー内の要求の処理を回避する場合に便利です。
-:::
-:--:1
+::: tip `None`値を返すと、ミドルウェアハンドラの実行を停止して、リクエストを通常どおりに処理できます。 This can be useful when using early return to avoid processing requests inside of that middleware handler. ::: :--:1
```python
@app.middleware("request")
async def halt_request(request):
@@ -158,7 +148,7 @@ async def halt_response(request, response):
#### Order of execution
-リクエスト・ミドルウェアは、宣言された順序で実行されます。レスポンス・ミドルウェアは、**逆順で実行されます**.
+リクエスト・ミドルウェアは、宣言された順序で実行されます。 レスポンス・ミドルウェアは、**逆順で実行されます**.
次の設定では、コンソールにこのメッセージが表示されます。
@@ -183,7 +173,7 @@ async def middleware_3(request, response):
@app.middleware("response")
async def middleware_4(request, response):
print("middleware_4")
-
+
@app.get("/handler")
async def handler(request):
print("~ handler ~")
From 86c3c59a6eba60d833f19dbfe089bb566568b6b3 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:11 +0300
Subject: [PATCH 070/776] New translations middleware.md (Korean)
---
src/ko/guide/basics/middleware.md | 30 +++++++-----------------------
1 file changed, 7 insertions(+), 23 deletions(-)
diff --git a/src/ko/guide/basics/middleware.md b/src/ko/guide/basics/middleware.md
index 8b56a7ee1e..85f4d2f20a 100644
--- a/src/ko/guide/basics/middleware.md
+++ b/src/ko/guide/basics/middleware.md
@@ -32,9 +32,7 @@ Note over Worker: Deliver response
---:1
-이것은 아마 지금쯤 친숙해 보일 것입니다. 당신이 해야 할 일은 미들웨어가 실행되기를 원하는 때를 선언하는 것뿐입니다: `request` 또는 `response`.
-
-:--:1
+이것은 아마 지금쯤 친숙해 보일 것입니다. 당신이 해야 할 일은 미들웨어가 실행되기를 원하는 때를 선언하는 것뿐입니다: `request` 또는 `response`. :--:1
```python
async def extract_user(request):
request.ctx.user = await extract_user_from_request(request)
@@ -45,9 +43,7 @@ app.register_middleware(extract_user, "request")
---:1
-다시 말하지만, `Sanic` 앱 인스턴스에는 편리한 데코레이터도 있습니다.
-
-:--:1
+다시 말하지만, `Sanic` 앱 인스턴스에는 편리한 데코레이터도 있습니다. :--:1
```python
@app.middleware("request")
async def extract_user(request):
@@ -57,9 +53,7 @@ async def extract_user(request):
---:1
-응답 미들웨어는 `request` 및 `response` 인수를 모두 받습니다.
-
-:--:1
+응답 미들웨어는 `request` 및 `response` 인수를 모두 받습니다. :--:1
```python
@app.middleware('response')
async def prevent_xss(request, response):
@@ -69,9 +63,7 @@ async def prevent_xss(request, response):
---:1
-데코레이터를 더 줄일 수 있습니다. 이는 자동 완성 기능이 있는 IDE가 있는 경우에 유용합니다.
-:::
-:--:1
+데코레이터를 더 줄일 수 있습니다. 이는 자동 완성 기능이 있는 IDE가 있는 경우에 유용합니다. ::: :--:1
```python
@app.on_request
async def extract_user(request):
@@ -91,13 +83,10 @@ async def prevent_xss(request, response):
#### 실행 순서(Order of execution)
-
1. 미들웨어 요청: `add_key`
2. 라우트 핸들러: `index`
3. 응답 미들웨어: `prevent_xss`
4. 응답 미들웨어: `custom_banner`
-
-:--:1
```python
@app.middleware("request")
async def add_key(request):
@@ -123,11 +112,7 @@ async def index(request):
:---
----:1
-
-`request.match_info`를 수정할 수 있습니다. 예를 들어 미들웨어에서 `a-slug`를 `a_slug`로 변환하는 데 사용할 수 있는 유용한 기능입니다.
-
-:--:1
+`request.match_info`를 수정할 수 있습니다. 예를 들어 미들웨어에서 `a-slug`를 `a_slug`로 변환하는 데 사용할 수 있는 유용한 기능입니다. :--:1
```python
@app.on_request
def convert_slug_to_underscore(request: Request):
@@ -149,7 +134,7 @@ foo_bar_baz
미들웨어가 `HTTPResponse` 객체를 반환하면 요청 처리가 중지되고 응답이 반환됩니다. 라우트 핸들러에 도달하기 전에 요청에 이 문제가 발생하면 핸들러가 호출되지 **않습니다**. 응답을 반환하면 더 이상 미들웨어가 실행되지 않습니다.
-:--:1
+::: tip You can return a `None` value to stop the execution of the middleware handler to allow the request to process as normal. This can be useful when using early return to avoid processing requests inside of that middleware handler. ::: :--:1
```python
@app.middleware("request")
async def halt_request(request):
@@ -163,7 +148,6 @@ async def halt_response(request, response):
#### 실행 순서(Order of execution)
-
요청 미들웨어는 선언된 순서대로 실행됩니다. 응답 미들웨어는 **역순**으로 실행됩니다.
다음 설정이 주어지면 콘솔에서 이를 볼 수 있을 것으로 예상해야 합니다
@@ -189,7 +173,7 @@ async def middleware_3(request, response):
@app.middleware("response")
async def middleware_4(request, response):
print("middleware_4")
-
+
@app.get("/handler")
async def handler(request):
print("~ handler ~")
From 6341f467bb33f11e3b2a96e1c2aac074fc3981a2 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:12 +0300
Subject: [PATCH 071/776] New translations middleware.md (Chinese Simplified)
---
src/zh/guide/basics/middleware.md | 62 ++++++++-----------------------
1 file changed, 15 insertions(+), 47 deletions(-)
diff --git a/src/zh/guide/basics/middleware.md b/src/zh/guide/basics/middleware.md
index 8ff9abc069..beae282ff9 100644
--- a/src/zh/guide/basics/middleware.md
+++ b/src/zh/guide/basics/middleware.md
@@ -28,58 +28,42 @@ loop
end
Note over 子程序: 返回响应
```
-
## 启用(Attaching middleware)
---:1
-这看起来和之前的流程没有什么不同,您需要做的就是完成响应函数的构建,并将其挂载到 `request` 或 `response` 上
-
-:--:1
-
+This should probably look familiar by now. All you need to do is declare when you would like the middleware to execute: on the `request` or on the `response`. :--:1
```python
async def extract_user(request):
request.ctx.user = await extract_user_from_request(request)
app.register_middleware(extract_user, "request")
```
-
:---
---:1
-同样, 中间件一样支持使用装饰器进行挂载。
-
-:--:1
-
+Again, the `Sanic` app instance also has a convenience decorator. :--:1
```python
@app.middleware("request")
async def extract_user(request):
request.ctx.user = await extract_user_from_request(request)
```
-
:---
---:1
-响应中间件需要同时接收 `request` 和 `response` 两个参数
-
-:--:1
-
+响应中间件需要同时接收 `request` 和 `response` 两个参数 :--:1
```python
@app.middleware('response')
async def prevent_xss(request, response):
response.headers["x-xss-protection"] = "1; mode=block"
```
-
:---
---:1
-您可以进一步缩短该装饰器的调用代码。如果您的 IDE 有自动补全的话会很方便。
-
-:--:1
-
+您可以进一步缩短该装饰器的调用代码。 如果您的 IDE 有自动补全的话会很方便。 :--:1
```python
@app.on_request
async def extract_user(request):
@@ -88,8 +72,11 @@ async def extract_user(request):
@app.on_response
async def prevent_xss(request, response):
...
-```
+@app.on_response
+async def prevent_xss(request, response):
+ ...
+```
:---
## 变更(Modification)
@@ -100,15 +87,10 @@ async def prevent_xss(request, response):
#### 执行顺序(Order of execution)
-
-
1. 请求中间件:`add_key`
2. 响应函数:`index`
3. 响应中间件:`prevent_xss`
4. 响应中间件:`custom_banner`
-
-:--:1
-
```python
@app.middleware("request")
async def add_key(request):
@@ -131,15 +113,10 @@ async def index(request):
return text(request.ctx.foo)
```
-
:---
----:1
-
-您可以修改 `request.match_info`。这个功能可能很有用,比如下面这个例子中,在中间件里将 `a-slug` 改变为 `a_slug`。
-
-:--:1
+您可以修改 `request.match_info`。 这个功能可能很有用,比如下面这个例子中,在中间件里将 `a-slug` 改变为 `a_slug`。 :--:1
```python
@app.on_request
def convert_slug_to_underscore(request: Request):
@@ -154,17 +131,14 @@ async def handler(request, slug):
$ curl localhost:9999/foo-bar-baz
foo_bar_baz
```
-
:---
-
## 提前响应(Resonding early)
---:1
-如果中间件返回了一个 `HTTPResponse` 对象, 那么请求将会终止,此对象将会作为最终响应进行返回。如果此操作发生在响应函数之前,那么响应函数将不会被调用。除此之外,此操作同样不会调用该中间件之后的其他中间件。
-
-:--:1
+如果中间件返回了一个 `HTTPResponse` 对象, 那么请求将会终止,此对象将会作为最终响应进行返回。 如果此操作发生在响应函数之前,那么响应函数将不会被调用。 除此之外,此操作同样不会调用该中间件之后的其他中间件。
+::: tip 您可以返回 `None` 值来跳过某个中间件的执行,如果这样的话将不影响后续中间件的执行。 您可以将这个特性用于在提前响应中中间件的选择性执行。 :::
```python
@app.middleware("request")
async def halt_request(request):
@@ -174,16 +148,13 @@ async def halt_request(request):
async def halt_response(request, response):
return text("I halted the response")
```
-
-::: tip
-您可以返回 `None` 值来跳过某个中间件的执行,如果这样的话将不影响后续中间件的执行。您可以将这个特性用于在提前响应中中间件的选择性执行。
-:::
-
:---
#### 执行顺序(Order of execution)
-请求中间件按照声明的顺序执行。响应中间件按照声明顺序的 **逆序** 执行。 在此示例中,我们可以在控制台看到如下的输出顺序。
+请求中间件按照声明的顺序执行。 响应中间件按照声明顺序的 **逆序** 执行。
+
+Given the following setup, we should expect to see this in the console.
---:1
@@ -206,15 +177,13 @@ async def middleware_3(request, response):
@app.middleware("response")
async def middleware_4(request, response):
print("middleware_4")
-
+
@app.get("/handler")
async def handler(request):
print("~ handler ~")
return text("Done.")
```
-
:--:1
-
```bash
middleware_1
middleware_2
@@ -223,5 +192,4 @@ middleware_4
middleware_3
[INFO][127.0.0.1:44788]: GET http://localhost:8000/handler 200 5
```
-
:---
From 6b8962c8827ac95720dea3c9b9f2690111a47d46 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:12 +0300
Subject: [PATCH 072/776] New translations middleware.md (Portuguese,
Brazilian)
---
src/pt/guide/basics/middleware.md | 191 ++++++++++++++++++++++++++++++
1 file changed, 191 insertions(+)
create mode 100644 src/pt/guide/basics/middleware.md
diff --git a/src/pt/guide/basics/middleware.md b/src/pt/guide/basics/middleware.md
new file mode 100644
index 0000000000..6e869bb693
--- /dev/null
+++ b/src/pt/guide/basics/middleware.md
@@ -0,0 +1,191 @@
+# Middleware
+
+Whereas listeners allow you to attach functionality to the lifecycle of a worker process, middleware allows you to attach functionality to the lifecycle of an HTTP stream.
+
+You can execute middleware either _before_ the handler is executed, or _after_.
+
+```mermaid
+sequenceDiagram
+autonumber
+participant Worker
+participant Middleware
+participant MiddlewareHandler
+participant RouteHandler
+Note over Worker: Incoming HTTP request
+loop
+ Worker->>Middleware: @app.on_request
+ Middleware->>MiddlewareHandler: Invoke middleware handler
+ MiddlewareHandler-->>Worker: Return response (optional)
+end
+rect rgba(255, 13, 104, .1)
+Worker->>RouteHandler: Invoke route handler
+RouteHandler->>Worker: Return response
+end
+loop
+ Worker->>Middleware: @app.on_response
+ Middleware->>MiddlewareHandler: Invoke middleware handler
+ MiddlewareHandler-->>Worker: Return response (optional)
+end
+Note over Worker: Deliver response
+```
+## Attaching middleware
+
+---:1
+
+This should probably look familiar by now. All you need to do is declare when you would like the middleware to execute: on the `request` or on the `response`. :--:1
+```python
+async def extract_user(request):
+ request.ctx.user = await extract_user_from_request(request)
+
+app.register_middleware(extract_user, "request")
+```
+:---
+
+---:1
+
+Again, the `Sanic` app instance also has a convenience decorator. :--:1
+```python
+@app.middleware("request")
+async def extract_user(request):
+ request.ctx.user = await extract_user_from_request(request)
+```
+:---
+
+---:1
+
+Response middleware receives both the `request` and `response` arguments. :--:1
+```python
+@app.middleware('response')
+async def prevent_xss(request, response):
+ response.headers["x-xss-protection"] = "1; mode=block"
+```
+:---
+
+---:1
+
+You can shorten the decorator even further. This is helpful if you have an IDE with autocomplete. :--:1
+```python
+@app.on_request
+async def extract_user(request):
+ ...
+
+@app.on_response
+async def prevent_xss(request, response):
+ ...
+```
+:---
+
+## Modification
+
+---:1
+
+Middleware can modify the request or response parameter it is given, _as long as it does not return it_.
+
+#### Order of execution
+
+1. Request middleware: `add_key`
+2. Route handler: `index`
+3. Response middleware: `prevent_xss`
+4. Response middleware: `custom_banner` :--:1
+```python
+@app.middleware("request")
+async def add_key(request):
+ # Arbitrary data may be stored in request context:
+ request.ctx.foo = "bar"
+
+
+@app.middleware("response")
+async def custom_banner(request, response):
+ response.headers["Server"] = "Fake-Server"
+
+
+@app.middleware("response")
+async def prevent_xss(request, response):
+ response.headers["x-xss-protection"] = "1; mode=block"
+
+
+@app.get("/")
+async def index(request):
+ return text(request.ctx.foo)
+
+```
+:---
+
+
+---:1 You can modify the `request.match_info`. A useful feature that could be used, for example, in middleware to convert `a-slug` to `a_slug`. :--:1
+```python
+@app.on_request
+def convert_slug_to_underscore(request: Request):
+ request._match_info["slug"] = request._match_info["slug"].replace("-", "_")
+
+
+@app.get("/")
+async def handler(request, slug):
+ return text(slug)
+```
+```
+$ curl localhost:9999/foo-bar-baz
+foo_bar_baz
+```
+:---
+## Responding early
+
+---:1
+
+If middleware returns a `HTTPResponse` object, the request will stop processing and the response will be returned. If this occurs to a request before the route handler is reached, the handler will **not** be called. Returning a response will also prevent any further middleware from running.
+
+::: tip You can return a `None` value to stop the execution of the middleware handler to allow the request to process as normal. This can be useful when using early return to avoid processing requests inside of that middleware handler. ::: :--:1
+```python
+@app.middleware("request")
+async def halt_request(request):
+ return text("I halted the request")
+
+@app.middleware("response")
+async def halt_response(request, response):
+ return text("I halted the response")
+```
+:---
+
+#### Order of execution
+
+Request middleware is executed in the order declared. Response middleware is executed in **reverse order**.
+
+Given the following setup, we should expect to see this in the console.
+
+---:1
+
+```python
+@app.middleware("request")
+async def middleware_1(request):
+ print("middleware_1")
+
+
+@app.middleware("request")
+async def middleware_2(request):
+ print("middleware_2")
+
+
+@app.middleware("response")
+async def middleware_3(request, response):
+ print("middleware_3")
+
+
+@app.middleware("response")
+async def middleware_4(request, response):
+ print("middleware_4")
+
+@app.get("/handler")
+async def handler(request):
+ print("~ handler ~")
+ return text("Done.")
+```
+:--:1
+```bash
+middleware_1
+middleware_2
+~ handler ~
+middleware_4
+middleware_3
+[INFO][127.0.0.1:44788]: GET http://localhost:8000/handler 200 5
+```
+:---
From 8db026eed1e95534cb00e3de9baeb6b47f97d79b Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:14 +0300
Subject: [PATCH 073/776] New translations request.md (Japanese)
---
src/ja/guide/basics/request.md | 79 +++++++++++++++++++++++++---------
1 file changed, 59 insertions(+), 20 deletions(-)
diff --git a/src/ja/guide/basics/request.md b/src/ja/guide/basics/request.md
index eeeeedf7ae..e6737a153d 100644
--- a/src/ja/guide/basics/request.md
+++ b/src/ja/guide/basics/request.md
@@ -1,6 +1,6 @@
# Request
-`Request`インスタンスには、そのパラメータに関する有用な情報が**たくさん**含まれています。詳細については、[APIドキュメント](https://sanic.readthedocs.io/) を参照してください。
+`Request`インスタンスには、そのパラメータに関する有用な情報が**たくさん**含まれています。 詳細については、[APIドキュメント](https://sanic.readthedocs.io/) を参照してください。
## Body
@@ -58,11 +58,9 @@ bar
['bar']
```
-::: tip FYI
-:bulb: `request.form`オブジェクトは、各値がリストであるディクショナリの、いくつかのタイプの1つです。これは、HTTPでは1つのキーを再利用して複数の値を送信できるためです。
+::: tip FYI :bulb: The `request.files` object is one of a few types that is a dictionary with each value being a list. This is because HTTP allows a single key to be reused to send multiple values.
-ほとんどの場合、リストではなく最初の要素にアクセスするには、`.get()`メソッドを使用します。すべての項目のリストが必要な場合は、`.getlist()`を使用できます。
-:::
+Most of the time you will want to use the `.get()` method to access the first element and not a list. If you do want a list of all items, you can use `.getlist()`. :::
::: tab Uploaded
@@ -86,10 +84,9 @@ File(type='application/octet-stream', body=b'hello\n', name='TEST')
>>> print(request.files.getlist("my_file"))
[File(type='application/octet-stream', body=b'hello\n', name='TEST')]
```
-::: tip FYI
-:bulb: The `request.files` object is one of a few types that is a dictionary with each value being a list. This is because HTTP allows a single key to be reused to send multiple values.
+::: tip FYI :bulb: `request.args`オブジェクトは、各値がリストになっているディクショナリのタイプの1つです。 これは、HTTPでは1つのキーを再利用して複数の値を送信できるためです。
-Most of the time you will want to use the `.get()` method to access the first element and not a list. If you do want a list of all items, you can use `.getlist()`.
+ほとんどの場合、リストではなく最初の要素にアクセスするには、`.get()`メソッドを使用します。 すべての項目のリストが必要な場合は、`.getlist()`を使用できます。 :::
:::
::::
@@ -100,7 +97,7 @@ Most of the time you will want to use the `.get()` method to access the first el
`request.ctx`オブジェクトは、リクエストに関して必要な情報を格納するためのプレイグラウンドです。
-これは、認証されたユーザーの詳細などのアイテムを格納するためによく使用されます。[ミドルウェア](./middleware.md)を使用しますが、ここでは簡単な例を示します。
+これは、認証されたユーザーの詳細などのアイテムを格納するためによく使用されます。 [ミドルウェア](./middleware.md)を使用しますが、ここでは簡単な例を示します。
```python
@app.on_request
@@ -112,18 +109,17 @@ async def hi_my_name_is(request):
return text("Hi, my name is {}".format(request.ctx.user.name))
```
-典型的な使用例は、データベースから取得したユーザー・オブジェクトを認証ミドルウェアに格納することです。追加されたキーは、以降のすべてのミドルウェアおよびリクエストの実行中にハンドラからアクセスできます。
+典型的な使用例は、データベースから取得したユーザー・オブジェクトを認証ミドルウェアに格納することです。 追加されたキーは、以降のすべてのミドルウェアおよびリクエストの実行中にハンドラからアクセスできます。
-カスタムコンテキストは、アプリケーションおよび拡張用に予約されています。サニック自身はそれを利用しない。
+カスタムコンテキストは、アプリケーションおよび拡張用に予約されています。 サニック自身はそれを利用しない。
### Connection context
---:1
-多くの場合、APIは同じクライアントに対して複数の同時 (または連続) リクエストを処理する必要があります。たとえば、データを取得するために複数のエンドポイントにクエリを実行する必要があるプログレッシブウェブアプリでは、これが頻繁に発生します。
-
+多くの場合、APIは同じクライアントに対して複数の同時 (または連続) リクエストを処理する必要があります。 たとえば、データを取得するために複数のエンドポイントにクエリを実行する必要があるプログレッシブウェブアプリでは、これが頻繁に発生します。
-HTTPプロトコルでは、[keep alive headers](../ deployment/configuration.md#keep-alive-timeout)を使用した接続によって発生するオーバーヘッド時間を緩和する必要があります。
+HTTPプロトコルでは、\[keep alive headers\](../ deployment/configuration.md#keep-alive-timeout)を使用した接続によって発生するオーバーヘッド時間を緩和する必要があります。
複数のリクエストが1つの接続を共有する場合、Sanicはそれらのリクエストが状態を共有できるようにコンテキストオブジェクトを提供します。
@@ -150,9 +146,7 @@ request.conn_info.ctx.foo=3
## Parameters
----:1
-パスから抽出された値は、パラメータとして、より具体的にはキーワード引数としてハンドラに注入されます。詳細については、 [ルーティングセクション](./routing.md)。
-:--:1
+---:1 パスから抽出された値は、パラメータとして、より具体的にはキーワード引数としてハンドラに注入されます。 詳細については、 [ルーティングセクション](./routing.md)。 :--:1 :--:1
```python
@app.route('/tag/')
async def tag_handler(request, tag):
@@ -190,8 +184,53 @@ key1=val1&key2=val2&key1=val3
```
-::: tip FYI
-:bulb: `request.args`オブジェクトは、各値がリストになっているディクショナリのタイプの1つです。これは、HTTPでは1つのキーを再利用して複数の値を送信できるためです。
+::: tip FYI :bulb: `request.form`オブジェクトは、各値がリストであるディクショナリの、いくつかのタイプの1つです。 これは、HTTPでは1つのキーを再利用して複数の値を送信できるためです。
+
+ほとんどの場合、リストではなく最初の要素にアクセスするには、`.get()`メソッドを使用します。 すべての項目のリストが必要な場合は、`.getlist()`を使用できます。 :::
+:::
+
+::: new NEW in v22.6
+
+## Current request getter
+
+Sometimes you may find that you need access to the current request in your application in a location where it is not accessible. A typical example might be in a `logging` format. You can use `Request.get_current()` to fetch the current request (if any).
+
+```python
+import logging
+
+from sanic import Request, Sanic, json
+from sanic.exceptions import SanicException
+from sanic.log import LOGGING_CONFIG_DEFAULTS
+
+LOGGING_FORMAT = (
+ "%(asctime)s - (%(name)s)[%(levelname)s][%(host)s]: "
+ "%(request_id)s %(request)s %(message)s %(status)d %(byte)d"
+)
+
+old_factory = logging.getLogRecordFactory()
+
+
+def record_factory(*args, **kwargs):
+ record = old_factory(*args, **kwargs)
+ record.request_id = ""
+
+ try:
+ request = Request.get_current()
+ except SanicException:
+ ...
+ else:
+ record.request_id = str(request.id)
+
+ return record
+
+
+logging.setLogRecordFactory(record_factory)
+
+LOGGING_CONFIG_DEFAULTS["formatters"]["access"]["format"] = LOGGING_FORMAT
+
+app = Sanic("Example", log_config=LOGGING_CONFIG_DEFAULTS)
+```
+
+In this example, we are adding the `request.id` to every access log message.
-ほとんどの場合、リストではなく最初の要素にアクセスするには、`.get()`メソッドを使用します。すべての項目のリストが必要な場合は、`.getlist()`を使用できます。
:::
From 29c207ec7ea5d09e8684ff9ac2747b48d8ae1de0 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:15 +0300
Subject: [PATCH 074/776] New translations request.md (Korean)
---
src/ko/guide/basics/request.md | 71 ++++++++++++++++++++++++++--------
1 file changed, 54 insertions(+), 17 deletions(-)
diff --git a/src/ko/guide/basics/request.md b/src/ko/guide/basics/request.md
index 1106cbe07a..0ac6be5cd1 100644
--- a/src/ko/guide/basics/request.md
+++ b/src/ko/guide/basics/request.md
@@ -58,12 +58,9 @@ bar
['bar']
```
-::: tip FYI
+:bulb: `request.form` 객체는 각 값이 목록인 사전인 몇 가지 유형 중 하나입니다. HTTP에서는 단일 키를 재사용하여 여러 값을 보낼 수 있기 때문입니다.
-:bulb: `request.form` 객체는 각 값이 목록인 사전인 몇 가지 유형 중 하나입니다. HTTP에서는 단일 키를 재사용하여 여러 값을 보낼 수 있기 때문입니다.
-
-대부분의 경우 `.get()` 메서드를 사용하여 목록이 아닌 첫 번째 요소에 액세스하기를 원할 것입니다. 모든 항목의 목록을 원하면 `.getlist()`를 사용할 수 있습니다.
-:::
+대부분의 경우 `.get()` 메서드를 사용하여 목록이 아닌 첫 번째 요소에 액세스하기를 원할 것입니다. 모든 항목의 목록을 원하면 `.getlist()`를 사용할 수 있습니다. :::
::: tab Uploaded
@@ -87,11 +84,9 @@ File(type='application/octet-stream', body=b'hello\n', name='TEST')
>>> print(request.files.getlist("my_file"))
[File(type='application/octet-stream', body=b'hello\n', name='TEST')]
```
-::: tip FYI
-:bulb: `request.files` 객체는 각 값이 목록인 사전인 몇 가지 유형 중 하나입니다. HTTP에서는 단일 키를 재사용하여 여러 값을 보낼 수 있기 때문입니다.
+::: tip FYI :bulb: `request.files` 객체는 각 값이 목록인 사전인 몇 가지 유형 중 하나입니다. HTTP에서는 단일 키를 재사용하여 여러 값을 보낼 수 있기 때문입니다.
-대부분의 경우 `.get()` 메서드를 사용하여 목록이 아닌 첫 번째 요소에 액세스하기를 원할 것입니다. 모든 항목의 목록을 원하면 `.getlist()`를 사용할 수 있습니다.
-:::
+대부분의 경우 `.get()` 메서드를 사용하여 목록이 아닌 첫 번째 요소에 액세스하기를 원할 것입니다. 모든 항목의 목록을 원하면 `.getlist()`를 사용할 수 있습니다. :::
::::
@@ -123,9 +118,9 @@ async def hi_my_name_is(request):
종종 API는 동일한 클라이언트에 여러 동시(또는 연속) 요청을 제공해야 합니다. 예를 들어, 이는 데이터를 얻기 위해 여러 엔드포인트를 쿼리해야 하는 점진적 웹 앱에서 매우 자주 발생합니다.
-HTTP 프로토콜은 [keep live headers](../deployment/configuration.md#keep-alive-timeout)를 사용하여 연결로 인한 오버헤드 시간의 완화를 요청합니다
+The HTTP protocol calls for an easing of overhead time caused by the connection with the use of [keep alive headers](../deployment/configuration.md#keep-alive-timeout).
-여러 요청이 단일 연결을 공유할 때 Sanic은 해당 요청이 상태를 공유할 수 있도록 컨텍스트 객체를 제공합니다.
+HTTP 프로토콜은 [keep live headers](../deployment/configuration.md#keep-alive-timeout)를 사용하여 연결로 인한 오버헤드 시간의 완화를 요청합니다
:--:1
```python
@@ -150,9 +145,7 @@ request.conn_info.ctx.foo=3
## 매개변수 (Parameters)
----:1
-경로에서 추출된 값은 핸들러에 매개변수로, 더 구체적으로는 키워드 인수로 주입됩니다. [Routing section](./routing.md)에 이에 대한 자세한 내용이 있습니다.
-:--:1
+---:1 경로에서 추출된 값은 핸들러에 매개변수로, 더 구체적으로는 키워드 인수로 주입됩니다. [Routing section](./routing.md)에 이에 대한 자세한 내용이 있습니다. :--:1
```python
@app.route('/tag/')
async def tag_handler(request, tag):
@@ -190,8 +183,52 @@ key1=val1&key2=val2&key1=val3
```
-::: tip FYI
-:bulb: `request.args` 객체는 각 값이 목록인 사전인 몇 가지 유형 중 하나입니다. HTTP에서는 단일 키를 재사용하여 여러 값을 보낼 수 있기 때문입니다.
+::: tip FYI :bulb: `request.args` 객체는 각 값이 목록인 사전인 몇 가지 유형 중 하나입니다. HTTP에서는 단일 키를 재사용하여 여러 값을 보낼 수 있기 때문입니다.
+
+대부분의 경우 `.get()` 메서드를 사용하여 목록이 아닌 첫 번째 요소에 액세스하기를 원할 것입니다. 모든 항목의 목록을 원하면 `.getlist()`를 사용할 수 있습니다. :::
+
+::: new NEW in v22.6
+
+## Current request getter
+
+Sometimes you may find that you need access to the current request in your application in a location where it is not accessible. A typical example might be in a `logging` format. You can use `Request.get_current()` to fetch the current request (if any).
+
+```python
+import logging
+
+from sanic import Request, Sanic, json
+from sanic.exceptions import SanicException
+from sanic.log import LOGGING_CONFIG_DEFAULTS
+
+LOGGING_FORMAT = (
+ "%(asctime)s - (%(name)s)[%(levelname)s][%(host)s]: "
+ "%(request_id)s %(request)s %(message)s %(status)d %(byte)d"
+)
+
+old_factory = logging.getLogRecordFactory()
+
+
+def record_factory(*args, **kwargs):
+ record = old_factory(*args, **kwargs)
+ record.request_id = ""
+
+ try:
+ request = Request.get_current()
+ except SanicException:
+ ...
+ else:
+ record.request_id = str(request.id)
+
+ return record
+
+
+logging.setLogRecordFactory(record_factory)
+
+LOGGING_CONFIG_DEFAULTS["formatters"]["access"]["format"] = LOGGING_FORMAT
+
+app = Sanic("Example", log_config=LOGGING_CONFIG_DEFAULTS)
+```
+
+In this example, we are adding the `request.id` to every access log message.
-대부분의 경우 `.get()` 메서드를 사용하여 목록이 아닌 첫 번째 요소에 액세스하기를 원할 것입니다. 모든 항목의 목록을 원하면 `.getlist()`를 사용할 수 있습니다.
:::
From a5f804809252adb6f49a67ed28770ba68b3bf991 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:16 +0300
Subject: [PATCH 075/776] New translations request.md (Chinese Simplified)
---
src/zh/guide/basics/request.md | 103 +++++++++++++++++++--------------
1 file changed, 60 insertions(+), 43 deletions(-)
diff --git a/src/zh/guide/basics/request.md b/src/zh/guide/basics/request.md
index 8029b076ba..74a393d9cb 100644
--- a/src/zh/guide/basics/request.md
+++ b/src/zh/guide/basics/request.md
@@ -8,10 +8,6 @@
::: tab JSON
-**参数名称**: `request.json`
-
-**参数说明**: 解析后的 JSON 对象
-
```bash
$ curl localhost:8000 -d '{"foo": "bar"}'
```
@@ -20,14 +16,11 @@ $ curl localhost:8000 -d '{"foo": "bar"}'
>>> print(request.json)
{'foo': 'bar'}
```
-
:::
::: tab Raw
-**参数名称**: `request.body`
-
-**参数说明**: 请求正文中的原始字节
+**参数名称**: `request.body`
```bash
$ curl localhost:8000 -d '{"foo": "bar"}'
@@ -41,9 +34,7 @@ b'{"foo": "bar"}'
::: tab Form
-**参数名称**: `request.form`
-
-**参数说明**: 表单数据
+**参数说明**: 请求正文中的原始字节
```bash
$ curl localhost:8000 -d 'foo=bar'
@@ -63,19 +54,13 @@ bar
['bar']
```
-::: tip 小提示:
-
-:bulb: `request.form` 对象是少数几种字典之一,每个值都是一个列表。这是因为 HTTP 允许单个键名被重用以发送多个值。
+:bulb: `request.form` 对象是少数几种字典之一,每个值都是一个列表。 这是因为 HTTP 允许单个键名被重用以发送多个值。
-大多数情况下您只需要使用 `.get()` 方法来获取列表中的第一个元素即可,如果您想获取列表中的全部元素,那么请使用 `.getlist()` 方法。
-
-:::
+Most of the time you will want to use the `.get()` method to access the first element and not a list. If you do want a list of all items, you can use `.getlist()`. :::
::: tab Uploaded
-**参数名称**: `request.files`
-
-**参数说明**: 上传到服务器的文件
+**参数说明**: 表单数据
```bash
$ curl -F 'my_file=@/path/to/TEST' http://localhost:8000
@@ -94,13 +79,9 @@ File(type='application/octet-stream', body=b'hello\n', name='TEST')
>>> print(request.files.getlist("my_file"))
[File(type='application/octet-stream', body=b'hello\n', name='TEST')]
```
-::: tip 小提示:
-
-:bulb: 和 `request.form` 对象一样, `request.files` 也是少数几种字典之一,每个值都是一个列表。这是因为 HTTP 同样允许单个键名被重用以发送多个文件。
-
-获取方式也和 `request.form` 一致,大多数情况下您只需要使用 `.get()` 方法来获取列表中的第一个元素即可,如果您想获取列表中的全部元素,那么请使用 `.getlist()` 方法。
+:bulb: 和上述的 `request.form`、`request.files` 对象一样,`request.args` 同样是少数几种字典之一,每个值都是一个列表。 这是因为HTTP允许单个键名被重用以发送多个值。
-:::
+Most of the time you will want to use the `.get()` method to access the first element and not a list. If you do want a list of all items, you can use `.getlist()`. :::
::::
@@ -110,7 +91,7 @@ File(type='application/octet-stream', body=b'hello\n', name='TEST')
`request.ctx` 对象是存储请求相关信息的地方。
-这里通常被用来存储服务端通过某些验证后需要临时存储的身份认证信息以及专有变量等内容。更多的具体内容我们将在 [中间件](/zh/guide/advanced/middleware.md) 这一章节进行更多的描述,下面是一个简单的例子。
+这里通常被用来存储服务端通过某些验证后需要临时存储的身份认证信息以及专有变量等内容。 更多的具体内容我们将在 [中间件](/zh/guide/advanced/middleware.md) 这一章节进行更多的描述,下面是一个简单的例子。
```python
@app.middleware("request")
@@ -122,22 +103,21 @@ async def hi_my_name_is(request):
return text("Hi, my name is {}".format(request.ctx.user.name))
```
-最典型的用法就是将从数据库获取的用户对象存储在 `request.ctx` 中。所有该中间件之后的其他中间件以及请求期间的处理程序都可以对此进行访问。
+最典型的用法就是将从数据库获取的用户对象存储在 `request.ctx` 中。 所有该中间件之后的其他中间件以及请求期间的处理程序都可以对此进行访问。
-自定义上下文是为了应用程序和拓展插件而保留的,Sanic 本身并不使用它。
+Custom context is reserved for applications and extensions. Sanic itself makes no use of it.
### 连接上下文(Connection context)
---:1
-通常情况下,您的应用程序需要向同一个客户端提供多个并发(或连续)的请求。这种情况通常发生在需要查询多个端点来获取数据的渐进式网络应用程序中。
+通常情况下,您的应用程序需要向同一个客户端提供多个并发(或连续)的请求。 这种情况通常发生在需要查询多个端点来获取数据的渐进式网络应用程序中。
-在 HTTP 协议要求通过 [keep alive](../deployment/configuration.md#keep-alive-timeout) 请求头来减少频繁连接所造成的时间浪费。
+获取方式也和 `request.form` 一致,大多数情况下您只需要使用 `.get()` 方法来获取列表中的第一个元素即可,如果您想获取列表中的全部元素,那么请使用 `.getlist()` 方法。
当多个请求共享一个连接时,Sanic 将提供一个上下文对象来允许这些请求共享状态。
:--:1
-
```python
@app.on_request
async def increment_foo(request):
@@ -156,17 +136,11 @@ request.conn_info.ctx.foo=1
request.conn_info.ctx.foo=2
request.conn_info.ctx.foo=3
```
-
:---
## 路由参数(Parameter)
----:1
-
-从路径提取的路由参数将作为参数(或更具体地作为关键字参数)传递到处理程序中。更多的详细内容我们将在 [路由](/zh/guide/basics/routing.md) 这一章节进行详细说明
-
-:--:1
-
+---:1 Values that are extracted from the path are injected into the handler as parameters, or more specifically as keyword arguments. 更多的详细内容我们将在 [路由](/zh/guide/basics/routing.md) 这一章节进行详细说明 :--:1
```python
@app.route('/tag/')
async def tag_handler(request, tag):
@@ -174,9 +148,10 @@ async def tag_handler(request, tag):
```
:---
+
## 请求参数(Arguments)
-在 `request` 中,您可以通过两种属性来访问请求参数:
+自定义上下文是为了应用程序和拓展插件而保留的,Sanic 本身并不使用它。
- `request.args`
- `request.query_args`
@@ -203,10 +178,52 @@ key1=val1&key2=val2&key1=val3
```
-::: tip 小提示:
+:bulb: 和 `request.form` 对象一样, `request.files` 也是少数几种字典之一,每个值都是一个列表。 这是因为 HTTP 同样允许单个键名被重用以发送多个文件。
+
+大多数情况下您只需要使用 `.get()` 方法来获取列表中的第一个元素即可,如果您想获取列表中的全部元素,那么请使用 `.getlist()` 方法。 If you do want a list of all items, you can use `.getlist()`. :::
+
+在 HTTP 协议要求通过 [keep alive](../deployment/configuration.md#keep-alive-timeout) 请求头来减少频繁连接所造成的时间浪费。
+
+## Current request getter
+
+Sometimes you may find that you need access to the current request in your application in a location where it is not accessible. A typical example might be in a `logging` format. You can use `Request.get_current()` to fetch the current request (if any).
+
+```python
+import logging
-:bulb: 和上述的 `request.form`、`request.files` 对象一样,`request.args` 同样是少数几种字典之一,每个值都是一个列表。这是因为HTTP允许单个键名被重用以发送多个值。
+from sanic import Request, Sanic, json
+from sanic.exceptions import SanicException
+from sanic.log import LOGGING_CONFIG_DEFAULTS
+
+LOGGING_FORMAT = (
+ "%(asctime)s - (%(name)s)[%(levelname)s][%(host)s]: "
+ "%(request_id)s %(request)s %(message)s %(status)d %(byte)d"
+)
+
+old_factory = logging.getLogRecordFactory()
+
+
+def record_factory(*args, **kwargs):
+ record = old_factory(*args, **kwargs)
+ record.request_id = ""
+
+ try:
+ request = Request.get_current()
+ except SanicException:
+ ...
+ else:
+ record.request_id = str(request.id)
+
+ return record
+
+
+logging.setLogRecordFactory(record_factory)
+
+LOGGING_CONFIG_DEFAULTS["formatters"]["access"]["format"] = LOGGING_FORMAT
+
+app = Sanic("Example", log_config=LOGGING_CONFIG_DEFAULTS)
+```
-获取方式也和 它们一致,大多数情况下您只需要使用 `.get()` 方法来获取列表中的第一个元素即可,如果您想获取列表中的全部元素,那么请使用 `.getlist()` 方法。
+In this example, we are adding the `request.id` to every access log message.
:::
From a7f3cb67f440bb552d25682fd8709d70f204d243 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:17 +0300
Subject: [PATCH 076/776] New translations request.md (Portuguese, Brazilian)
---
src/pt/guide/basics/request.md | 234 +++++++++++++++++++++++++++++++++
1 file changed, 234 insertions(+)
create mode 100644 src/pt/guide/basics/request.md
diff --git a/src/pt/guide/basics/request.md b/src/pt/guide/basics/request.md
new file mode 100644
index 0000000000..8c93a9e3f2
--- /dev/null
+++ b/src/pt/guide/basics/request.md
@@ -0,0 +1,234 @@
+# Request
+
+The `Request` instance contains **a lot** of helpful information available on its parameters. Refer to the [API documentation](https://sanic.readthedocs.io/) for full details.
+
+## Body
+
+:::: tabs
+::: tab JSON
+
+**Parameter**: `request.json`
+**Description**: The parsed JSON object
+
+```bash
+$ curl localhost:8000 -d '{"foo": "bar"}'
+```
+
+```python
+>>> print(request.json)
+{'foo': 'bar'}
+```
+:::
+
+::: tab Raw
+
+**Parameter**: `request.body`
+**Description**: The raw bytes from the request body
+
+```bash
+$ curl localhost:8000 -d '{"foo": "bar"}'
+```
+
+```python
+>>> print(request.body)
+b'{"foo": "bar"}'
+```
+:::
+
+::: tab Form
+
+**Parameter**: `request.form`
+**Description**: The form data
+
+```bash
+$ curl localhost:8000 -d 'foo=bar'
+```
+
+```python
+>>> print(request.body)
+b'foo=bar'
+
+>>> print(request.form)
+{'foo': ['bar']}
+
+>>> print(request.form.get("foo"))
+bar
+
+>>> print(request.form.getlist("foo"))
+['bar']
+```
+
+::: tip FYI :bulb: The `request.form` object is one of a few types that is a dictionary with each value being a list. This is because HTTP allows a single key to be reused to send multiple values.
+
+Most of the time you will want to use the `.get()` method to access the first element and not a list. If you do want a list of all items, you can use `.getlist()`. :::
+
+::: tab Uploaded
+
+**Parameter**: `request.files`
+**Description**: The files uploaded to the server
+
+```bash
+$ curl -F 'my_file=@/path/to/TEST' http://localhost:8000
+```
+
+```python
+>>> print(request.body)
+b'--------------------------cb566ad845ad02d3\r\nContent-Disposition: form-data; name="my_file"; filename="TEST"\r\nContent-Type: application/octet-stream\r\n\r\nhello\n\r\n--------------------------cb566ad845ad02d3--\r\n'
+
+>>> print(request.files)
+{'my_file': [File(type='application/octet-stream', body=b'hello\n', name='TEST')]}
+
+>>> print(request.files.get("my_file"))
+File(type='application/octet-stream', body=b'hello\n', name='TEST')
+
+>>> print(request.files.getlist("my_file"))
+[File(type='application/octet-stream', body=b'hello\n', name='TEST')]
+```
+::: tip FYI :bulb: The `request.files` object is one of a few types that is a dictionary with each value being a list. This is because HTTP allows a single key to be reused to send multiple values.
+
+Most of the time you will want to use the `.get()` method to access the first element and not a list. If you do want a list of all items, you can use `.getlist()`. :::
+
+::::
+
+## Context
+
+### Request context
+
+The `request.ctx` object is your playground to store whatever information you need to about the request.
+
+This is often used to store items like authenticated user details. We will get more into [middleware](./middleware.md) later, but here is a simple example.
+
+```python
+@app.on_request
+async def run_before_handler(request):
+ request.ctx.user = await fetch_user_by_token(request.token)
+
+@app.route('/hi')
+async def hi_my_name_is(request):
+ return text("Hi, my name is {}".format(request.ctx.user.name))
+```
+
+A typical use case would be to store the user object acquired from database in an authentication middleware. Keys added are accessible to all later middleware as well as the handler over the duration of the request.
+
+Custom context is reserved for applications and extensions. Sanic itself makes no use of it.
+
+### Connection context
+
+---:1
+
+Often times your API will need to serve multiple concurrent (or consecutive) requests to the same client. This happens, for example, very often with progressive web apps that need to query multiple endpoints to get data.
+
+The HTTP protocol calls for an easing of overhead time caused by the connection with the use of [keep alive headers](../deployment/configuration.md#keep-alive-timeout).
+
+When multiple requests share a single connection, Sanic provides a context object to allow those requests to share state.
+
+:--:1
+```python
+@app.on_request
+async def increment_foo(request):
+ if not hasattr(request.conn_info.ctx, "foo"):
+ request.conn_info.ctx.foo = 0
+ request.conn_info.ctx.foo += 1
+
+@app.get("/")
+async def count_foo(request):
+ return text(f"request.conn_info.ctx.foo={request.conn_info.ctx.foo}")
+```
+
+```bash
+$ curl localhost:8000 localhost:8000 localhost:8000
+request.conn_info.ctx.foo=1
+request.conn_info.ctx.foo=2
+request.conn_info.ctx.foo=3
+```
+:---
+
+## Parameters
+
+---:1 Values that are extracted from the path are injected into the handler as parameters, or more specifically as keyword arguments. There is much more detail about this in the [Routing section](./routing.md). :--:1
+```python
+@app.route('/tag/')
+async def tag_handler(request, tag):
+ return text("Tag - {}".format(tag))
+```
+:---
+
+
+## Arguments
+
+There are two attributes on the `request` instance to get query parameters:
+
+- `request.args`
+- `request.query_args`
+
+```bash
+$ curl http://localhost:8000\?key1\=val1\&key2\=val2\&key1\=val3
+```
+
+```python
+>>> print(request.args)
+{'key1': ['val1', 'val3'], 'key2': ['val2']}
+
+>>> print(request.args.get("key1"))
+val1
+
+>>> print(request.args.getlist("key1"))
+['val1', 'val3']
+
+>>> print(request.query_args)
+[('key1', 'val1'), ('key2', 'val2'), ('key1', 'val3')]
+
+>>> print(request.query_string)
+key1=val1&key2=val2&key1=val3
+
+```
+
+::: tip FYI :bulb: The `request.args` object is one of a few types that is a dictionary with each value being a list. This is because HTTP allows a single key to be reused to send multiple values.
+
+Most of the time you will want to use the `.get()` method to access the first element and not a list. If you do want a list of all items, you can use `.getlist()`. :::
+
+::: new NEW in v22.6
+
+## Current request getter
+
+Sometimes you may find that you need access to the current request in your application in a location where it is not accessible. A typical example might be in a `logging` format. You can use `Request.get_current()` to fetch the current request (if any).
+
+```python
+import logging
+
+from sanic import Request, Sanic, json
+from sanic.exceptions import SanicException
+from sanic.log import LOGGING_CONFIG_DEFAULTS
+
+LOGGING_FORMAT = (
+ "%(asctime)s - (%(name)s)[%(levelname)s][%(host)s]: "
+ "%(request_id)s %(request)s %(message)s %(status)d %(byte)d"
+)
+
+old_factory = logging.getLogRecordFactory()
+
+
+def record_factory(*args, **kwargs):
+ record = old_factory(*args, **kwargs)
+ record.request_id = ""
+
+ try:
+ request = Request.get_current()
+ except SanicException:
+ ...
+ else:
+ record.request_id = str(request.id)
+
+ return record
+
+
+logging.setLogRecordFactory(record_factory)
+
+LOGGING_CONFIG_DEFAULTS["formatters"]["access"]["format"] = LOGGING_FORMAT
+
+app = Sanic("Example", log_config=LOGGING_CONFIG_DEFAULTS)
+```
+
+In this example, we are adding the `request.id` to every access log message.
+
+:::
From 983f5242174538c9de9d1d802307cd7e0e4197c7 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:18 +0300
Subject: [PATCH 077/776] New translations response.md (Japanese)
---
src/ja/guide/basics/response.md | 30 +++---------------------------
1 file changed, 3 insertions(+), 27 deletions(-)
diff --git a/src/ja/guide/basics/response.md b/src/ja/guide/basics/response.md
index 91915b5fd3..0f22fb68e5 100644
--- a/src/ja/guide/basics/response.md
+++ b/src/ja/guide/basics/response.md
@@ -91,28 +91,6 @@ You can also choose to override the file name:
file("/path/to/whatever.png", filename="super-awesome-incredible.png")
```
:::
-::: tab Streaming
-
-**Default Content-Type**: `text/plain; charset=utf-8`
-**Description**: Streams data to a client
-
-```python
-from sanic.response import stream
-
-@app.route("/")
-async def handler(request):
- return stream(streaming_fn)
-
-async def streaming_fn(response):
- await response.write('foo')
- await response.write('bar')
-```
-By default, Sanic will stream back to the client using chunked encoding if the client supports it. You can disable this:
-
-```python
-stream(streaming_fn, chunked=False)
-```
-:::
::: tab "File Streaming"
**Default Content-Type**: N/A
@@ -126,8 +104,7 @@ async def handler(request):
return await file_stream("/path/to/whatever.mp4")
```
-Like the `file()` method, `file_stream()` will attempt to determine the mime type of the file.
-:::
+Like the `file()` method, `file_stream()` will attempt to determine the mime type of the file. :::
::: tab Raw
**Default Content-Type**: `application/octet-stream`
@@ -168,13 +145,12 @@ async def handler(request):
return empty()
```
-Defaults to a `204` status.
-:::
+Defaults to a `204` status. :::
::::
## Default status
-レスポンスのデフォルトのHTTPステータス・コードは`200`です。変更が必要な場合は、レスポンス方式で行うことができます。
+レスポンスのデフォルトのHTTPステータス・コードは`200`です。 変更が必要な場合は、レスポンス方式で行うことができます。
```python
From da78c6c74960c31844d604c9ea9091cce9953fc9 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:19 +0300
Subject: [PATCH 078/776] New translations response.md (Korean)
---
src/ko/guide/basics/response.md | 36 +++++----------------------------
1 file changed, 5 insertions(+), 31 deletions(-)
diff --git a/src/ko/guide/basics/response.md b/src/ko/guide/basics/response.md
index 9ab1ce8fba..f147241518 100644
--- a/src/ko/guide/basics/response.md
+++ b/src/ko/guide/basics/response.md
@@ -79,8 +79,7 @@ async def handler(request):
return await file("/path/to/whatever.png")
```
-Sanic은 파일을 검사하고 MIME 유형을 추측하고 콘텐츠 유형에 적절한 값을 사용합니다.
-원하는 경우 명시적일 수 있습니다:
+Sanic은 파일을 검사하고 MIME 유형을 추측하고 콘텐츠 유형에 적절한 값을 사용합니다. 원하는 경우 명시적일 수 있습니다:
```python
file("/path/to/whatever.png", mime_type="image/png")
@@ -92,35 +91,11 @@ file("/path/to/whatever.png", mime_type="image/png")
file("/path/to/whatever.png", filename="super-awesome-incredible.png")
```
:::
-::: tab Streaming
+::: tab "File Streaming"
**기본 콘텐츠 유형**: `text/plain; charset=utf-8`
**설명**: 클라이언트에 데이터 스트리밍
-```python
-from sanic.response import stream
-
-@app.route("/")
-async def handler(request):
- return stream(streaming_fn)
-
-async def streaming_fn(response):
- await response.write('foo')
- await response.write('bar')
-```
-
-기본적으로 Sanic은 클라이언트가 지원하는 경우 청크 인코딩을 사용하여 클라이언트로 다시 스트리밍합니다.
-비활성화할수도 있습니다:
-
-```python
-stream(streaming_fn, chunked=False)
-```
-:::
-::: tab "File Streaming"
-
-**기본 콘텐츠 유형**: N/A
-**설명**: 파일을 클라이언트로 스트리밍하며, 동영상과 같은 대용량 파일을 스트리밍할 때 유용합니다.
-
```python
from sanic.response import file_stream
@@ -129,8 +104,7 @@ async def handler(request):
return await file_stream("/path/to/whatever.mp4")
```
-`file()` 메소드와 마찬가지로 `file_stream()`은 파일의 MIME 유형을 결정하려고 시도합니다.
-:::
+`file()` 메소드와 마찬가지로 `file_stream()`은 파일의 MIME 유형을 결정하려고 시도합니다. :::
::: tab Raw
**기본 콘텐츠 유형**: `application/octet-stream`
@@ -170,8 +144,8 @@ from sanic.response import empty
async def handler(request):
return empty()
```
-기본값은 `204` 상태입니다.
-:::
+
+기본값은 `204` 상태입니다. :::
::::
## 기본 상태 (Default status)
From 6ec351ebd29ea28727f7d422bcad9a0a39ae65ec Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:20 +0300
Subject: [PATCH 079/776] New translations response.md (Portuguese, Brazilian)
---
src/pt/guide/basics/response.md | 161 ++++++++++++++++++++++++++++++++
1 file changed, 161 insertions(+)
create mode 100644 src/pt/guide/basics/response.md
diff --git a/src/pt/guide/basics/response.md b/src/pt/guide/basics/response.md
new file mode 100644
index 0000000000..adb36f2565
--- /dev/null
+++ b/src/pt/guide/basics/response.md
@@ -0,0 +1,161 @@
+# Response
+
+All [handlers](./handlers.md) **must** return a response object, and [middleware](./middleware.md) may optionally return a response object.
+
+## Methods
+
+The easiest way to generate a response object is to use one of the nine (9) convenience methods.
+
+:::: tabs
+
+::: tab Text
+
+**Default Content-Type**: `text/plain; charset=utf-8`
+**Description**: Returns plain text
+
+```python
+from sanic.response import text
+
+@app.route("/")
+async def handler(request):
+ return text("Hi 😎")
+```
+:::
+::: tab HTML
+
+**Default Content-Type**: `text/html; charset=utf-8`
+**Description**: Returns an HTML document
+
+```python
+from sanic.response import html
+
+@app.route("/")
+async def handler(request):
+ return html('
Hi 😎
')
+```
+:::
+::: tab JSON
+
+**Default Content-Type**: `application/json`
+**Description**: Returns a JSON document
+
+```python
+from sanic.response import json
+
+@app.route("/")
+async def handler(request):
+ return json({"foo": "bar"})
+```
+
+By default, Sanic ships with [`ujson`](https://github.com/ultrajson/ultrajson) as its JSON encoder of choice. It is super simple to change this if you want.
+
+```python
+from orjson import dumps
+
+json({"foo": "bar"}, dumps=dumps)
+```
+
+If `ujson` is not installed, it will fall back to the standard library `json` module.
+
+You may additionally declare which implementation to use globally across your application at initialization:
+
+```python
+from orjson import dumps
+
+app = Sanic(..., dumps=dumps)
+```
+:::
+::: tab File
+
+**Default Content-Type**: N/A
+**Description**: Returns a file
+
+
+```python
+from sanic.response import file
+
+@app.route("/")
+async def handler(request):
+ return await file("/path/to/whatever.png")
+```
+
+Sanic will examine the file, and try and guess its mime type and use an appropriate value for the content type. You could be explicit, if you would like:
+
+```python
+file("/path/to/whatever.png", mime_type="image/png")
+```
+
+You can also choose to override the file name:
+
+```python
+file("/path/to/whatever.png", filename="super-awesome-incredible.png")
+```
+:::
+::: tab "File Streaming"
+
+**Default Content-Type**: N/A
+**Description**: Streams a file to a client, useful when streaming large files, like a video
+
+```python
+from sanic.response import file_stream
+
+@app.route("/")
+async def handler(request):
+ return await file_stream("/path/to/whatever.mp4")
+```
+
+Like the `file()` method, `file_stream()` will attempt to determine the mime type of the file. :::
+::: tab Raw
+
+**Default Content-Type**: `application/octet-stream`
+**Description**: Send raw bytes without encoding the body
+
+```python
+from sanic.response import raw
+
+@app.route("/")
+async def handler(request):
+ return raw(b"raw bytes")
+```
+:::
+::: tab Redirect
+
+**Default Content-Type**: `text/html; charset=utf-8`
+**Description**: Send a `302` response to redirect the client to a different path
+
+```python
+from sanic.response import redirect
+
+@app.route("/")
+async def handler(request):
+ return redirect("/login")
+```
+
+:::
+::: tab Empty
+
+**Default Content-Type**: N/A
+**Description**: For responding with an empty message as defined by [RFC 2616](https://tools.ietf.org/search/rfc2616#section-7.2.1)
+
+```python
+from sanic.response import empty
+
+@app.route("/")
+async def handler(request):
+ return empty()
+```
+
+Defaults to a `204` status. :::
+::::
+
+## Default status
+
+The default HTTP status code for the response is `200`. If you need to change it, it can be done by the response method.
+
+
+```python
+@app.post("/")
+async def create_new(request):
+ new_thing = await do_create(request)
+ return json({"created": True, "id": new_thing.thing_id}, status=201)
+```
From e38cf5b16d04636a0fcf310a65e9a4a4aee6ce3f Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:22 +0300
Subject: [PATCH 080/776] New translations routing.md (Japanese)
---
src/ja/guide/basics/routing.md | 293 ++++++++++++++++++++++++---------
1 file changed, 213 insertions(+), 80 deletions(-)
diff --git a/src/ja/guide/basics/routing.md b/src/ja/guide/basics/routing.md
index 9f0a31d335..a8289a3073 100644
--- a/src/ja/guide/basics/routing.md
+++ b/src/ja/guide/basics/routing.md
@@ -4,8 +4,7 @@
これまでに様々な形の装飾家を見てきました。
-でも何なの?どうやって使うのか?
-:--:1
+But what is it? And how do we use it? :--:1
```python
@app.route("/stairway")
...
@@ -24,8 +23,7 @@
ハンドラをエンドポイントに接続する最も基本的な方法は、`app.add_route()`を使用することです。
-詳細については、[API docs](https://sanic.readthedocs.io/en/stable/sanic/api_reference.html#sanic.app.Sanic.url_for)を参照してください。
-:--:1
+詳細については、[API docs](https://sanic.readthedocs.io/en/stable/sanic/api_reference.html#sanic.app.Sanic.url_for)を参照してください。 :--:1 :--:1
```python
async def handler(request):
return text("OK")
@@ -36,8 +34,7 @@ app.add_route(handler, "/test")
---:1
-デフォルトでは、ルートはHTTP`GET`コールとして使用できます。1つ以上のHTTPメソッドに応答するようにハンドラを変更できます。
-:--:1
+デフォルトでは、ルートはHTTP`GET`コールとして使用できます。 1つ以上のHTTPメソッドに応答するようにハンドラを変更できます。 :--:1 :--:1
```python
app.add_route(
handler,
@@ -49,8 +46,7 @@ app.add_route(
---:1
-デコレータ構文を使用する場合、前の例はこれと同じです。
-:--:1
+でも何なの?どうやって使うのか? :--:1
```python
@app.route('/test', methods=["POST", "PUT"])
async def handler(request):
@@ -71,8 +67,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) :::
::: tab POST
```python
@@ -81,8 +76,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) :::
::: tab PUT
```python
@@ -91,8 +85,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) :::
::: tab PATCH
```python
@@ -101,8 +94,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) :::
::: tab DELETE
```python
@@ -111,8 +103,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) :::
::: tab HEAD
```python
@@ -121,8 +112,7 @@ async def handler(request):
return empty()
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) :::
::: tab OPTIONS
```python
@@ -131,12 +121,10 @@ async def handler(request):
return empty()
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS) :::
::::
-::: warning
-デフォルトでは、Sanic は安全でない HTTP メソッド (`POST`、`PUT`、`PATCH`) で受信したリクエストボディ**のみ**を消費します。他のメソッドでHTTPリクエストのデータを受け取りたい場合は、以下の2つのオプションのいずれかを実行する必要があります。
+::: warning デフォルトでは、Sanic は安全でない HTTP メソッド (`POST`、`PUT`、`PATCH`) で受信したリクエストボディ**のみ**を消費します。 他のメソッドでHTTPリクエストのデータを受け取りたい場合は、以下の2つのオプションのいずれかを実行する必要があります。
**オプション#1 - `ignore_body`を使用してSanicにボディを消費するように指示する。**
```python
@@ -157,8 +145,7 @@ async def handler(request: Request):
---:1
-Sanicでは、パターンマッチングやURLパスからの値の抽出が可能です。これらのパラメータは、キーワード引数としてルートハンドラに挿入されます。
-:--:1
+Sanicでは、パターンマッチングやURLパスからの値の抽出が可能です。 これらのパラメータは、キーワード引数としてルートハンドラに挿入されます。 :--:1 :--:1
```python
@app.get("/tag/")
async def tag_handler(request, tag):
@@ -168,8 +155,7 @@ async def tag_handler(request, tag):
---:1
-パラメータの型を宣言できます。これはマッチング時に強制され、変数を型キャストします。
-:--:1
+パラメータの型を宣言できます。 これはマッチング時に強制され、変数を型キャストします。 :--:1 :--:1
```python
@app.get("/foo/")
async def uuid_handler(request, foo_id: UUID):
@@ -194,10 +180,31 @@ async def handler(request, foo: str):
- `/path/to/Bob`
- `/path/to/Python%203`
+Beginning in v22.3 `str` will *not* match on empty strings. See `strorempty` for this behavior.
-以前のバージョンのSanicでは、この形式は非推奨となり、v21.12で削除される予定です。
:::
-::: tab int
+::: tab strorempty
+
+```python
+async def handler(request, ws):
+ messgage = "Start"
+ while True:
+ await ws.send(message)
+ message = ws.recv()
+
+app.add_websocket_route(handler, "/test")
+```
+**Regular expression applied**: `r"[^/]*")`
+**Cast type**: `str`
+**Example matches**:
+- `/path/to/Bob`
+- `/path/to/Python%203`
+- `/path/to/`
+
+Unlike the `str` path parameter type, `strorempty` can also match on an empty string path segment.
+
+以前のバージョンのSanicでは、この形式は非推奨となり、v21.12で削除される予定です。 :::
+::: tab alpha
```python
@app.route("/path/to/")
@@ -210,8 +217,7 @@ async def handler(request, foo: int):
- `/path/to/10`
- `/path/to/-10`
-_Does not match float, hex, octal, etc_
-:::
+_Does not match float, hex, octal, etc_ :::
::: tab float
```python
@@ -226,7 +232,6 @@ async def handler(request, foo: float):
- `/path/to/-10`
- `/path/to/1.5`
-以前のバージョンのSanicでは、この形式は非推奨となり、v21.12で削除される予定です。
:::
::: tab alpha
@@ -241,8 +246,7 @@ async def handler(request, foo: str):
- `/path/to/Bob`
- `/path/to/Python`
-_Does not match a digit, or a space or other special character_
-:::
+_Does not match a digit, or a space or other special character_ :::
::: tab slug
```python
@@ -271,10 +275,9 @@ async def handler(request, foo: str):
- `/path/to/hello.txt`
- `/path/to/hello/world.txt`
-::: warning
-これは`/`で一致するため、`path`を使用するパターンを慎重に徹底的にテストして、別のエンドポイント向けのトラフィックをキャプチャしないようにする必要があります。
-:::
+::: warning これは`/`で一致するため、`path`を使用するパターンを慎重に徹底的にテストして、別のエンドポイント向けのトラフィックをキャプチャしないようにする必要があります。 :::
::: tab ymd
+::: ::: tab ymd
```python
@app.route("/path/to/")
@@ -284,8 +287,7 @@ async def handler(request, foo: datetime.date):
**Regular expression applied**: `r"^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))"`
**Cast type**: `datetime.date`
**Example matches**:
-- `/path/to/2021-03-28`
-:::
+- `/path/to/2021-03-28` :::
::: tab uuid
@@ -301,6 +303,152 @@ async def handler(request, foo: UUID):
:::
+複雑なルーティングと比較すると、上記の例は単純すぎることが多く、まったく異なるルーティングマッチングパターンを使用するため、ここではregexマッチングの高度な使用方法について詳しく説明します。
+
+```python
+@app.websocket("/test")
+async def handler(request, ws):
+ messgage = "Start"
+ while True:
+ await ws.send(message)
+ message = ws.recv()
+```
+ルートの一部を照合する場合があります。
+
+
+
+
+ definition
+
+
+
+ example
+
+
+
+ filename
+
+
+
+ extension
+
+
+
+
+
+ \
+
+
+
+ page.txt
+
+
+
+ "page"
+
+
+
+ "txt"
+
+
+
+
+
+ \
+
+
+
+ cat.jpg
+
+
+
+ "cat"
+
+
+
+ "jpg"
+
+
+
+
+
+ \
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | cat.jpg | "cat" | "jpg"
+
+
+
+
+
+
+
+
+
+ 123.txt
+
+
+
+ 123
+
+
+
+ "txt"
+
+
+
+
+
+
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | 123.svg | 123 | "svg"
+
+
+
+
+
+
+
+
+
+ 3.14.tar.gz
+
+
+
+ 3.14
+
+
+
+ "tar.gz"
+
+
+
+
+File extensions can be matched using the special `ext` parameter type. It uses a special format that allows you to specify other types of parameter types as the file name, and one or more specific extensions as shown in the example table above.
+
+さらに、これらはすべて許容可能です。
+
+また、名前付き一致グループを使用する場合は、セグメントラベルと同じである必要があります。
+
::: tab regex
```python
@@ -313,9 +461,9 @@ async def handler(request, foo: str):
**Example matches**:
- `/path/to/2021-01-01`
-これにより、ユースケースの特定のマッチング・パターンを自由に定義できます。
-この例では、YYYY-MM-DD形式の日付を探しています。
+This gives you the freedom to define specific matching patterns for your use case.
+これにより、ユースケースの特定のマッチング・パターンを自由に定義できます。 この例では、YYYY-MM-DD形式の日付を探しています。
::::
@@ -323,9 +471,9 @@ async def handler(request, foo: str):
-複雑なルーティングと比較すると、上記の例は単純すぎることが多く、まったく異なるルーティングマッチングパターンを使用するため、ここではregexマッチングの高度な使用方法について詳しく説明します。
+More often than not, compared with complex routing, the above example is too simple, and we use a completely different routing matching pattern, so here we will explain the advanced usage of regex matching in detail.
-ルートの一部を照合する場合があります。
+Sometimes, you want to match a part of a route:
```text
/image/123456789.jpg
@@ -337,7 +485,7 @@ async def handler(request, foo: str):
app.route(r"/image/\d+)\.jpg>")
```
-さらに、これらはすべて許容可能です。
+また、1つのクエリキーに複数の値を渡すこともサポートされています。 :--:1
```python
@app.get(r"/") # matching on the full pattern
@@ -346,7 +494,7 @@ app.route(r"/image/\d+)\.jpg>")
@app.get(r"/[a-z]{3}).(?:txt)>") # defining a single named matching group, with one or more non-matching groups
```
-また、名前付き一致グループを使用する場合は、セグメントラベルと同じである必要があります。
+Also, if using a named matching group, it must be the same as the segment label.
```python
@app.get(r"/\d+).jpg>") # OK
@@ -359,14 +507,13 @@ app.route(r"/image/\d+)\.jpg>")
---:1
-Sanicは、ハンドラメソッド名`app.url_for()`に基づいてURLを生成するメソッドを提供しています。これは、アプリケーションへのURLパスをハードコーディングしない場合に便利です。代わりに、ハンドラ名を参照することができます。
-:--:1
+Sanicは、ハンドラメソッド名`app.url_for()`に基づいてURLを生成するメソッドを提供しています。 これは、アプリケーションへのURLパスをハードコーディングしない場合に便利です。 代わりに、ハンドラ名を参照することができます。 :--:1
```python
@app.route('/')
async def index(request):
# generate a URL for the endpoint `post_handler`
url = app.url_for('post_handler', post_id=5)
-
+
# Redirect to `/posts/5`
return redirect(url)
@@ -378,8 +525,7 @@ async def post_handler(request, post_id):
---:1
-任意の数のキーワード引数を渡すことができます。_not_a要求パラメータであるものはすべて、クエリ文字列の一部として実装されます。
-:--:1
+任意の数のキーワード引数を渡すことができます。 _not_a要求パラメータであるものはすべて、クエリ文字列の一部として実装されます。 :--:1 :--:1
```python
>>> app.url_for(
"post_handler",
@@ -393,8 +539,7 @@ async def post_handler(request, post_id):
---:1
-また、1つのクエリキーに複数の値を渡すこともサポートされています。
-:--:1
+Also supported is passing multiple values for a single query key. :--:1
```python
>>> app.url_for(
"post_handler",
@@ -430,8 +575,7 @@ See [API Docs]() for more details.
---:1
-カスタムルート名は、ルートの登録時に`name`引数を渡すことで使用できます。
-:--:1
+カスタムルート名は、ルートの登録時に`name`引数を渡すことで使用できます。 :--:1 :--:1
```python
@app.get("/get", name="get_handler")
def handler(request):
@@ -441,8 +585,7 @@ def handler(request):
---:1
-ここで、このカスタム名を使用してURLを取得します。
-:--:1
+ここで、このカスタム名を使用してURLを取得します。 :--:1
```python
>>> app.url_for("get_handler", foo="bar")
'/get?foo=bar'
@@ -453,14 +596,13 @@ def handler(request):
---:1
-WebsocketルーティングはHTTPメソッドと同様に動作します。
-:--:1
+WebsocketルーティングはHTTPメソッドと同様に動作します。 :--:1 :--:1
```python
async def handler(request, ws):
- messgage = "Start"
+ message = "Start"
while True:
await ws.send(message)
- message = ws.recv()
+ message = await ws.recv()
app.add_websocket_route(handler, "/test")
```
@@ -468,15 +610,14 @@ app.add_websocket_route(handler, "/test")
---:1
-便利なデコレーターも付いています。
-:--:1
+It also has a convenience decorator. :--:1
```python
@app.websocket("/test")
async def handler(request, ws):
- messgage = "Start"
+ message = "Start"
while True:
await ws.send(message)
- message = ws.recv()
+ message = await ws.recv()
```
:---
@@ -487,7 +628,7 @@ async def handler(request, ws):
---:1
-Sanicルートは、末尾のスラッシュがあるかどうかに厳密に一致するように設定できます。これはいくつかのレベルで設定でき、次の優先順位に従います。
+Sanicルートは、末尾のスラッシュがあるかどうかに厳密に一致するように設定できます。 これはいくつかのレベルで設定でき、次の優先順位に従います。
1. Route
2. Blueprint
@@ -542,8 +683,7 @@ Sanicから静的ファイルを提供するには、`app.static()`を使用し
1. ファイルが提供されるルート
2. サーバー上のファイルへのパス
-詳しくは[API docs]()を見てください。
-:--:1
+詳しくは[API docs]()を見てください。 :--:1 :--:1
```python
app.static("/static", "/path/to/directory")
```
@@ -551,8 +691,7 @@ app.static("/static", "/path/to/directory")
---:1
-個々のファイルを提供することもできます。
-:--:1
+個々のファイルを提供することもできます。 :--:1 :--:1
```python
app.static("/", "/path/to/index.html")
```
@@ -560,8 +699,7 @@ app.static("/", "/path/to/index.html")
---:1
-また、エンドポイントに名前を付けると便利な場合もあります。
-:--:1
+また、エンドポイントに名前を付けると便利な場合もあります。 :--:1
```python
app.static(
"/user/uploads",
@@ -573,8 +711,7 @@ app.static(
---:1
-URLの取得は、ハンドラと同様に機能します。ただし、ディレクトリ内に特定のファイルが必要な場合は、`filename`引数を追加することもできます。
-:--:1
+URLの取得は、ハンドラと同様に機能します。 ただし、ディレクトリ内に特定のファイルが必要な場合は、`filename`引数を追加することもできます。 :--:1 :--:1
```python
>>> app.url_for(
"static",
@@ -594,8 +731,7 @@ URLの取得は、ハンドラと同様に機能します。ただし、ディ
```
:---
-::: tip
-複数の`static()`ルートを使用する場合は、手動で名前を付けることを推奨します。これにより、バグを発見するのが難しい可能性がほぼ確実に軽減されます。
+::: tip 複数の`static()`ルートを使用する場合は、手動で名前を付けることを推奨します。 これにより、バグを発見するのが難しい可能性がほぼ確実に軽減されます。
```python
app.static("/user/uploads", "/path/to/uploads", name="uploads")
@@ -604,11 +740,8 @@ app.static("/user/profile", "/path/to/profile", name="profile_pics")
:::
## ルートコンテキスト
-::: new NEW in v21.12
----:1
-ルートが定義されるとき、`ctx_` という接頭辞を持つキーワード引数をいくつでも追加することができます。これらの値はルートの `ctx` オブジェクトにインジェクションされます。
-:--:1
+---:1 ルートが定義されるとき、`ctx_` という接頭辞を持つキーワード引数をいくつでも追加することができます。 これらの値はルートの `ctx` オブジェクトにインジェクションされます。 :--:1 :--:1
```python
@app.get("/1", ctx_label="something")
async def handler1(request):
From 79d6eb49f91ae197eefa53fbcf31e54d7201747e Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:24 +0300
Subject: [PATCH 081/776] New translations routing.md (Korean)
---
src/ko/guide/basics/routing.md | 384 ++++++++++++++++++++++++---------
1 file changed, 280 insertions(+), 104 deletions(-)
diff --git a/src/ko/guide/basics/routing.md b/src/ko/guide/basics/routing.md
index c6a96fa1df..ea17f6cd4d 100644
--- a/src/ko/guide/basics/routing.md
+++ b/src/ko/guide/basics/routing.md
@@ -4,9 +4,7 @@
지금까지 우리는 이 데코레이터를 다양한 형태로 많이 보았습니다.
-그러나 이것은 뭘까요? 어떻게 사용할까요?
-
-:--:1
+그러나 이것은 뭘까요? 어떻게 사용할까요? :--:1
```python
@app.route("/stairway")
...
@@ -25,8 +23,7 @@
핸들러를 엔드포인트에 연결하는 가장 기본적인 방법은 `app.add_route()`를 사용하는 것입니다.
-자세한 내용은 [API 문서](https://sanic.readthedocs.io/en/stable/sanic/api_reference.html#sanic.app.Sanic.url_for)를 참조하세요.
-:--:1
+자세한 내용은 [API 문서](https://sanic.readthedocs.io/en/stable/sanic/api_reference.html#sanic.app.Sanic.url_for)를 참조하세요. :--:1
```python
async def handler(request):
return text("OK")
@@ -37,8 +34,7 @@ app.add_route(handler, "/test")
---:1
-기본적으로 경로는 HTTP 'GET' 호출로 사용할 수 있습니다. 하나 이상의 HTTP 메서드에 응답하도록 핸들러를 변경할 수 있습니다.
-:--:1
+기본적으로 경로는 HTTP 'GET' 호출로 사용할 수 있습니다. 하나 이상의 HTTP 메서드에 응답하도록 핸들러를 변경할 수 있습니다. :--:1
```python
app.add_route(
handler,
@@ -50,8 +46,7 @@ app.add_route(
---:1
-HTTP 메소드(HTTP methods)
-:--:1
+Websocket 라우팅은 HTTP 메서드와 유사하게 작동합니다. :--:1
```python
@app.route('/test', methods=["POST", "PUT"])
async def handler(request):
@@ -72,8 +67,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) :::
::: tab POST
```python
@@ -82,8 +76,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) :::
::: tab PUT
```python
@@ -92,8 +85,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) :::
::: tab PATCH
```python
@@ -102,8 +94,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) :::
::: tab DELETE
```python
@@ -112,8 +103,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) :::
::: tab HEAD
```python
@@ -122,8 +112,7 @@ async def handler(request):
return empty()
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) :::
::: tab OPTIONS
```python
@@ -132,17 +121,38 @@ async def handler(request):
return empty()
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS)
-:::
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS) :::
::::
+::: warning By default, Sanic will **only** consume the incoming request body on non-safe HTTP methods (`POST`, `PUT`, `PATCH`). If you want to receive data in the HTTP request on any other method, you will need to do one of the following two options:
+
+**Option #1 - Tell Sanic to consume the body using `ignore_body`**
+```python
+async def handler(request, ws):
+ messgage = "Start"
+ while True:
+ await ws.send(message)
+ message = ws.recv()
+
+app.add_websocket_route(handler, "/test")
+```
+
+**Option #2 - Manually consume the body in the handler using `receive_body`**
+```python
+@app.websocket("/test")
+async def handler(request, ws):
+ messgage = "Start"
+ while True:
+ await ws.send(message)
+ message = ws.recv()
+```
+:::
+
## 경로 매개 변수(Path parameters)
---:1
-Sanic은 패턴 일치를 허용하고 URL 경로에서 값을 추출 할 수 있습니다. 그런 다음 이러한 매개 변수는 경로 처리기에서 키워드 인수로 삽입됩니다.
-
-:--:1
+URL 검색은 핸들러와 유사하게 작동합니다. 그러나 디렉토리 내부에 특정 파일이 필요할 때 `filename` 인수를 추가할 수도 있습니다. :--:1
```python
@app.get("/tag/")
async def tag_handler(request, tag):
@@ -152,8 +162,7 @@ async def tag_handler(request, tag):
---:1
-매개 변수의 유형을 선언 할 수 있습니다. 일치 할 때 적용되며 변수를 형변환합니다.
-:--:1
+매개 변수의 유형을 선언 할 수 있습니다. 일치 할 때 적용되며 변수를 형변환합니다. :--:1
```python
@app.get("/foo/")
async def uuid_handler(request, foo_id: UUID):
@@ -172,71 +181,86 @@ async def uuid_handler(request, foo_id: UUID):
async def handler(request, foo: str):
...
```
-**적용된 정규 표현식**: `r"[^/]+")`
-**캐스트 타입**: `str`
-**일치하는 예시**:
+:::
+::: tab int
- `/path/to/Bob`
- `/path/to/Python%203`
+Beginning in v22.3 `str` will *not* match on empty strings. See `strorempty` for this behavior.
-Sanic의 이전 버전에서는 ``이었습니다. 해당 양식은 더 이상 사용되지 않으며 v21.12에서 제거됩니다.
+_부동 소수점, 16진수, 8진수, 기타는 매칭되지 않습니다._ :::
+::: tab float
-:::
-::: tab int
+```python
+@app.route("/path/to/")
+async def handler(request, foo: str):
+ ...
+```
+**적용된 정규 표현식**: `r"-?(?:\d+(?:\.\d*)?|\.\d+)")`
+**캐스트 타입**: `float`
+**일치하는 예시**:
+- `/path/to/Bob`
+- `/path/to/Python%203`
+- `/path/to/`
+
+Unlike the `str` path parameter type, `strorempty` can also match on an empty string path segment.
+
+**적용된 정규 표현식**: `r"[A-Za-z]+")`
+**캐스트 타입**: `str`
+**일치하는 예시**:
```python
@app.route("/path/to/")
async def handler(request, foo: int):
...
```
-**적용된 정규 표현식**: `r"-?\d+")`
-**캐스트 타입**: `int`
-**일치하는 예시**:
+_숫자나 공간 또는 기타 특수 문자는 매칭되지 않습니다_ :::
+::: tab slug
- `/path/to/10`
- `/path/to/-10`
-_부동 소수점, 16진수, 8진수, 기타는 매칭되지 않습니다._
-:::
-::: tab float
+**적용된 정규 표현식**: `r"[a-z0-9]+(?:-[a-z0-9]+)*")`
+**캐스트 타입**: `str`
+**일치하는 예시**:
```python
@app.route("/path/to/")
async def handler(request, foo: float):
...
```
-**적용된 정규 표현식**: `r"-?(?:\d+(?:\.\d*)?|\.\d+)")`
-**캐스트 타입**: `float`
+**적용된 정규 표현식**: `r"-?\d+")`
+**캐스트 타입**: `int`
**일치하는 예시**:
- `/path/to/10`
- `/path/to/-10`
- `/path/to/1.5`
-
-Sanic의 이전 버전에서는 ``이었습니다. 해당 양식은 더 이상 사용되지 않으며 v21.12에서 제거됩니다.
-:::
-::: tab alpha
+
+**적용된 정규 표현식**: `r"[^/].*?")`
+**캐스트 타입**: `str`
+**일치하는 예시**:
```python
@app.route("/path/to/")
async def handler(request, foo: str):
...
```
-**적용된 정규 표현식**: `r"[A-Za-z]+")`
+**적용된 정규 표현식**: `r"[^/]+")`
**캐스트 타입**: `str`
**일치하는 예시**:
- `/path/to/Bob`
- `/path/to/Python`
-_숫자나 공간 또는 기타 특수 문자는 매칭되지 않습니다_
-:::
-::: tab slug
+**적용된 정규 표현식**: `r"^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))"`
+**캐스트 타입**: `datetime.date`
+**일치하는 예시**:
```python
@app.route("/path/to/")
async def handler(request, article: str):
...
```
-**적용된 정규 표현식**: `r"[a-z0-9]+(?:-[a-z0-9]+)*")`
-**캐스트 타입**: `str`
+**적용된 정규 표현식**: `r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}"`
+**캐스트 타입**: `UUID`
**일치하는 예시**:
- `/path/to/some-news-story`
- `/path/to/or-has-digits-123`
@@ -249,16 +273,14 @@ async def handler(request, article: str):
async def handler(request, foo: str):
...
```
-**적용된 정규 표현식**: `r"[^/].*?")`
-**캐스트 타입**: `str`
-**일치하는 예시**:
+**Regular expression applied**: `r"[^/].*?")`
+**Cast type**: `str`
+**Example matches**:
- `/path/to/hello`
- `/path/to/hello.txt`
- `/path/to/hello/world.txt`
-::: warning
-여기선 `/`가 매칭되기 때문에, `path` 를 사용하는 패턴을 주의 깊게 검사해, 다른 엔드포인트의 트래픽을 포착하지 않도록 해야 합니다.
-:::
+::: warning 여기선 `/`가 매칭되기 때문에, `path` 를 사용하는 패턴을 주의 깊게 검사해, 다른 엔드포인트의 트래픽을 포착하지 않도록 해야 합니다. :::
::: tab ymd
```python
@@ -266,11 +288,10 @@ async def handler(request, foo: str):
async def handler(request, foo: datetime.date):
...
```
-**적용된 정규 표현식**: `r"^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))"`
-**캐스트 타입**: `datetime.date`
+**적용된 정규 표현식**: _whatever you insert_
+**캐스트 타입**: `str`
**일치하는 예시**:
-- `/path/to/2021-03-28`
-:::
+- `/path/to/2021-03-28` :::
::: tab uuid
@@ -279,13 +300,154 @@ async def handler(request, foo: datetime.date):
async def handler(request, foo: UUID):
...
```
-**적용된 정규 표현식**: `r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}"`
-**캐스트 타입**: `UUID`
-**일치하는 예시**:
+표시된 예에서 'YYYY-MM-DD' 형식의 날짜를 찾고 있습니다.
- `/path/to/123a123a-a12a-1a1a-a1a1-1a12a1a12345`
:::
+복잡한 라우팅에 비해 위의 예는 너무 단순하고 완전히 다른 라우팅 일치 패턴을 사용하므로 여기서는 정규식 일치의 고급 사용법에 대해 자세히 설명합니다.
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: UUID):
+ ...
+```
+때로는 경로의 일부를 일치시키고 싶을 때가 있습니다.
+
+
+
+
+ definition
+
+
+
+ example
+
+
+
+ filename
+
+
+
+ extension
+
+
+
+
+
+ \
+
+
+
+ page.txt
+
+
+
+ "page"
+
+
+
+ "txt"
+
+
+
+
+
+ \
+
+
+
+ cat.jpg
+
+
+
+ "cat"
+
+
+
+ "jpg"
+
+
+
+
+
+ \
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | cat.jpg | "cat" | "jpg"
+
+
+
+
+
+
+
+
+
+ 123.txt
+
+
+
+ 123
+
+
+
+ "txt"
+
+
+
+
+
+
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | 123.svg | 123 | "svg"
+
+
+
+
+
+
+
+
+
+ 3.14.tar.gz
+
+
+
+ 3.14
+
+
+
+ "tar.gz"
+
+
+
+
+File extensions can be matched using the special `ext` parameter type. It uses a special format that allows you to specify other types of parameter types as the file name, and one or more specific extensions as shown in the example table above.
+
+또한 다음 사항이 모두 허용되어야 합니다.
+
+또한 명명된 일치 그룹을 사용하는 경우 세그먼트 레이블과 동일해야 합니다.
+
::: tab regex
```python
@@ -293,22 +455,24 @@ async def handler(request, foo: UUID):
async def handler(request, foo: str):
...
```
-**적용된 정규 표현식**: _whatever you insert_
-**캐스트 타입**: `str`
-**일치하는 예시**:
+**Regular expression applied**: _whatever you insert_
+**Cast type**: `str`
+**Example matches**:
- `/path/to/2021-01-01`
이를 통해 사용 사례에 대한 특정 일치 패턴을 자유롭게 정의할 수 있습니다.
-표시된 예에서 'YYYY-MM-DD' 형식의 날짜를 찾고 있습니다.
+In the example shown, we are looking for a date that is in `YYYY-MM-DD` format.
::::
### 정규식 일치(Regex Matching)
-복잡한 라우팅에 비해 위의 예는 너무 단순하고 완전히 다른 라우팅 일치 패턴을 사용하므로 여기서는 정규식 일치의 고급 사용법에 대해 자세히 설명합니다.
-때로는 경로의 일부를 일치시키고 싶을 때가 있습니다.
+
+More often than not, compared with complex routing, the above example is too simple, and we use a completely different routing matching pattern, so here we will explain the advanced usage of regex matching in detail.
+
+Sometimes, you want to match a part of a route:
```text
/image/123456789.jpg
@@ -320,7 +484,7 @@ async def handler(request, foo: str):
app.route(r"/image/\d+)\.jpg>")
```
-또한 다음 사항이 모두 허용되어야 합니다.
+Further, these should all be acceptable:
```python
@app.get(r"/") # matching on the full pattern
@@ -329,27 +493,26 @@ app.route(r"/image/\d+)\.jpg>")
@app.get(r"/[a-z]{3}).(?:txt)>") # defining a single named matching group, with one or more non-matching groups
```
-또한 명명된 일치 그룹을 사용하는 경우 세그먼트 레이블과 동일해야 합니다.
+Also, if using a named matching group, it must be the same as the segment label.
```python
@app.get(r"/\d+).jpg>") # OK
@app.get(r"/\d+).jpg>") # NOT OK
```
-보다 일반적인 사용 방법은 [정규식 연산](https://docs.python.org/3/library/re.html)을 참조하세요.
+자세한 내용은 [API Docs]()를 참조하세요.
## URL 생성(Generating a URL)
---:1
-Sanic은 핸들러 메소드 이름: `app.url_for ()` 를 기반으로 URL을 생성하는 메소드를 제공합니다. 이는 앱에 URL 경로를 하드 코딩하지 않으려는 경우에 유용합니다. 대신 핸들러 이름 만 참조 할 수 있습니다.
-:--:1
+Sanic은 핸들러 메소드 이름: `app.url_for ()` 를 기반으로 URL을 생성하는 메소드를 제공합니다. 이는 앱에 URL 경로를 하드 코딩하지 않으려는 경우에 유용합니다. 대신 핸들러 이름 만 참조 할 수 있습니다. :--:1
```python
@app.route('/')
async def index(request):
# generate a URL for the endpoint `post_handler`
url = app.url_for('post_handler', post_id=5)
-
+
# Redirect to `/posts/5`
return redirect(url)
@@ -361,8 +524,7 @@ async def post_handler(request, post_id):
---:1
-임의의 수의 키워드 인수를 전달할 수 있습니다. 요청 매개 변수가 _아닌_ 모든 것은 쿼리 문자열의 일부로 구현됩니다.
-:--:1
+임의의 수의 키워드 인수를 전달할 수 있습니다. 요청 매개 변수가 _아닌_ 모든 것은 쿼리 문자열의 일부로 구현됩니다. :--:1
```python
>>> app.url_for(
"post_handler",
@@ -376,8 +538,7 @@ async def post_handler(request, post_id):
---:1
-또한 단일 쿼리 키에 대해 여러 값을 전달하는 것도 지원됩니다.
-:--:1
+또한 단일 쿼리 키에 대해 여러 값을 전달하는 것도 지원됩니다. :--:1
```python
>>> app.url_for(
"post_handler",
@@ -390,7 +551,7 @@ async def post_handler(request, post_id):
### 특수 키워드 인수(Special keyword arguments)
-자세한 내용은 [API Docs]()를 참조하세요.
+See [API Docs]() for more details.
```python
>>> app.url_for("post_handler", post_id=5, arg_one="one", _anchor="anchor")
@@ -413,8 +574,7 @@ async def post_handler(request, post_id):
---:1
-사용자 지정 경로 이름은 경로를 등록하는 동안 `name` 인수를 전달하여 사용할 수 있습니다.
-:--:1
+사용자 지정 경로 이름은 경로를 등록하는 동안 `name` 인수를 전달하여 사용할 수 있습니다. :--:1
```python
@app.get("/get", name="get_handler")
def handler(request):
@@ -424,8 +584,7 @@ def handler(request):
---:1
-이제 이 사용자 지정 이름을 사용하여 URL을 검색합니다.
-:--:1
+Now, use this custom name to retrieve the URL :--:1
```python
>>> app.url_for("get_handler", foo="bar")
'/get?foo=bar'
@@ -436,14 +595,13 @@ def handler(request):
---:1
-Websocket 라우팅은 HTTP 메서드와 유사하게 작동합니다.
-:--:1
+이제 이 사용자 지정 이름을 사용하여 URL을 검색합니다. :--:1
```python
async def handler(request, ws):
- messgage = "Start"
+ message = "Start"
while True:
await ws.send(message)
- message = ws.recv()
+ message = await ws.recv()
app.add_websocket_route(handler, "/test")
```
@@ -451,15 +609,14 @@ app.add_websocket_route(handler, "/test")
---:1
-편리한 데코레이터도 있습니다.
-:--:1
+편리한 데코레이터도 있습니다. :--:1
```python
@app.websocket("/test")
async def handler(request, ws):
- messgage = "Start"
+ message = "Start"
while True:
await ws.send(message)
- message = ws.recv()
+ message = await ws.recv()
```
:---
@@ -525,8 +682,7 @@ Sanic에서 정적 파일을 제공하려면, `app.static()` 을 사용하세요
1. 파일이 제공될 경로
2. 서버의 파일 경로
-자세한 내용은 [API Docs]()를 참고하세요.
-:--:1
+자세한 내용은 [API Docs]()를 참고하세요. :--:1
```python
app.static("/static", "/path/to/directory")
```
@@ -534,8 +690,7 @@ app.static("/static", "/path/to/directory")
---:1
-개별 파일을 제공할 수도 있습니다.
-:--:1
+개별 파일을 제공할 수도 있습니다. :--:1
```python
app.static("/", "/path/to/index.html")
```
@@ -543,8 +698,7 @@ app.static("/", "/path/to/index.html")
---:1
-때로는 엔드포인트의 이름을 지정하는 것이 도움이 됩니다.
-:--:1
+It is also sometimes helpful to name your endpoint :--:1
```python
app.static(
"/user/uploads",
@@ -556,8 +710,7 @@ app.static(
---:1
-URL 검색은 핸들러와 유사하게 작동합니다. 그러나 디렉토리 내부에 특정 파일이 필요할 때 `filename` 인수를 추가할 수도 있습니다.
-:--:1
+Retrieving the URLs works similar to handlers. But, we can also add the `filename` argument when we need a specific file inside a directory. :--:1
```python
>>> app.url_for(
"static",
@@ -577,10 +730,33 @@ URL 검색은 핸들러와 유사하게 작동합니다. 그러나 디렉토리
```
:---
-::: tip
-여러 `static()` 경로를 사용하려는 경우, 수동으로 이름을 지정하는 것이 *매우* 좋습니다. 이것은 버그를 발견하기 어려운 잠재적 가능성을 거의 확실히 완화할 것입니다.
+::: tip 여러 `static()` 경로를 사용하려는 경우, 수동으로 이름을 지정하는 것이 *매우* 좋습니다. 이것은 버그를 발견하기 어려운 잠재적 가능성을 거의 확실히 완화할 것입니다.
```python
app.static("/user/uploads", "/path/to/uploads", name="uploads")
app.static("/user/profile", "/path/to/profile", name="profile_pics")
```
+:::
+
+## Route context
+
+---:1 When a route is defined, you can add any number of keyword arguments with a `ctx_` prefix. These values will be injected into the route `ctx` object. :--:1
+```python
+@app.get("/1", ctx_label="something")
+async def handler1(request):
+ ...
+
+@app.get("/2", ctx_label="something")
+async def handler2(request):
+ ...
+
+@app.get("/99")
+async def handler99(request):
+ ...
+
+@app.on_request
+async def do_something(request):
+ if request.route.ctx.label == "something":
+ ...
+```
+:---
From a878fac02af340b0b294392208fb1fb69be24a58 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:25 +0300
Subject: [PATCH 082/776] New translations routing.md (Chinese Simplified)
---
src/zh/guide/basics/routing.md | 509 ++++++++++++++-------------------
1 file changed, 220 insertions(+), 289 deletions(-)
diff --git a/src/zh/guide/basics/routing.md b/src/zh/guide/basics/routing.md
index 71ce9fe9f1..53999fffb7 100644
--- a/src/zh/guide/basics/routing.md
+++ b/src/zh/guide/basics/routing.md
@@ -2,12 +2,10 @@
---:1
-到目前为止,我们已经接触了各式各样的装饰器,但是这些装饰器是干什么用的?我们该如何使用它?
-
-:--:1
+So far we have seen a lot of this decorator in different forms.
+But what is it? 我们该如何使用它? :--:1
```python
-
@app.route("/stairway")
...
@@ -20,8 +18,12 @@
...
-```
+@app.get("/to")
+...
+@app.post("/heaven")
+...
+```
:---
## 添加路由(Adding a route)
@@ -30,8 +32,7 @@
将响应函数进行挂载的最基本方式就是使用 `app.add_route()`,具体的细节请查看 [API 文档](https://sanic.readthedocs.io/en/stable/sanic/api_reference.html#sanic.app.Sanic.url_for)
-:--:1
-
+您可以在 [API Docs](https://sanic.readthedocs.io/en/stable/sanic/api_reference.html#sanic.app.Sanic.url_for) 查看更多详细信息。 :--:1
```python
async def handler(request):
return text("OK")
@@ -39,15 +40,11 @@ async def handler(request):
app.add_route(handler, "/test")
```
-
:---
---:1
-默认的情况下,路由会绑定监听 HTTP `GET` 请求方式, 您可以通过修改 `methods` 参数,从而达到使用一个响应函数响应 HTTP 的多种请求方式。
-
-:--:1
-
+By default, routes are available as an HTTP `GET` call. You can change a handler to respond to one or more HTTP methods. :--:1
```python
app.add_route(
handler,
@@ -55,30 +52,23 @@ app.add_route(
methods=["POST", "PUT"],
)
```
-
:---
---:1
-您也可以使用装饰器来进行路由绑定,下面是使用装饰器的方式进行路由绑定的例子,实现的效果和上一个例子相同。
-
-:--:1
-
+Using the decorator syntax, the previous example is identical to this. :--:1
```python
@app.route('/test', methods=["POST", "PUT"])
async def handler(request):
return text('OK')
```
-
:---
## HTTP 方法(HTTP methods)
-每一个标准的 HTTP 请求方式都对应封装了一个简单易用的装饰器:
-
-:::: tabs
+Each of the standard HTTP methods has a convenience decorator.
-::: tab GET
+::: tab PATCH
```python
@app.get('/test')
@@ -86,11 +76,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET)
-
-:::
-
-::: tab POST
+每一个标准的 HTTP 请求方式都对应封装了一个简单易用的装饰器:
```python
@app.post('/test')
@@ -98,11 +84,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)
-
-:::
-
-::: tab PUT
+https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
```python
@app.put('/test')
@@ -110,11 +92,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT)
-
-:::
-
-::: tab PATCH
+::: tab GET
```python
@app.patch('/test')
@@ -122,11 +100,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH)
-
-:::
-
-::: tab DELETE
+https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH
```python
@app.delete('/test')
@@ -134,11 +108,7 @@ async def handler(request):
return text('OK')
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE)
-
-:::
-
-::: tab HEAD
+https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD
```python
@app.head('/test')
@@ -146,11 +116,7 @@ async def handler(request):
return empty()
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD)
-
-:::
-
-::: tab OPTIONS
+::: tab POST
```python
@app.options('/test')
@@ -158,18 +124,11 @@ async def handler(request):
return empty()
```
-[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS)
+https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
-:::
-
-::::
-
-::: warning 注意
-
-默认情况下,Sanic 将 **仅** 在不安全的 HTTP 方法(`POST`、`PUT`、`PATCH`) 上使用传入的请求体。如果你想以任何其他方法中接收 HTTP 请求中的数据,您需要从以下两种方法中任选其一:
+默认情况下,Sanic 将 **仅** 在不安全的 HTTP 方法(`POST`、`PUT`、`PATCH`) 上使用传入的请求体。 如果你想以任何其他方法中接收 HTTP 请求中的数据,您需要从以下两种方法中任选其一:
**方法 #1 - 通过 `ignore_body` 告诉 Sanic 不要忽略请求体**
-
```python
@app.delete("/path", ignore_body=False)
async def handler(_):
@@ -177,43 +136,33 @@ async def handler(_):
```
**方法 #2 - 通过 `receive_body` 在请求中手动使用**
-
```python
@app.delete("/path")
async def handler(request: Request):
await request.receive_body()
```
-
:::
## 路由参数(Path parameters)
---:1
-Sanic 允许模式匹配,并从 URL 中提取值。然后将这些参数作为关键字参数传递到响应函数中。
-
-:--:1
-
+Sanic 允许模式匹配,并从 URL 中提取值。 These parameters are then injected as keyword arguments in the route handler. :--:1
```python
@app.get("/tag/")
async def tag_handler(request, tag):
return text("Tag - {}".format(tag))
```
-
:---
---:1
-您可以为路由参数指定类型,它将在匹配时进行强制类型转换。
-
-:--:1
-
+You can declare a type for the parameter. This will be enforced when matching, and also will type cast the variable. :--:1
```python
@app.get("/foo/")
async def uuid_handler(request, foo_id: UUID):
return text("UUID - {}".format(foo_id))
```
-
:---
### 匹配类型(Supported types)
@@ -227,90 +176,49 @@ async def uuid_handler(request, foo_id: UUID):
async def handler(request, foo: str):
...
```
-
-**使用的正则表达式**: `r"[^/]+")`
-
-**转换类型**: `str`
-
-**匹配示例**:
-
+**使用的正则表达式**: `r"[^/].*?")`
- `/path/to/Bob`
- `/path/to/Python%203`
-::: new v22.3 新特征
-
-`str` 将不再匹配空字符串, 更多信息请参照 `strorempty`
-
-:::
-
-::: tab "strorempty 🌟"
+Beginning in v22.3 `str` will *not* match on empty strings. See `strorempty` for this behavior.
-::: new v22.3 新特征
+::: tab PUT
```python
@app.route("/path/to/")
async def handler(request, foo: str):
...
```
-
-**使用正则表达式**: `r"[^/]*")`
-
-**转换类型**: `str`
-
-**匹配示例**:
-
+**使用的正则表达式**: _whatever you insert_
- `/path/to/Bob`
- `/path/to/Python%203`
- `/path/to/`
-与 `str` 不同,`strorempty` 还能够匹配空字符串路径
+Unlike the `str` path parameter type, `strorempty` can also match on an empty string path segment.
-:::
-
-::: tab int
+::: warning 注意
```python
@app.route("/path/to/")
async def handler(request, foo: int):
...
```
-
-**使用的正则表达式**: `r"-?\d+")`
-
-**转换类型**: `int`
-
-**匹配示例**:
-
+**使用的正则表达式**: `r"[a-z0-9]+(?:-[a-z0-9]+)*")`
- `/path/to/10`
-
- `/path/to/-10`
- _无法匹配 float,hex,octal,etc 等数字类型。_
-
-:::
-
-::: tab "float"
+无法匹配 float,hex,octal,etc 等数字类型。
```python
@app.route("/path/to/")
async def handler(request, foo: float):
...
```
-
**使用的正则表达式**: `r"-?(?:\d+(?:\.\d*)?|\.\d+)")`
-
-**转换类型**: `float`
-
-**匹配示例**:
-
- `/path/to/10`
- `/path/to/-10`
- `/path/to/1.5`
-在之前版本中,您应该这样写 ``。这种写法将在 v21.12 中被弃用
-
-:::
-
::: tab alpha
```python
@@ -318,40 +226,21 @@ async def handler(request, foo: float):
async def handler(request, foo: str):
...
```
-
-**使用的正则表达式**: `r"[A-Za-z]+")`
-
-**转换类型**: `str`
-
-**匹配示例**:
-
+**使用的正则表达式**: `r"^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))"`
- `/path/to/Bob`
-
- `/path/to/Python`
-_无法匹配数字,空格以及其他特殊字符。_
-
-:::
-
-::: tab "slug"
+该方法 _不_ 不支持 `path` 类型的参数。
```python
@app.route("/path/to/")
async def handler(request, article: str):
...
```
-
-**使用的正则表达式**: `r"[a-z0-9]+(?:-[a-z0-9]+)*")`
-
-**类型转换**: `str`
-
-**匹配示例**:
-
+**使用的正则表达式**: `r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}"`
- `/path/to/some-news-story`
- `/path/to/or-has-digits-123`
-:::
-
::: tab path
```python
@@ -359,40 +248,20 @@ async def handler(request, article: str):
async def handler(request, foo: str):
...
```
-
-**使用的正则表达式**: `r"[^/].*?")`
-
-**转换类型**: `str`
-
-**匹配示例**:
-
+**使用的正则表达式**: n/a
- `/path/to/hello`
- `/path/to/hello.txt`
- `/path/to/hello/world.txt`
-::: warning
-
-因为这将从 `/` 开始进行匹配,所以您应该小心使用,并测试您的正则表达式是否正确,以免匹配错误而调用了错误的响应函数。
-
-:::
-
-::: tab ymd
+::: warning Because this will match on `/`, you should be careful and thoroughly test your patterns that use `path` so they do not capture traffic intended for another endpoint. ::: tab "ext 🌟"
```python
@app.route("/path/to/")
async def handler(request, foo: datetime.date):
...
```
-
-**使用的正则表达式**: `r"^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))"`
-
-**转换类型**: `datetime.date`
-
-**匹配示例**:
-
-- `/path/to/2021-03-28`
-
-:::
+**类型转换**: `str`
+- /path/to/2021-03-28
::: tab uuid
@@ -401,47 +270,153 @@ async def handler(request, foo: datetime.date):
async def handler(request, foo: UUID):
...
```
-
-**使用的正则表达式**: `r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}"`
-
-**转换类型**: `UUID`
-
-**匹配示例**:
-
-`/path/to/123a123a-a12a-1a1a-a1a1-1a12a1a12345`
+**转换类型**: _varies_
+- `/path/to/123a123a-a12a-1a1a-a1a1-1a12a1a12345`
:::
-::: tab "ext 🌟"
-
-::: new v22.3 新特征
+**使用的正则表达式**: `r"[^/]+")`
```python
@app.route("/path/to/")
async def handler(request, foo: UUID):
...
```
+**转换类型**: `str`
-**使用的正则表达式**: n/a
-
-**转换类型**: _varies_
-
-**匹配示例**:
-
-| 定义 | 示例 | 文件名 | 拓展名 |
-| --------------------------------- | ----------- | -------- | ---------- |
-| \ | page.txt | `"page"` | `"txt"` |
-| \ | cat.jpg | `"cat"` | `"jpg"` |
-| \ | cat.jpg | `"cat"` | `"jpg"` |
-| | 123.txt | `123` | `"txt"` |
-| | 123.svg | `123` | `"svg"` |
-| | 3.14.tar.gz | `3.14` | `"tar.gz"` |
-
-可以使用特殊的 `ext` 参数类型匹配文件扩展名。它使用一种特殊的格式,允许您指定其他类型的参数类型作为文件名,以及一个或多个特定的扩展名,如上表所示。
+
+
+
+ 定义
+
+
+
+ 示例
+
+
+
+ 文件名
+
+
+
+ 拓展名
+
+
+
+
+
+ \
+
+
+
+ page.txt
+
+
+
+ "page"
+
+
+
+ "txt"
+
+
+
+
+
+ \
+
+
+
+ cat.jpg
+
+
+
+ "cat"
+
+
+
+ "jpg"
+
+
+
+
+
+ \
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | cat.jpg | "cat" | "jpg"
+
+
+
+
+
+
+
+
+
+ 123.txt
+
+
+
+ 123
+
+
+
+ "txt"
+
+
+
+
+
+
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | 123.svg | 123 | "svg"
+
+
+
+
+
+
+
+
+
+ 3.14.tar.gz
+
+
+
+ 3.14
+
+
+
+ "tar.gz"
+
+
+
+
+可以使用特殊的 `ext` 参数类型匹配文件扩展名。 它使用一种特殊的格式,允许您指定其他类型的参数类型作为文件名,以及一个或多个特定的扩展名,如上表所示。
-该方法 _不_ 不支持 `path` 类型的参数。
+::: new v22.3 新特征
-:::
+`str` 将不再匹配空字符串, 更多信息请参照 `strorempty`
::: tab regex
@@ -450,24 +425,22 @@ async def handler(request, foo: UUID):
async def handler(request, foo: str):
...
```
-
-**使用的正则表达式**: _whatever you insert_
-
-**转换类型**: `str`
-
-**匹配示例**:
-
+::: tab "strorempty 🌟"
- `/path/to/2021-01-01`
-该方法允许您使用自定义的匹配模式,在上面的示例中,我们通过指定的正则表达式,来匹配符合 `YYYY-MM-DD` 格式的路由参数。
+::: new v22.3 新特征
+
+**使用正则表达式**: `r"[^/]*")`
::::
### 正则匹配(Regex Matching)
-更多时候,相对于复杂的路由,以上示例还是过于简单了,由我们使用了和以前完全不同的路由匹配模式,所以在这里我们要详细的说明一下正则的进阶用法。
-有时,您希望匹配路由中的某一部分:
+
+**匹配示例**:
+
+与 `str` 不同,`strorempty` 还能够匹配空字符串路径
```text
/image/123456789.jpg
@@ -479,7 +452,7 @@ async def handler(request, foo: str):
app.route(r"/image/\d+)\.jpg>")
```
-更进一步,下面的这些匹配方式都是支持的:
+::: tab int
```python
@app.get(r"/") # 全模式匹配
@@ -488,24 +461,20 @@ app.route(r"/image/\d+)\.jpg>")
@app.get(r"/[a-z]{3}).(?:txt)>") # 用一个或多个不匹配组定义单个命名匹配组
```
-值得注意的是,如果您使用了命名的匹配组,它的名称必须与 `label` 相同
+**使用的正则表达式**: `r"-?\d+")`
```python
@app.get(r"/\d+).jpg>") # 正确示例
@app.get(r"/\d+).jpg>") # 错误示例
```
-更多的用方法请参考:[正则表达式操作](https://docs.python.org/zh-cn/3/library/re.html)
+**转换类型**: `int`
## 动态访问(Generating a URL)
---:1
-Sanic 提供了一种基于处理程序方法名生成 url 的方法:`app.url_for()`,您只需要函数名称即可实现响应函数之间的处理权力的移交。在您不希望将 url
-进行硬编码或希望响应函数之间具有层级关系的时候,这将非常有用。它的使用方法如下:
-
-:--:1
-
+Sanic 提供了一种基于处理程序方法名生成 url 的方法:`app.url_for()`,您只需要函数名称即可实现响应函数之间的处理权力的移交。 This is useful if you want to avoid hardcoding url paths into your app; instead, you can just reference the handler name. :--:1
```python
@app.route('/')
async def index(request):
@@ -520,15 +489,11 @@ async def index(request):
async def post_handler(request, post_id):
...
```
-
:---
---:1
-您可以传递任意数量的关键字参数,任何非路由参数的部分都会被是做为查询字符串的一部分
-
-:--:1
-
+You can pass any arbitrary number of keyword arguments. Anything that is _not_ a request parameter will be implemented as a part of the query string. :--:1
```python
>> > app.url_for(
"post_handler",
@@ -538,15 +503,11 @@ async def post_handler(request, post_id):
)
'/posts/5?arg_one=one&arg_two=two'
```
-
:---
---:1
-该方法同样支持为一个键名传递多个值。
-
-:--:1
-
+该方法同样支持为一个键名传递多个值。 :--:1
```python
>> > app.url_for(
"post_handler",
@@ -555,12 +516,11 @@ async def post_handler(request, post_id):
)
'/posts/5?arg_one=one&arg_one=two'
```
-
:---
### 特殊关键字参数(Special keyword arguments)
-您可以在 [API Docs](https://sanic.readthedocs.io/en/stable/sanic/api_reference.html#sanic.app.Sanic.url_for) 查看更多详细信息。
+**使用的正则表达式**: `r"[A-Za-z]+")`
```python
>> > app.url_for("post_handler", post_id=5, arg_one="one", _anchor="anchor")
@@ -584,39 +544,28 @@ async def post_handler(request, post_id):
---:1
-在注册路由的时候,可以通过给定 `name` 参数来自定义路由名称
-
-:--:1
-
+在注册路由的时候,可以通过给定 `name` 参数来自定义路由名称 :--:1
```python
@app.get("/get", name="get_handler")
def handler(request):
return text("OK")
```
-
:---
---:1
-现在,您可以通过自定义的名称进行路由匹配。
-
-:--:1
-
+::: tab "slug"
```python
>> > app.url_for("get_handler", foo="bar")
'/get?foo=bar'
```
-
:---
## Websocket 路径(Websockets routes)
---:1
-Websocket 的工作方式和 HTTP 是类似的。
-
-:--:1
-
+Websocket 的工作方式和 HTTP 是类似的。 :--:1
```python
async def handler(request, ws):
messgage = "Start"
@@ -627,15 +576,11 @@ async def handler(request, ws):
app.add_websocket_route(handler, "/test")
```
-
:---
---:1
-它也具备有一个独立的装饰器。
-
-:--:1
-
+它也具备有一个独立的装饰器。 :--:1
```python
@app.websocket("/test")
async def handler(request, ws):
@@ -644,16 +589,16 @@ async def handler(request, ws):
await ws.send(message)
message = ws.recv()
```
-
:---
-具体的工作原理,我们会在之后的 [websocket](/zh/guide/advanced/websockets.md) 进行更多描述。
+**匹配示例**:
## 严格匹配分隔符(Strict slashes)
+
---:1
-Sanic 可以按需开启或关闭路由的严格匹配模式,开启后路由将会严格按照 `/` 作为分隔来进行路由匹配,您可以在以下几种方法中进行匹配,它们的优先级遵循:
+Sanic 可以按需开启或关闭路由的严格匹配模式,开启后路由将会严格按照 `/` 作为分隔来进行路由匹配,您可以在以下几种方法中进行匹配,它们的优先级遵循: This can be configured at a few levels and follows this order of precedence:
1. 路由(Route)
2. 蓝图(Blueprint)
@@ -661,7 +606,6 @@ Sanic 可以按需开启或关闭路由的严格匹配模式,开启后路由
4. 应用(Application)
:--:1
-
```python
# 为应用程序下所有的路由都启用严格匹配模式
app = Sanic(__file__, strict_slashes=True)
@@ -696,49 +640,36 @@ bp2 = Blueprint(
# set the strict slashes check to false
group = Blueprint.group([bp1, bp2], strict_slashes=True)
```
-
:---
## 静态文件(Static files)
---:1
-为了确保 Sanic 可以正确代理静态文件,请使用 `app.static()` 方法进行路由分配。
-
-在这里,参数的顺序十分重要
-
-第一个参数是静态文件所需要匹配的路由
-
-第二个参数是渲染文件所在的文件(夹)路径
+**转换类型**: `datetime.date`
-更多详细用法请参考 [API docs]()
+**匹配示例**:
-:--:1
+1. Route the files will be served from
+2. Path to the files on the server
+更多详细用法请参考 [API docs]() :--:1
```python
app.static("/static", "/path/to/directory")
```
-
:---
---:1
-您也可以提供单独的文件
-
-:--:1
-
+您也可以提供单独的文件 :--:1
```python
app.static("/", "/path/to/index.html")
```
-
:---
---:1
-它同样支持自定义名称,来帮助您实现快速访问
-
-:--:1
-
+It is also sometimes helpful to name your endpoint :--:1
```python
app.static(
"/user/uploads",
@@ -746,16 +677,12 @@ app.static(
name="uploads",
)
```
-
:---
---:1
-检索 URL 的流程和响应函数类似,但是当您需要特定的文件的时候,可以通过添加 `filename` 参数来达到效果。
-
-:--:1
-
-````python
+Retrieving the URLs works similar to handlers. But, we can also add the `filename` argument when we need a specific file inside a directory. :--:1
+```python
>> > app.url_for(
"static",
name="static",
@@ -771,28 +698,20 @@ app.static(
)
'/user/uploads/image.png'
-````
-
+```
:---
-::: tip
-
-如果您想要设置多个静态文件路由,我们*强烈建议*您手动为 `static()` 加上 `name` 参数。可以确定的是,这样做可以减少一些潜在且隐蔽的 bug。
+如果您想要设置多个静态文件路由,我们*强烈建议*您手动为 `static()` 加上 `name` 参数。 可以确定的是,这样做可以减少一些潜在且隐蔽的 bug。
```python
app.static("/user/uploads", "/path/to/uploads", name="uploads")
app.static("/user/profile", "/path/to/profile", name="profile_pics")
-
```
+:::
## 路由上下文(Route context)
----:1
-
-定义路由时,您可以添加任意数量的带有 `ctx_` 前缀的关键字参数。这些值将被注入到路由的 `ctx` 对象中。
-
-:--:1
-
+定义路由时,您可以添加任意数量的带有 `ctx_` 前缀的关键字参数。 这些值将被注入到路由的 `ctx` 对象中。 :--:1
```python
@app.get("/1", ctx_label="something")
async def handler1(request):
@@ -810,6 +729,18 @@ async def handler99(request):
async def do_something(request):
if request.route.ctx.label == "something":
...
-```
+@app.get("/2", ctx_label="something")
+async def handler2(request):
+ ...
+
+@app.get("/99")
+async def handler99(request):
+ ...
+
+@app.on_request
+async def do_something(request):
+ if request.route.ctx.label == "something":
+ ...
+```
:---
From 3026b2a2f49aaf074a286e831d2a201402639730 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:27 +0300
Subject: [PATCH 083/776] New translations routing.md (Portuguese, Brazilian)
---
src/pt/guide/basics/routing.md | 757 +++++++++++++++++++++++++++++++++
1 file changed, 757 insertions(+)
create mode 100644 src/pt/guide/basics/routing.md
diff --git a/src/pt/guide/basics/routing.md b/src/pt/guide/basics/routing.md
new file mode 100644
index 0000000000..d107780b16
--- /dev/null
+++ b/src/pt/guide/basics/routing.md
@@ -0,0 +1,757 @@
+# Routing
+
+---:1
+
+So far we have seen a lot of this decorator in different forms.
+
+But what is it? And how do we use it? :--:1
+```python
+@app.route("/stairway")
+...
+
+@app.get("/to")
+...
+
+@app.post("/heaven")
+...
+```
+:---
+
+## Adding a route
+
+---:1
+
+The most basic way to wire up a handler to an endpoint is with `app.add_route()`.
+
+See [API docs](https://sanic.readthedocs.io/en/stable/sanic/api_reference.html#sanic.app.Sanic.url_for) for more details. :--:1
+```python
+async def handler(request):
+ return text("OK")
+
+app.add_route(handler, "/test")
+```
+:---
+
+---:1
+
+By default, routes are available as an HTTP `GET` call. You can change a handler to respond to one or more HTTP methods. :--:1
+```python
+app.add_route(
+ handler,
+ '/test',
+ methods=["POST", "PUT"],
+)
+```
+:---
+
+---:1
+
+Using the decorator syntax, the previous example is identical to this. :--:1
+```python
+@app.route('/test', methods=["POST", "PUT"])
+async def handler(request):
+ return text('OK')
+```
+:---
+
+## HTTP methods
+
+Each of the standard HTTP methods has a convenience decorator.
+
+:::: tabs
+::: tab GET
+
+```python
+@app.get('/test')
+async def handler(request):
+ return text('OK')
+```
+
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) :::
+::: tab POST
+
+```python
+@app.post('/test')
+async def handler(request):
+ return text('OK')
+```
+
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) :::
+::: tab PUT
+
+```python
+@app.put('/test')
+async def handler(request):
+ return text('OK')
+```
+
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) :::
+::: tab PATCH
+
+```python
+@app.patch('/test')
+async def handler(request):
+ return text('OK')
+```
+
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) :::
+::: tab DELETE
+
+```python
+@app.delete('/test')
+async def handler(request):
+ return text('OK')
+```
+
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) :::
+::: tab HEAD
+
+```python
+@app.head('/test')
+async def handler(request):
+ return empty()
+```
+
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) :::
+::: tab OPTIONS
+
+```python
+@app.options('/test')
+async def handler(request):
+ return empty()
+```
+
+[MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS) :::
+::::
+
+::: warning By default, Sanic will **only** consume the incoming request body on non-safe HTTP methods (`POST`, `PUT`, `PATCH`). If you want to receive data in the HTTP request on any other method, you will need to do one of the following two options:
+
+**Option #1 - Tell Sanic to consume the body using `ignore_body`**
+```python
+@app.delete("/path", ignore_body=False)
+async def handler(_):
+ ...
+```
+
+**Option #2 - Manually consume the body in the handler using `receive_body`**
+```python
+@app.delete("/path")
+async def handler(request: Request):
+ await request.receive_body()
+```
+:::
+
+## Path parameters
+
+---:1
+
+Sanic allows for pattern matching, and for extracting values from URL paths. These parameters are then injected as keyword arguments in the route handler. :--:1
+```python
+@app.get("/tag/")
+async def tag_handler(request, tag):
+ return text("Tag - {}".format(tag))
+```
+:---
+
+---:1
+
+You can declare a type for the parameter. This will be enforced when matching, and also will type cast the variable. :--:1
+```python
+@app.get("/foo/")
+async def uuid_handler(request, foo_id: UUID):
+ return text("UUID - {}".format(foo_id))
+```
+:---
+
+### Supported types
+
+:::: tabs
+
+::: tab str
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: str):
+ ...
+```
+**Regular expression applied**: `r"[^/]+")`
+**Cast type**: `str`
+**Example matches**:
+- `/path/to/Bob`
+- `/path/to/Python%203`
+
+Beginning in v22.3 `str` will *not* match on empty strings. See `strorempty` for this behavior.
+
+:::
+::: tab strorempty
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: str):
+ ...
+```
+**Regular expression applied**: `r"[^/]*")`
+**Cast type**: `str`
+**Example matches**:
+- `/path/to/Bob`
+- `/path/to/Python%203`
+- `/path/to/`
+
+Unlike the `str` path parameter type, `strorempty` can also match on an empty string path segment.
+
+*Added in v22.3* :::
+::: tab int
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: int):
+ ...
+```
+**Regular expression applied**: `r"-?\d+")`
+**Cast type**: `int`
+**Example matches**:
+- `/path/to/10`
+- `/path/to/-10`
+
+_Does not match float, hex, octal, etc_ :::
+::: tab float
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: float):
+ ...
+```
+**Regular expression applied**: `r"-?(?:\d+(?:\.\d*)?|\.\d+)")`
+**Cast type**: `float`
+**Example matches**:
+- `/path/to/10`
+- `/path/to/-10`
+- `/path/to/1.5`
+
+:::
+::: tab alpha
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: str):
+ ...
+```
+**Regular expression applied**: `r"[A-Za-z]+")`
+**Cast type**: `str`
+**Example matches**:
+- `/path/to/Bob`
+- `/path/to/Python`
+
+_Does not match a digit, or a space or other special character_ :::
+::: tab slug
+
+```python
+@app.route("/path/to/")
+async def handler(request, article: str):
+ ...
+```
+**Regular expression applied**: `r"[a-z0-9]+(?:-[a-z0-9]+)*")`
+**Cast type**: `str`
+**Example matches**:
+- `/path/to/some-news-story`
+- `/path/to/or-has-digits-123`
+
+:::
+::: tab path
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: str):
+ ...
+```
+**Regular expression applied**: `r"[^/].*?")`
+**Cast type**: `str`
+**Example matches**:
+- `/path/to/hello`
+- `/path/to/hello.txt`
+- `/path/to/hello/world.txt`
+
+::: warning Because this will match on `/`, you should be careful and thoroughly test your patterns that use `path` so they do not capture traffic intended for another endpoint. :::
+::: tab ymd
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: datetime.date):
+ ...
+```
+**Regular expression applied**: `r"^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))"`
+**Cast type**: `datetime.date`
+**Example matches**:
+- `/path/to/2021-03-28` :::
+
+::: tab uuid
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: UUID):
+ ...
+```
+**Regular expression applied**: `r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}"`
+**Cast type**: `UUID`
+**Example matches**:
+- `/path/to/123a123a-a12a-1a1a-a1a1-1a12a1a12345`
+
+:::
+
+::: tab ext
+
+```python
+@app.route("/path/to/")
+async def handler(request, foo: UUID):
+ ...
+```
+**Regular expression applied**: n/a
+**Cast type**: *varies*
+**Example matches**:
+
+
+
+
+ definition
+
+
+
+ example
+
+
+
+ filename
+
+
+
+ extension
+
+
+
+
+
+ \
+
+
+
+ page.txt
+
+
+
+ "page"
+
+
+
+ "txt"
+
+
+
+
+
+ \
+
+
+
+ cat.jpg
+
+
+
+ "cat"
+
+
+
+ "jpg"
+
+
+
+
+
+ \
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | cat.jpg | "cat" | "jpg"
+
+
+
+
+
+
+
+
+
+ 123.txt
+
+
+
+ 123
+
+
+
+ "txt"
+
+
+
+
+
+
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | 123.svg | 123 | "svg"
+
+
+
+
+
+
+
+
+
+ 3.14.tar.gz
+
+
+
+ 3.14
+
+
+
+ "tar.gz"
+
+
+
+
+File extensions can be matched using the special `ext` parameter type. It uses a special format that allows you to specify other types of parameter types as the file name, and one or more specific extensions as shown in the example table above.
+
+It does *not* support the `path` parameter type.
+
+*Added in v22.3* :::
+
+::: tab regex
+
+```python
+@app.route(r"/path/to/")
+async def handler(request, foo: str):
+ ...
+```
+**Regular expression applied**: _whatever you insert_
+**Cast type**: `str`
+**Example matches**:
+- `/path/to/2021-01-01`
+
+This gives you the freedom to define specific matching patterns for your use case.
+
+In the example shown, we are looking for a date that is in `YYYY-MM-DD` format.
+
+::::
+
+### Regex Matching
+
+
+
+More often than not, compared with complex routing, the above example is too simple, and we use a completely different routing matching pattern, so here we will explain the advanced usage of regex matching in detail.
+
+Sometimes, you want to match a part of a route:
+
+```text
+/image/123456789.jpg
+```
+
+If you wanted to match the file pattern, but only capture the numeric portion, you need to do some regex fun 😄:
+
+```python
+app.route(r"/image/\d+)\.jpg>")
+```
+
+Further, these should all be acceptable:
+
+```python
+@app.get(r"/") # matching on the full pattern
+@app.get(r"/") # defining a single matching group
+@app.get(r"/[a-z]{3}).txt>") # defining a single named matching group
+@app.get(r"/[a-z]{3}).(?:txt)>") # defining a single named matching group, with one or more non-matching groups
+```
+
+Also, if using a named matching group, it must be the same as the segment label.
+
+```python
+@app.get(r"/\d+).jpg>") # OK
+@app.get(r"/\d+).jpg>") # NOT OK
+```
+
+For more regular usage methods, please refer to [Regular expression operations](https://docs.python.org/3/library/re.html)
+
+## Generating a URL
+
+---:1
+
+Sanic provides a method to generate URLs based on the handler method name: `app.url_for()`. This is useful if you want to avoid hardcoding url paths into your app; instead, you can just reference the handler name. :--:1
+```python
+@app.route('/')
+async def index(request):
+ # generate a URL for the endpoint `post_handler`
+ url = app.url_for('post_handler', post_id=5)
+
+ # Redirect to `/posts/5`
+ return redirect(url)
+
+@app.route('/posts/')
+async def post_handler(request, post_id):
+ ...
+```
+:---
+
+---:1
+
+You can pass any arbitrary number of keyword arguments. Anything that is _not_ a request parameter will be implemented as a part of the query string. :--:1
+```python
+>>> app.url_for(
+ "post_handler",
+ post_id=5,
+ arg_one="one",
+ arg_two="two",
+)
+'/posts/5?arg_one=one&arg_two=two'
+```
+:---
+
+---:1
+
+Also supported is passing multiple values for a single query key. :--:1
+```python
+>>> app.url_for(
+ "post_handler",
+ post_id=5,
+ arg_one=["one", "two"],
+)
+'/posts/5?arg_one=one&arg_one=two'
+```
+:---
+
+### Special keyword arguments
+
+See [API Docs]() for more details.
+
+```python
+>>> app.url_for("post_handler", post_id=5, arg_one="one", _anchor="anchor")
+'/posts/5?arg_one=one#anchor'
+
+# _external requires you to pass an argument _server or set SERVER_NAME in app.config if not url will be same as no _external
+>>> app.url_for("post_handler", post_id=5, arg_one="one", _external=True)
+'//server/posts/5?arg_one=one'
+
+# when specifying _scheme, _external must be True
+>>> app.url_for("post_handler", post_id=5, arg_one="one", _scheme="http", _external=True)
+'http://server/posts/5?arg_one=one'
+
+# you can pass all special arguments at once
+>>> app.url_for("post_handler", post_id=5, arg_one=["one", "two"], arg_two=2, _anchor="anchor", _scheme="http", _external=True, _server="another_server:8888")
+'http://another_server:8888/posts/5?arg_one=one&arg_one=two&arg_two=2#anchor'
+```
+
+### Customizing a route name
+
+---:1
+
+A custom route name can be used by passing a `name` argument while registering the route. :--:1
+```python
+@app.get("/get", name="get_handler")
+def handler(request):
+ return text("OK")
+```
+:---
+
+---:1
+
+Now, use this custom name to retrieve the URL :--:1
+```python
+>>> app.url_for("get_handler", foo="bar")
+'/get?foo=bar'
+```
+:---
+
+## Websockets routes
+
+---:1
+
+Websocket routing works similar to HTTP methods. :--:1
+```python
+async def handler(request, ws):
+ message = "Start"
+ while True:
+ await ws.send(message)
+ message = await ws.recv()
+
+app.add_websocket_route(handler, "/test")
+```
+:---
+
+---:1
+
+It also has a convenience decorator. :--:1
+```python
+@app.websocket("/test")
+async def handler(request, ws):
+ message = "Start"
+ while True:
+ await ws.send(message)
+ message = await ws.recv()
+```
+:---
+
+Read the [websockets section](/guide/advanced/websockets.md) to learn more about how they work.
+
+## Strict slashes
+
+
+---:1
+
+Sanic routes can be configured to strictly match on whether or not there is a trailing slash: `/`. This can be configured at a few levels and follows this order of precedence:
+
+1. Route
+2. Blueprint
+3. BlueprintGroup
+4. Application
+
+:--:1
+```python
+# provide default strict_slashes value for all routes
+app = Sanic(__file__, strict_slashes=True)
+```
+
+```python
+# overwrite strict_slashes value for specific route
+@app.get("/get", strict_slashes=False)
+def handler(request):
+ return text("OK")
+```
+
+```python
+# it also works for blueprints
+bp = Blueprint(__file__, strict_slashes=True)
+
+@bp.get("/bp/get", strict_slashes=False)
+def handler(request):
+ return text("OK")
+```
+
+```python
+bp1 = Blueprint(name="bp1", url_prefix="/bp1")
+bp2 = Blueprint(
+ name="bp2",
+ url_prefix="/bp2",
+ strict_slashes=False,
+)
+
+# This will enforce strict slashes check on the routes
+# under bp1 but ignore bp2 as that has an explicitly
+# set the strict slashes check to false
+group = Blueprint.group([bp1, bp2], strict_slashes=True)
+```
+:---
+
+## Static files
+
+---:1
+
+In order to serve static files from Sanic, use `app.static()`.
+
+The order of arguments is important:
+
+1. Route the files will be served from
+2. Path to the files on the server
+
+See [API docs]() for more details. :--:1
+```python
+app.static("/static", "/path/to/directory")
+```
+:---
+
+---:1
+
+You can also serve individual files. :--:1
+```python
+app.static("/", "/path/to/index.html")
+```
+:---
+
+---:1
+
+It is also sometimes helpful to name your endpoint :--:1
+```python
+app.static(
+ "/user/uploads",
+ "/path/to/uploads",
+ name="uploads",
+)
+```
+:---
+
+---:1
+
+Retrieving the URLs works similar to handlers. But, we can also add the `filename` argument when we need a specific file inside a directory. :--:1
+```python
+>>> app.url_for(
+ "static",
+ name="static",
+ filename="file.txt",
+)
+'/static/file.txt'
+
+```python
+>>> app.url_for(
+ "static",
+ name="uploads",
+ filename="image.png",
+)
+'/user/uploads/image.png'
+
+```
+:---
+
+::: tip If you are going to have multiple `static()` routes, then it is *highly* suggested that you manually name them. This will almost certainly alleviate potential hard to discover bugs.
+
+```python
+app.static("/user/uploads", "/path/to/uploads", name="uploads")
+app.static("/user/profile", "/path/to/profile", name="profile_pics")
+```
+:::
+
+## Route context
+
+---:1 When a route is defined, you can add any number of keyword arguments with a `ctx_` prefix. These values will be injected into the route `ctx` object. :--:1
+```python
+@app.get("/1", ctx_label="something")
+async def handler1(request):
+ ...
+
+@app.get("/2", ctx_label="something")
+async def handler2(request):
+ ...
+
+@app.get("/99")
+async def handler99(request):
+ ...
+
+@app.on_request
+async def do_something(request):
+ if request.route.ctx.label == "something":
+ ...
+```
+:---
From b7d35301c4a48b12f5bf446e597ab28e29c8a251 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:28 +0300
Subject: [PATCH 084/776] New translations tasks.md (Japanese)
---
src/ja/guide/basics/tasks.md | 61 +++++++++++-------------------------
1 file changed, 18 insertions(+), 43 deletions(-)
diff --git a/src/ja/guide/basics/tasks.md b/src/ja/guide/basics/tasks.md
index a5b0cf7248..9ef47c95f1 100644
--- a/src/ja/guide/basics/tasks.md
+++ b/src/ja/guide/basics/tasks.md
@@ -1,7 +1,7 @@
# バックグラウンドタスク
## Tasksを作成
-非同期Pythonで[tasks](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task)を使用することは、望ましいことが多く、非常に便利です。Sanicは、現在実行中の**ループにタスクを追加する便利な方法を提供します。これは`asyncio.create_task`。'App'ループの実行前にタスクを追加する方法については、次のセクションを参照してください。
+非同期Pythonで[tasks](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task)を使用することは、望ましいことが多く、非常に便利です。 Sanicは、現在実行中の**ループにタスクを追加する便利な方法を提供します。 これは`asyncio.create_task`。 'App'ループの実行前にタスクを追加する方法については、次のセクションを参照してください。
```python
async def notify_server_started_after_five_seconds():
@@ -13,8 +13,7 @@ app.add_task(notify_server_started_after_five_seconds())
---:1
-Sanicは自動的にアプリを注入し、タスクへの引数として渡す。
-:--:1
+Sanicは自動的にアプリを注入し、タスクへの引数として渡す。 :--:1 :--:1
```python
async def auto_inject(app):
await asyncio.sleep(5)
@@ -26,8 +25,7 @@ app.add_task(auto_inject)
---:1
-または、`app`引数を明示的に渡すこともできます。
-:--:1
+または、`app`引数を明示的に渡すこともできます。 :--:1 :--:1
```python
async def explicit_inject(app):
await asyncio.sleep(5)
@@ -39,33 +37,32 @@ app.add_task(explicit_inject(app))
## `app.run`の前にタスクを追加します
-Appを実行する前にバックグラウンドタスクを追加することができます。`app.run`の前に置きます。Appが実行される前にタスクを追加するには、コルーチンオブジェクト(つまり、。`async`callable)を渡さずに、単に呼び出し可能オブジェクトを渡すことをお勧めします。Sanicは各ワーカーにコルーチンオブジェクトを作成します**.注:追加されるタスクは`before_server_start`ジョブとして実行されるため、すべてのワーカーで実行されます (メインプロセスでは実行されません) 。これには特定の結果が伴います。詳細については、[この問題](https://github.com/sanic-org/sanic/issues/2139) の [このコメント](https://github.com/sanic-org/sanic/issues/2139#issuecomment-868993668) を参照してください。
+Appを実行する前にバックグラウンドタスクを追加することができます。 `app.run`の前に置きます。 Appが実行される前にタスクを追加するには、コルーチンオブジェクト(つまり、。 `async`callable)を渡さずに、単に呼び出し可能オブジェクトを渡すことをお勧めします。 Sanicは各ワーカーにコルーチンオブジェクトを作成します**.注:追加されるタスクは`before_server_start`ジョブとして実行されるため、すべてのワーカーで実行されます (メインプロセスでは実行されません) 。 Note: the tasks that are added such are run as `before_server_start` jobs and thus run on every worker (and not in the main process). これには特定の結果が伴います。 詳細については、[この問題](https://github.com/sanic-org/sanic/issues/2139) の [このコメント](https://github.com/sanic-org/sanic/issues/2139#issuecomment-868993668) を参照してください。
-メイン・プロセスに作業を追加するには、[`@app.main_process_start`](./listeners.md)。注意:この作業が完了するまで、就業者は開始しません。
+メイン・プロセスに作業を追加するには、[`@app.main_process_start`](./listeners.md)。 注意:この作業が完了するまで、就業者は開始しません。
---:1
-`app.run`の前にタスクを追加する例
-:---:1
+`app.run`の前にタスクを追加する例 :---:1
```python
async def slow_work(...):
...
+async def even_slower(num):
+ ...
+
app = Sanic(...)
app.add_task(slow_work) # Note: we are passing the callable and not coroutine object `slow_work(...)`
app.run(...)
+app.add_task(even_slower(10)) # ... or we can call the function and pass the coroutine.
+app.run(...)
```
-::: tip
-上記の`slow_work`にパラメータを渡すには、`functools.partial`を使用します。
-:::
## Named tasks
-::: new NEW in v21.12
-_Python 3.8以上でのみサポートされます_
+_This is only supported in Python 3.8+_
----:1
-タスクを作成するときに、`name`を指定することで、Sanicにそのタスクを追跡するように依頼することができます。
+::: new NEW in v21.12 _Python 3.8以上でのみサポートされます_
:--:1
```python
@@ -73,8 +70,7 @@ app.add_task(slow_work, name="slow_task")
```
:---
----:1
-これで、アプリケーションのどこからでも `get_task` を使って、そのタスクのインスタンスを取得できるようになりました。
+---:1 これで、アプリケーションのどこからでも `get_task` を使って、そのタスクのインスタンスを取得できるようになりました。
:--:1
```python
@@ -82,8 +78,7 @@ task = app.get_task("slow_task")
```
:---
----:1
-そのタスクをキャンセルする必要がある場合は、 `cancel_task` を使って行うことができます。必ず `await` してください。
+---:1 そのタスクをキャンセルする必要がある場合は、 `cancel_task` を使って行うことができます。 必ず `await` してください。
:--:1
```python
@@ -91,8 +86,7 @@ await app.cancel_task("slow_task")
```
:---
----:1
-登録されたすべてのタスクは `app.tasks` プロパティで確認することができます。キャンセルされたタスクが一杯になるのを防ぐために、`app.purge_tasks`を実行して、完了したタスクやキャンセルされたタスクを消去するとよいでしょう。
+---:1 登録されたすべてのタスクは `app.tasks` プロパティで確認することができます。 キャンセルされたタスクが一杯になるのを防ぐために、`app.purge_tasks`を実行して、完了したタスクやキャンセルされたタスクを消去するとよいでしょう。
:--:1
```python
@@ -100,27 +94,8 @@ app.purge_tasks()
```
:---
+This pattern can be particularly useful with `websockets`:
+
このパターンは、特に `websocket` で有効です:
-```python
-async def receiver(ws):
- while True:
- message = await ws.recv()
- if not message:
- break
- print(f"Received: {message}")
-
-@app.websocket("/feed")
-async def feed(request, ws):
- task_name = f"receiver:{request.id}"
- request.app.add_task(receiver(ws), name=task_name)
- try:
- while True:
- await request.app.event("my.custom.event")
- await ws.send("A message")
- finally:
- # When the websocket closes, let's cleanup the task
- await request.app.cancel_task(task_name)
- request.app.purge_tasks()
-```
:::
From 1bd1df102acd05133430288c43c8c5ea2fae3469 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:30 +0300
Subject: [PATCH 085/776] New translations tasks.md (Korean)
---
src/ko/guide/basics/tasks.md | 69 ++++++++++++++++++++++++++++--------
1 file changed, 54 insertions(+), 15 deletions(-)
diff --git a/src/ko/guide/basics/tasks.md b/src/ko/guide/basics/tasks.md
index e10a74cdd5..dbe55db4f6 100644
--- a/src/ko/guide/basics/tasks.md
+++ b/src/ko/guide/basics/tasks.md
@@ -1,6 +1,7 @@
# 백그라운드 작업(Background tasks)
-비동기 Python에서 [tasks](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task)을 사용하는 것이 바람직하고 매우 편리합니다. Sanic은 작업을 현재 실행 중인 루프에 추가할 수 있는 편리한 방법을 제공합니다. 이것은 `asyncio.create_task`와 다소 비슷합니다.
+## Creating Tasks
+비동기 Python에서 [tasks](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task)을 사용하는 것이 바람직하고 매우 편리합니다. Sanic은 작업을 현재 실행 중인 루프에 추가할 수 있는 편리한 방법을 제공합니다. 이것은 `asyncio.create_task`와 다소 비슷합니다. For adding tasks before the 'App' loop is running, see next section.
```python
async def notify_server_started_after_five_seconds():
@@ -12,9 +13,7 @@ app.add_task(notify_server_started_after_five_seconds())
---:1
-Sanic은 자동으로 앱을 주입하여 인수로 작업에 전달합니다.
-:--:1
-
+Sanic은 자동으로 앱을 주입하여 인수로 작업에 전달합니다. :--:1
```python
async def auto_inject(app):
await asyncio.sleep(5)
@@ -22,14 +21,11 @@ async def auto_inject(app):
app.add_task(auto_inject)
```
-
:---
---:1
-또는 `app` 인수를 명시적으로 전달할 수 있습니다.
-:--:1
-
+또는 `app` 인수를 명시적으로 전달할 수 있습니다. :--:1
```python
async def explicit_inject(app):
await asyncio.sleep(5)
@@ -37,26 +33,69 @@ async def explicit_inject(app):
app.add_task(explicit_inject(app))
```
-
:---
## `app.run` 전에 작업 추가 (Adding tasks before `app.run`)
-앱이 실행되기 전에 백그라운드 작업을 추가할 수 있습니다. `app.run` 전에. 앱이 실행되기 전에 작업을 추가하려면, 코루틴 객체를 전달하지 않는 것이 좋습니다. (즉, `async` 콜러블을 호출하여 생성된 것), 대신 콜러블을 전달하면 Sanic은 **각 작업자**에 코루틴 객체를 생성합니다. 참고: 추가된 작업은 'before_server_start' 작업으로 실행되므로 모든 작업자(메인 프로세스가 아님 에서 실행됩니다.이것은 특정한 결과를 가져옵니다. 자세한 내용은 이 [issue](https://github.com/sanic-org/sanic/issues/2139)에 대한 [comment](https://github.com/sanic-org/sanic/issues/2139#issuecomment-868993668)을 읽으십시오.
+앱이 실행되기 전에 백그라운드 작업을 추가할 수 있습니다. `app.run` 전에. To add a task before the App is run, it is recommended to not pass the coroutine object (ie. one created by calling the `async` callable), but instead just pass the callable and Sanic will create the coroutine object on **each worker**. 참고: 추가된 작업은 'before_server_start' 작업으로 실행되므로 모든 작업자(메인 프로세스가 아님 에서 실행됩니다.이것은 특정한 결과를 가져옵니다. 자세한 내용은 이 [issue](https://github.com/sanic-org/sanic/issues/2139)에 대한 [comment](https://github.com/sanic-org/sanic/issues/2139#issuecomment-868993668)을 읽으십시오.
메인 프로세스에 작업을 추가하려면 [`@app.main_process_start`](./listeners.md)에 작업을 추가하는 것이 좋습니다. 참고: 작업자는 이 작업이 완료될 때까지 시작되지 않습니다.
+
---:1
-`app.run` 전에 작업을 추가하는 예
-:---:1
+`app.run` 전에 작업을 추가하는 예 :---:1
```python
async def slow_work(...):
...
+async def even_slower(num):
+ ...
+
app = Sanic(...)
app.add_task(slow_work) # Note: we are passing the callable and not coroutine object `slow_work(...)`
app.run(...)
+app.add_task(even_slower(10)) # ... or we can call the function and pass the coroutine.
+app.run(...)
```
-::: tip
-위의 `slow_work`에 매개변수를 전달하려면 `functools.partial`을 사용할 수 있습니다.
-:::
\ No newline at end of file
+
+## Named tasks
+
+_This is only supported in Python 3.8+_
+
+---:1 When creating a task, you can ask Sanic to keep track of it for you by providing a `name`.
+
+:--:1
+```python
+app.add_task(slow_work, name="slow_task")
+```
+:---
+
+---:1 You can now retrieve that task instance from anywhere in your application using `get_task`.
+
+:--:1
+```python
+task = app.get_task("slow_task")
+```
+:---
+
+---:1 If that task needs to be cancelled, you can do that with `cancel_task`. Make sure that you `await` it.
+
+:--:1
+```python
+await app.cancel_task("slow_task")
+```
+:---
+
+---:1 All registered tasks can be found in the `app.tasks` property. To prevent cancelled tasks from filling up, you may want to run `app.purge_tasks` that will clear out any completed or cancelled tasks.
+
+:--:1
+```python
+app.purge_tasks()
+```
+:---
+
+This pattern can be particularly useful with `websockets`:
+
+```python async def receiver(ws): while True: message = await ws.recv() if not message: break print(f"Received: {message}")
+
+@app.websocket("/feed") async def feed(request, ws): task_name = f"receiver:{request.id}" request.app.add_task(receiver(ws), name=task_name) try: while True: await request.app.event("my.custom.event") await ws.send("A message") finally: # When the websocket closes, let's cleanup the task await request.app.cancel_task(task_name) request.app.purge_tasks() :::
From 28c4009a054f9130443408e40ca489d9e3813593 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:31 +0300
Subject: [PATCH 086/776] New translations tasks.md (Chinese Simplified)
---
src/zh/guide/basics/tasks.md | 109 ++++++++++++-----------------------
1 file changed, 38 insertions(+), 71 deletions(-)
diff --git a/src/zh/guide/basics/tasks.md b/src/zh/guide/basics/tasks.md
index 9459dc1a06..d0549af69b 100644
--- a/src/zh/guide/basics/tasks.md
+++ b/src/zh/guide/basics/tasks.md
@@ -1,23 +1,34 @@
# 后台任务(Background tasks)
## 创建任务(Creating Tasks)
-
-在异步 Python 里使用 [任务](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task) 是非常简单方便的,Sanic 提供了一种简单的方法来将任务添加到**当前运行**的 loop 当中, 它有点类似于 `asyncio.create_task`。关于在 "应用程序" loop 运行之前添加任务,请参见下一节。
+在异步 Python 里使用 [任务](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task) 是非常简单方便的,Sanic 提供了一种简单的方法来将任务添加到**当前运行**的 loop 当中, 它有点类似于 `asyncio.create_task`。 Sanic provides a convenient method to add tasks to the currently **running** loop. It is somewhat similar to `asyncio.create_task`. 关于在 "应用程序" loop 运行之前添加任务,请参见下一节。
```python
-async def notify_server_started_after_five_seconds():
- await asyncio.sleep(5)
- print('Server successfully started!')
+async def receiver(ws):
+ while True:
+ message = await ws.recv()
+ if not message:
+ break
+ print(f"Received: {message}")
-app.add_task(notify_server_started_after_five_seconds())
+@app.websocket("/feed")
+async def feed(request, ws):
+ task_name = f"receiver:{request.id}"
+ request.app.add_task(receiver(ws), name=task_name)
+ try:
+ while True:
+ await request.app.event("my.custom.event")
+ await ws.send("A message")
+ finally:
+ # 当 websocket 关闭连接的时候,我们可以清除所有的任务。
+
+await request.app.cancel_task(task_name)
+ request.app.purge_tasks()
```
---:1
-Sanic 将尝试自动注入该应用程序,并将应用程序作为任务的参数进行传递。
-
-:--:1
-
+Sanic 将尝试自动注入该应用程序,并将应用程序作为任务的参数进行传递。 :--:1
```python
async def auto_inject(app):
await asyncio.sleep(5)
@@ -25,15 +36,11 @@ async def auto_inject(app):
app.add_task(auto_inject)
```
-
:---
---:1
-或者您可以选择显式的将 `app` 作为传递参数。
-
-:--:1
-
+或者您可以选择显式的将 `app` 作为传递参数。 :--:1
```python
async def explicit_inject(app):
await asyncio.sleep(5)
@@ -41,113 +48,73 @@ async def explicit_inject(app):
app.add_task(explicit_inject(app))
```
-
:---
## 在 `app.run` 之前添加任务(Adding tasks before `app.run`)
-在 app 运行前是可以添加后台任务的。为了完成这个目的,您应该为 `Sanic.add_task` 方法传入一个可调用的对象,即使用 `async` 定义的函数本身,而不是一个协程对象(调用 `async` 函数后得到的对象),当传入可调用对象之后,Sanic 将为 **每一个** 子程序都创建该任务。
-
-注意:这样添加的任务是在 `before_server_start` 阶段工作的,因此在每个子进程都会有该任务(而不是在主进程中)。
-
-这将会产生一些后果:请查看[这个问题](https://github.com/sanic-org/sanic/issues/2139)的[这条评论](https://github.com/sanic-org/sanic/issues/2139#issuecomment-868993668)来获取更多信息。
+It is possible to add background tasks before the App is run ie. before `app.run`. 在 app 运行前是可以添加后台任务的。 为了完成这个目的,您应该为 `Sanic.add_task` 方法传入一个可调用的对象,即使用 `async` 定义的函数本身,而不是一个协程对象(调用 `async` 函数后得到的对象),当传入可调用对象之后,Sanic 将为 **每一个** 子程序都创建该任务。 Note: the tasks that are added such are run as `before_server_start` jobs and thus run on every worker (and not in the main process). 这将会产生一些后果:请查看[这个问题](https://github.com/sanic-org/sanic/issues/2139)的[这条评论](https://github.com/sanic-org/sanic/issues/2139#issuecomment-868993668)来获取更多信息。
-要想只为主进程添加任务,您应该考虑使用 [`@app.main_process_start`](./listeners.md)添加任务。注意:任务没完成子进程将无法启动。
+要想只为主进程添加任务,您应该考虑使用 [`@app.main_process_start`](./listeners.md)添加任务。 注意:任务没完成子进程将无法启动。
---:1
-示例代码:
+注意:这样添加的任务是在 `before_server_start` 阶段工作的,因此在每个子进程都会有该任务(而不是在主进程中)。
+```python
+async def slow_work():
+ ...
-:---:1
+async def even_slower(num):
+ ...
-```python
+app = Sanic(...)
async def slow_work(...):
...
app = Sanic(...)
app.add_task(slow_work) # Note: we are passing the callable and not coroutine object `slow_work(...)`
app.run(...)
-
+app.add_task(even_slower(10)) # ... or we can call the function and pass the coroutine.
+app.run(...)
```
-::: tip
-
-如果您想要为 `slow_work` 绑定一些参数,可以使用 `functools.partial`。
-
-:::
-
## 命名任务(Named tasks)
_这只适用于 Python3.8 及以上版本_
----:1
-
当您创建任务的时候,您可以为您的任务指定一个名称,方便您后续进行任务追踪。
:--:1
-
```python
app.add_task(slow_work, name="slow_task")
```
-
:---
----:1
-
-之后,您可以使用 `get_task` 方法从应用程序的任何地方查看您的任务。
+:---:1
:--:1
-
```python
task = app.get_task("slow_task")
```
-
:---
----:1
-
-如果您想要取消任务,您可以通过 `cacle_task` 来进行操作,当然,该方法也是异步的,请确保使用时添加了 `await`。
+如果您想要取消任务,您可以通过 `cacle_task` 来进行操作,当然,该方法也是异步的,请确保使用时添加了 `await`。 Make sure that you `await` it.
:--:1
-
```python
await app.cancel_task("slow_task")
```
-
:---
----:1
-
-所有注册的任务都可以在 `app.tasks` 属性中找到。为了防止已取消的任务填满,您可能需要运行 `app.purge_tasks` 来清除所有已完成或已取消的任务。
+所有注册的任务都可以在 `app.tasks` 属性中找到。 为了防止已取消的任务填满,您可能需要运行 `app.purge_tasks` 来清除所有已完成或已取消的任务。
:--:1
-
```python
app.purge_tasks()
```
-
:---
这种模式对于 websocket 来说非常有用:
-```python
-async def receiver(ws):
- while True:
- message = await ws.recv()
- if not message:
- break
- print(f"Received: {message}")
+之后,您可以使用 `get_task` 方法从应用程序的任何地方查看您的任务。
-@app.websocket("/feed")
-async def feed(request, ws):
- task_name = f"receiver:{request.id}"
- request.app.add_task(receiver(ws), name=task_name)
- try:
- while True:
- await request.app.event("my.custom.event")
- await ws.send("A message")
- finally:
- # 当 websocket 关闭连接的时候,我们可以清除所有的任务。
- await request.app.cancel_task(task_name)
- request.app.purge_tasks()
-```
+async def notify_server_started_after_five_seconds(): await asyncio.sleep(5) print('Server successfully started!') app.add_task(notify_server_started_after_five_seconds())
From e5fd9e99de13985c396fbdc4086eb70c117544f1 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:32 +0300
Subject: [PATCH 087/776] New translations tasks.md (Portuguese, Brazilian)
---
src/pt/guide/basics/tasks.md | 100 +++++++++++++++++++++++++++++++++++
1 file changed, 100 insertions(+)
create mode 100644 src/pt/guide/basics/tasks.md
diff --git a/src/pt/guide/basics/tasks.md b/src/pt/guide/basics/tasks.md
new file mode 100644
index 0000000000..0db16a8004
--- /dev/null
+++ b/src/pt/guide/basics/tasks.md
@@ -0,0 +1,100 @@
+# Background tasks
+
+## Creating Tasks
+It is often desirable and very convenient to make usage of [tasks](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task) in async Python. Sanic provides a convenient method to add tasks to the currently **running** loop. It is somewhat similar to `asyncio.create_task`. For adding tasks before the 'App' loop is running, see next section.
+
+```python
+async def notify_server_started_after_five_seconds():
+ await asyncio.sleep(5)
+ print('Server successfully started!')
+
+app.add_task(notify_server_started_after_five_seconds())
+```
+
+---:1
+
+Sanic will attempt to automatically inject the app, passing it as an argument to the task. :--:1
+```python
+async def auto_inject(app):
+ await asyncio.sleep(5)
+ print(app.name)
+
+app.add_task(auto_inject)
+```
+:---
+
+---:1
+
+Or you can pass the `app` argument explicitly. :--:1
+```python
+async def explicit_inject(app):
+ await asyncio.sleep(5)
+ print(app.name)
+
+app.add_task(explicit_inject(app))
+```
+:---
+
+## Adding tasks before `app.run`
+
+It is possible to add background tasks before the App is run ie. before `app.run`. To add a task before the App is run, it is recommended to not pass the coroutine object (ie. one created by calling the `async` callable), but instead just pass the callable and Sanic will create the coroutine object on **each worker**. Note: the tasks that are added such are run as `before_server_start` jobs and thus run on every worker (and not in the main process). This has certain consequences, please read [this comment](https://github.com/sanic-org/sanic/issues/2139#issuecomment-868993668) on [this issue](https://github.com/sanic-org/sanic/issues/2139) for further details.
+
+To add work on the main process, consider adding work to [`@app.main_process_start`](./listeners.md). Note: the workers won't start until this work is completed.
+
+---:1
+
+Example to add a task before `app.run` :---:1
+```python
+async def slow_work():
+ ...
+
+async def even_slower(num):
+ ...
+
+app = Sanic(...)
+app.add_task(slow_work) # Note: we are passing the callable and not coroutine object ...
+app.add_task(even_slower(10)) # ... or we can call the function and pass the coroutine.
+app.run(...)
+```
+
+## Named tasks
+
+_This is only supported in Python 3.8+_
+
+---:1 When creating a task, you can ask Sanic to keep track of it for you by providing a `name`.
+
+:--:1
+```python
+app.add_task(slow_work, name="slow_task")
+```
+:---
+
+---:1 You can now retrieve that task instance from anywhere in your application using `get_task`.
+
+:--:1
+```python
+task = app.get_task("slow_task")
+```
+:---
+
+---:1 If that task needs to be cancelled, you can do that with `cancel_task`. Make sure that you `await` it.
+
+:--:1
+```python
+await app.cancel_task("slow_task")
+```
+:---
+
+---:1 All registered tasks can be found in the `app.tasks` property. To prevent cancelled tasks from filling up, you may want to run `app.purge_tasks` that will clear out any completed or cancelled tasks.
+
+:--:1
+```python
+app.purge_tasks()
+```
+:---
+
+This pattern can be particularly useful with `websockets`:
+
+```python async def receiver(ws): while True: message = await ws.recv() if not message: break print(f"Received: {message}")
+
+@app.websocket("/feed") async def feed(request, ws): task_name = f"receiver:{request.id}" request.app.add_task(receiver(ws), name=task_name) try: while True: await request.app.event("my.custom.event") await ws.send("A message") finally: # When the websocket closes, let's cleanup the task await request.app.cancel_task(task_name) request.app.purge_tasks() :::
From 8e2e1e25b742d305c2673578430c56644327695e Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:33 +0300
Subject: [PATCH 088/776] New translations README.md (Korean)
---
src/ko/guide/best-practices/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/best-practices/README.md
diff --git a/src/ko/guide/best-practices/README.md b/src/ko/guide/best-practices/README.md
new file mode 100644
index 0000000000..874ca7f3c6
--- /dev/null
+++ b/src/ko/guide/best-practices/README.md
@@ -0,0 +1 @@
+# Best Practices
From 3218af635784010c764ff98722329cf55023f0bf Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:34 +0300
Subject: [PATCH 089/776] New translations README.md (Portuguese, Brazilian)
---
src/pt/guide/deployment/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/deployment/README.md
diff --git a/src/pt/guide/deployment/README.md b/src/pt/guide/deployment/README.md
new file mode 100644
index 0000000000..d36c65e59e
--- /dev/null
+++ b/src/pt/guide/deployment/README.md
@@ -0,0 +1 @@
+# Deployment
From 8641c05f0e22c495ce89bcd183827573174f9dcb Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:35 +0300
Subject: [PATCH 090/776] New translations configuration.md (Japanese)
---
src/ja/guide/deployment/configuration.md | 130 ++++++++++-------------
1 file changed, 54 insertions(+), 76 deletions(-)
diff --git a/src/ja/guide/deployment/configuration.md b/src/ja/guide/deployment/configuration.md
index ebe0a8be97..556b26b15e 100644
--- a/src/ja/guide/deployment/configuration.md
+++ b/src/ja/guide/deployment/configuration.md
@@ -5,8 +5,7 @@
---:1
-Sanicは、アプリケーションオブジェクトのconfig属性に設定を保持します。構成オブジェクトは、ドット表記法を使用して、または辞書のように変更できる単なるオブジェクトです。
-:--:1
+Sanicは、アプリケーションオブジェクトのconfig属性に設定を保持します。 構成オブジェクトは、ドット表記法を使用して、または辞書のように変更できる単なるオブジェクトです。 :--:1 :--:1
```python
app = Sanic("myapp")
app.config.DB_NAME = "appdb"
@@ -16,8 +15,7 @@ app.config["DB_USER"] = "appuser"
---:1
-また、通常の辞書と同様に`update()`メソッドを使用することもできます。
-:--:1
+また、通常の辞書と同様に`update()`メソッドを使用することもできます。 :--:1 :--:1
```python
db_settings = {
'DB_HOST': 'localhost',
@@ -28,8 +26,7 @@ app.config.update(db_settings)
```
:---
-::: tip
-Sanicでは、設定値には**大文字で名前を付けるのが一般的です**.実際、大文字と小文字を混在させると奇妙な動作をすることがあります。
+::: tip Sanicでは、設定値には**大文字で名前を付けるのが一般的です**.実際、大文字と小文字を混在させると奇妙な動作をすることがあります。 ::: Indeed, you may experience weird behaviors if you start mixing uppercase and lowercase names.
:::
## 読み込み中
@@ -38,8 +35,7 @@ Sanicでは、設定値には**大文字で名前を付けるのが一般的で
---:1
-`SANIC_`プレフィックスで定義された環境変数は、Sanicの設定に適用されます。たとえば、設定`SANIC_REQUEST_TIMEOUT`はアプリケーションによって自動的にロードされ、`REQUEST_TIMEOUT`構成変数に渡されます。
-:--:1
+`SANIC_`プレフィックスで定義された環境変数は、Sanicの設定に適用されます。 たとえば、設定`SANIC_REQUEST_TIMEOUT`はアプリケーションによって自動的にロードされ、`REQUEST_TIMEOUT`構成変数に渡されます。 :--:1 :--:1
```bash
$ export SANIC_REQUEST_TIMEOUT=10
```
@@ -51,8 +47,7 @@ $ export SANIC_REQUEST_TIMEOUT=10
---:1
-起動時にSanicが要求するプレフィクスを変更できます。
-:--:1
+起動時にSanicが要求するプレフィクスを変更できます。 :--:1 :--:1
```bash
$ export MYAPP_REQUEST_TIMEOUT=10
```
@@ -65,8 +60,7 @@ $ export MYAPP_REQUEST_TIMEOUT=10
---:1
-環境変数のロードを完全に無効にすることもできます。
-:--:1
+環境変数のロードを完全に無効にすることもできます。 :--:1 :--:1
```python
app = Sanic(__name__, load_env=False)
```
@@ -74,14 +68,13 @@ app = Sanic(__name__, load_env=False)
### Sanic.update_configを使用する
-`Sanic`インスタンスには、config:`app.update_config`をロードするための_very_versatileメソッドがあります。ファイル、辞書、クラスなど、あらゆる種類のオブジェクトへのパスを指定できます。
+`Sanic`インスタンスには、config:`app.update_config`をロードするための_very_versatileメソッドがあります。 ファイル、辞書、クラスなど、あらゆる種類のオブジェクトへのパスを指定できます。
#### From a file
---:1
-たとえば、次のような`my_config.py`ファイルがあるとします。
-:--:1
+たとえば、次のような`my_config.py`ファイルがあるとします。 :--:1 :--:1
```python
# my_config.py
A = 1
@@ -91,8 +84,7 @@ B = 2
---:1
-パスを`app.update_config`に渡すことで、これを構成値としてロードできます。
-:--:1
+パスを`app.update_config`に渡すことで、これを構成値としてロードできます。 :--:1 :--:1
```python
>>> app.update_config("/path/to/my_config.py")
>>> print(app.config.A)
@@ -102,8 +94,7 @@ B = 2
---:1
-このパスはbashスタイルの環境変数も受け付けます。
-:--:1
+このパスはbashスタイルの環境変数も受け付けます。 :--:1 :--:1
```bash
$ export my_path="/path/to"
```
@@ -112,15 +103,13 @@ app.update_config("${my_path}/my_config.py")
```
:---
-::: tip
-環境変数は`${environment_variable}`の形式で指定する必要があり、`$environment_variable`は展開されません ("プレーン"テキストとして扱われます) 。
+::: tip 環境変数は`${environment_variable}`の形式で指定する必要があり、`$environment_variable`は展開されません ("プレーン"テキストとして扱われます) 。 :::
:::
#### 辞書から
---:1
-`app.update_config`メソッドは、通常の辞書でも動作します。
-:--:1
+`app.update_config`メソッドは、通常の辞書でも動作します。 :--:1 :--:1
```python
app.update_config({"A": 1, "B": 2})
```
@@ -130,8 +119,7 @@ app.update_config({"A": 1, "B": 2})
---:1
-独自の構成クラスを定義して、`app.update_config`
-:--:1
+独自の構成クラスを定義して、`app.update_config` :--:1
```python
class MyConfig:
A = 1
@@ -143,8 +131,7 @@ app.update_config(MyConfig)
---:1
-インスタンス化も可能です。
-:--:1
+It even could be instantiated. :--:1
```python
app.update_config(MyConfig())
```
@@ -152,7 +139,7 @@ app.update_config(MyConfig())
### 型キャスティング
-環境変数から読み込む場合、Sanicは値を期待されるPythonの型にキャストしようとします。これは特に以下に当てはまります。
+環境変数から読み込む場合、Sanicは値を期待されるPythonの型にキャストしようとします。 これは特に以下に当てはまります。
- `int`
- `float`
@@ -163,76 +150,67 @@ app.update_config(MyConfig())
- **`True`**: `y`, `yes`, `yep`, `yup`, `t`, `true`, `on`, `enable`, `enabled`, `1`
- **`False`**: `n`, `no`, `f`, `false`, `off`, `disable`, `disabled`, `0`
-::: new NEW in v21.12
-
----:1
-さらに、Sanicは追加のタイプコンバータを使用して、追加の型をキャストするように設定することができます。これは、値を返すか、`ValueError`を発生させる任意のcallableでなければならない。
-:--:1
+---:1 さらに、Sanicは追加のタイプコンバータを使用して、追加の型をキャストするように設定することができます。 これは、値を返すか、`ValueError`を発生させる任意のcallableでなければならない。 :--:1 :--:1
```python
app = Sanic(..., config=Config(converters=[UUID]))
```
:---
-:::
## 組み込み値
-| **変数** | **デフォルト** | **説明** |
-|--|--|--|
-| ACCESS_LOG | True | アクセスログを無効または有効にする。
-| AUTO_EXTEND ^ | True | [Sanic Extensions](../../plugins/sanic-ext/getting-started.md) が既存の仮想環境内にある場合にロードするかどうかを制御する |
-| AUTO_RELOAD | True | ファイルが変更されたときにアプリケーションが自動的にリロードするかどうかを制御します。 |
-| EVENT_AUTOREGISTER | True | `True` のとき、存在しないシグナルに対して `app.event()` メソッドを使用すると、自動的にシグナルを生成して例外を発生させないEVENT_AUTOREGISTER.index.index. |
-| FALLBACK_ERROR_FORMAT|html| 例外が発生し処理されなかった場合のエラー応答のフォーマット |
-| FORWARDED_FOR_HEADER| X-Forwarded-For| クライアントとプロキシのIPを含む「X-Forwarded-For」HTTPヘッダの名前です。 |
-| FORWARDED_SECRET|なし|特定のプロキシサーバーを安全に識別するために使用される(下記参照) |
-| GRACEFUL_SHUTDOWN_TIMEOUT | 15.0 | アイドルでない接続を強制終了するまでの時間(秒) |
-| KEEP_ALIVE | True | Falseの場合、キープアライブを無効にする。 |
-| KEEP_ALIVE_TIMEOUT | 5 | TCP接続を開いたままにする時間(秒) |
-| MOTD ^ | True | 起動時にMOTD(今日のメッセージ)を表示するかどうか |
-| MOTD_DISPLAY ^ | {} | MOTDに任意のデータを追加表示するためのキー/バリュー・ペア |
-| NOISY_EXCEPTIONS ^ | False | すべての `quiet` 例外を強制的にログに記録する |
-| PROXIES_COUNT | なし | アプリの前にあるプロキシサーバーの数(例:nginx) |
-| REAL_IP_HEADER | なし | 本当のクライアントIPを含む「X-Real-IP」HTTPヘッダーの名前 | REAL_IP_HEADER | なし |
-| REGISTER | True | アプリのレジストリを有効にするかどうか。 |
-| REQUEST_BUFFER_SIZE | 65536 | リクエストが一時停止するまでのリクエストバッファサイズ、デフォルトは64Kib |
-| REQUEST_ID_HEADER | X-Request-ID | リクエスト/相関 ID を含む HTTP ヘッダー "X-Request-ID" の名前 |
-| REQUEST_MAX_SIZE | 100000000 | リクエストの大きさ (バイト)、デフォルトは100メガバイトです。 |
-| REQUEST_TIMEOUT | 60 | リクエストが到着するまでの時間(秒)です。 |
-| RESPONSE_TIMEOUT | 60 | レスポンス処理にかかる時間(秒)です。 |
-| USE_UVLOOP | True | ループポリシーをオーバーライドして `uvloop` を使用するかどうかを指定します。`app.run`でのみサポートされる。 |
-| WEBSOCKET_MAX_SIZE | 2^20 | 受信メッセージの最大サイズ (バイト) |
-| WEBSOCKET_PING_INTERVAL | 20 | Pingフレームはping_interval秒ごとに送信されます。 |
-| WEBSOCKET_PING_TIMEOUT | 20 |ping_timeout秒後にPongを受信しない場合、接続を終了します。|
-
-::: new NEW in v21.12
-新要素: `AUTO_EXTEND`, `MOTD`, `MOTD_DISPLAY`, `NOISY_EXCEPTIONS`
-:::
+| **変数** | **デフォルト** | **説明** |
+| --------------------------- | --------------- | ------------------------------------------------------------------------------------------------------- |
+| ACCESS_LOG | True | アクセスログを無効または有効にする。 |
+| AUTO_EXTEND ^ | True | [Sanic Extensions](../../plugins/sanic-ext/getting-started.md) が既存の仮想環境内にある場合にロードするかどうかを制御する |
+| AUTO_RELOAD | True | ファイルが変更されたときにアプリケーションが自動的にリロードするかどうかを制御します。 |
+| EVENT_AUTOREGISTER | True | `True` のとき、存在しないシグナルに対して `app.event()` メソッドを使用すると、自動的にシグナルを生成して例外を発生させないEVENT_AUTOREGISTER.index.index. |
+| FALLBACK_ERROR_FORMAT | html | 例外が発生し処理されなかった場合のエラー応答のフォーマット |
+| FORWARDED_FOR_HEADER | X-Forwarded-For | クライアントとプロキシのIPを含む「X-Forwarded-For」HTTPヘッダの名前です。 |
+| FORWARDED_SECRET | なし | 特定のプロキシサーバーを安全に識別するために使用される(下記参照) |
+| GRACEFUL_SHUTDOWN_TIMEOUT | 15.0 | アイドルでない接続を強制終了するまでの時間(秒) |
+| KEEP_ALIVE | True | Falseの場合、キープアライブを無効にする。 |
+| KEEP_ALIVE_TIMEOUT | 5 | TCP接続を開いたままにする時間(秒) |
+| MOTD ^ | True | 起動時にMOTD(今日のメッセージ)を表示するかどうか |
+| MOTD_DISPLAY ^ | {} | MOTDに任意のデータを追加表示するためのキー/バリュー・ペア |
+| NOISY_EXCEPTIONS ^ | False | すべての `quiet` 例外を強制的にログに記録する |
+| PROXIES_COUNT | なし | アプリの前にあるプロキシサーバーの数(例:nginx) |
+| REAL_IP_HEADER | なし | 本当のクライアントIPを含む「X-Real-IP」HTTPヘッダーの名前 | REAL_IP_HEADER | なし |
+| REGISTER | True | アプリのレジストリを有効にするかどうか。 |
+| REQUEST_BUFFER_SIZE | 65536 | リクエストが一時停止するまでのリクエストバッファサイズ、デフォルトは64Kib |
+| REQUEST_ID_HEADER | X-Request-ID | リクエスト/相関 ID を含む HTTP ヘッダー "X-Request-ID" の名前 |
+| REQUEST_MAX_SIZE | 100000000 | リクエストの大きさ (バイト)、デフォルトは100メガバイトです。 |
+| REQUEST_TIMEOUT | 60 | リクエストが到着するまでの時間(秒)です。 |
+| RESPONSE_TIMEOUT | 60 | レスポンス処理にかかる時間(秒)です。 |
+| USE_UVLOOP | True | ループポリシーをオーバーライドして `uvloop` を使用するかどうかを指定します。 `app.run`でのみサポートされる。 |
+| WEBSOCKET_MAX_SIZE | 2^20 | 受信メッセージの最大サイズ (バイト) |
+| WEBSOCKET_PING_INTERVAL | 20 | Pingフレームはping_interval秒ごとに送信されます。 |
+| WEBSOCKET_PING_TIMEOUT | 20 | ping_timeout秒後にPongを受信しない場合、接続を終了します。 |
::: tip FYI
-- `USE_UVLOOP` の値は、Gunicorn で実行されている場合、無視されます。サポートされていないプラットフォーム (Windows) では、デフォルトは `False` である。
-- ASGI モードでは `WEBSOCKET_` 値は無視されます。
+- `USE_UVLOOP` の値は、Gunicorn で実行されている場合、無視されます。 サポートされていないプラットフォーム (Windows) では、デフォルトは `False` である。
+- ASGI モードでは `WEBSOCKET_` 値は無視されます。 :::
:::
## タイムアウト
-### リクエストタイムアウト
+### REQUEST_TIMEOUT
-要求タイムアウトは、新しいオープンTCP接続がSanicバックエンドサーバーに渡された瞬間と、HTTP要求全体を受信した瞬間の間の時間を測定します。もし時間が `REQUEST_TIMEOUT` 値(秒)を超えたら、これはクライアントエラーとみなされ、Sanicは `HTTP 408` 応答を生成してクライアントに送信する。クライアントが日常的に非常に大きなリクエストペイロードを渡したり、リクエストを非常にゆっくりとアップロードする場合は、このパラメータの値を高く設定してください。
+要求タイムアウトは、新しいオープンTCP接続がSanicバックエンドサーバーに渡された瞬間と、HTTP要求全体を受信した瞬間の間の時間を測定します。 もし時間が `REQUEST_TIMEOUT` 値(秒)を超えたら、これはクライアントエラーとみなされ、Sanicは `HTTP 408` 応答を生成してクライアントに送信する。 クライアントが日常的に非常に大きなリクエストペイロードを渡したり、リクエストを非常にゆっくりとアップロードする場合は、このパラメータの値を高く設定してください。
-### 応答タイムアウト
+### RESPONSE_TIMEOUT
-レスポンスタイムアウトは、SanicサーバーがSanicアプリにHTTPリクエストを渡した瞬間から、HTTPレスポンスがクライアントに送信されるまでの時間を測定します。時間が `RESPONSE_TIMEOUT` 値 (秒) を超えると、サーバーエラーと見なされるため、Sanic は `HTTP 503` 応答を生成してクライアントに送信します。レスポンスの生成を遅らせるような長時間稼働のプロセスがあるようなアプリケーションでは、このパラメータの値を高く設定してください。
+レスポンスタイムアウトは、SanicサーバーがSanicアプリにHTTPリクエストを渡した瞬間から、HTTPレスポンスがクライアントに送信されるまでの時間を測定します。 時間が `RESPONSE_TIMEOUT` 値 (秒) を超えると、サーバーエラーと見なされるため、Sanic は `HTTP 503` 応答を生成してクライアントに送信します。 レスポンスの生成を遅らせるような長時間稼働のプロセスがあるようなアプリケーションでは、このパラメータの値を高く設定してください。
-### キープアライブタイムアウト
+### KEEP_ALIVE_TIMEOUT
-#### Keep Alive とは何ですか?また、キープアライブタイムアウトの値は何をするのでしょうか?
+#### Keep Alive とは何ですか? また、キープアライブタイムアウトの値は何をするのでしょうか?
-キープアライブとは、HTTP 1.1 で導入された HTTP の機能です。HTTPリクエストを送信するとき、クライアント(通常はウェブブラウザアプリケーション)は `Keep-Alive` ヘッダを設定して、HTTPサーバ(Sanic)が応答を送信した後もTCP接続を閉じないように指示することができます。これにより、クライアントは後続のHTTPリクエストを送信するために既存のTCP接続を再利用することができ、クライアントとサーバーの両方にとってより効率的なネットワークトラフィックを確保することができます。
+キープアライブとは、HTTP 1.1 で導入された HTTP の機能です。 HTTPリクエストを送信するとき、クライアント(通常はウェブブラウザアプリケーション)は `Keep-Alive` ヘッダを設定して、HTTPサーバ(Sanic)が応答を送信した後もTCP接続を閉じないように指示することができます。 これにより、クライアントは後続のHTTPリクエストを送信するために既存のTCP接続を再利用することができ、クライアントとサーバーの両方にとってより効率的なネットワークトラフィックを確保することができます。
-Sanicでは、`KEEP_ALIVE`設定変数がデフォルトで `True` に設定されています。アプリケーションでこの機能を必要としない場合は、`False`に設定すると、リクエストの `Keep-Alive` ヘッダに関係なく、レスポンスが送信された後にすべてのクライアント接続を直ちに終了するようになります。
+Sanicでは、`KEEP_ALIVE`設定変数がデフォルトで `True` に設定されています。 アプリケーションでこの機能を必要としない場合は、`False`に設定すると、リクエストの `Keep-Alive` ヘッダに関係なく、レスポンスが送信された後にすべてのクライアント接続を直ちに終了するようになります。
-サーバーが TCP 接続を開いたままにする時間は、サーバー自身が決定します。Sanic では、その値は `KEEP_ALIVE_TIMEOUT` 値を使用して設定されます。デフォルトでは、5秒に設定されています。これは Apache HTTP サーバーと同じデフォルト設定で、クライアントが新しいリクエストを送信するのに十分な時間を与えることと、一度に多くのコネクションをオープンしないことのバランスが取れています。クライアントが、その時間だけ開いたままの TCP 接続をサポートするブラウザを使用していることが分かっている場合を除き、75 秒を超えないようにしてください。
+サーバーが TCP 接続を開いたままにする時間は、サーバー自身が決定します。 Sanic では、その値は `KEEP_ALIVE_TIMEOUT` 値を使用して設定されます。 デフォルトでは、5秒に設定されています。 これは Apache HTTP サーバーと同じデフォルト設定で、クライアントが新しいリクエストを送信するのに十分な時間を与えることと、一度に多くのコネクションをオープンしないことのバランスが取れています。 クライアントが、その時間だけ開いたままの TCP 接続をサポートするブラウザを使用していることが分かっている場合を除き、75 秒を超えないようにしてください。
参考までに
From 39d0960a2a377e47f4c048ffc671122b00a68e93 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:36 +0300
Subject: [PATCH 091/776] New translations autodiscovery.md (Korean)
---
src/ko/guide/how-to/autodiscovery.md | 161 +++++++++++++++++++++++++++
1 file changed, 161 insertions(+)
create mode 100644 src/ko/guide/how-to/autodiscovery.md
diff --git a/src/ko/guide/how-to/autodiscovery.md b/src/ko/guide/how-to/autodiscovery.md
new file mode 100644
index 0000000000..4cf319357b
--- /dev/null
+++ b/src/ko/guide/how-to/autodiscovery.md
@@ -0,0 +1,161 @@
+---
+title: Autodiscovery
+---
+
+
+# Autodiscovery of Blueprints, Middleware, and Listeners
+
+> How do I autodiscover the components I am using to build my application?
+
+One of the first problems someone faces when building an application, is *how* to structure the project. Sanic makes heavy use of decorators to register route handlers, middleware, and listeners. And, after creating blueprints, they need to be mounted to the application.
+
+A possible solution is a single file in which **everything** is imported and applied to the Sanic instance. Another is passing around the Sanic instance as a global variable. Both of these solutions have their drawbacks.
+
+An alternative is autodiscovery. You point your application at modules (already imported, or strings), and let it wire everything up.
+
+:::: tabs
+::: tab server.py
+```python
+from sanic import Sanic
+from sanic.response import empty
+
+import blueprints
+from utility import autodiscover
+
+app = Sanic("auto", register=True)
+autodiscover(
+ app,
+ blueprints,
+ "parent.child",
+ "listeners.something",
+ recursive=True,
+)
+
+app.route("/")(lambda _: empty())
+```
+```bash
+[2021-03-02 21:37:02 +0200] [880451] [INFO] Goin' Fast @ http://127.0.0.1:9999
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something @ nested
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something @ level1
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something @ level3
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something inside __init__.py
+[2021-03-02 21:37:02 +0200] [880451] [INFO] Starting worker [880451]
+```
+:::
+::: tab utility.py
+```python
+
+from glob import glob
+from importlib import import_module, util
+from inspect import getmembers
+from pathlib import Path
+from types import ModuleType
+from typing import Union
+
+from sanic.blueprints import Blueprint
+
+
+def autodiscover(
+ app, *module_names: Union[str, ModuleType], recursive: bool = False
+):
+ mod = app.__module__
+ blueprints = set()
+ _imported = set()
+
+ def _find_bps(module):
+ nonlocal blueprints
+
+ for _, member in getmembers(module):
+ if isinstance(member, Blueprint):
+ blueprints.add(member)
+
+ for module in module_names:
+ if isinstance(module, str):
+ module = import_module(module, mod)
+ _imported.add(module.__file__)
+ _find_bps(module)
+
+ if recursive:
+ base = Path(module.__file__).parent
+ for path in glob(f"{base}/**/*.py", recursive=True):
+ if path not in _imported:
+ name = "module"
+ if "__init__" in path:
+ *_, name, __ = path.split("/")
+ spec = util.spec_from_file_location(name, path)
+ specmod = util.module_from_spec(spec)
+ _imported.add(path)
+ spec.loader.exec_module(specmod)
+ _find_bps(specmod)
+
+ for bp in blueprints:
+ app.blueprint(bp)
+```
+:::
+::: tab blueprints/level1.py
+```python
+from sanic import Blueprint
+from sanic.log import logger
+
+level1 = Blueprint("level1")
+
+
+@level1.after_server_start
+def print_something(app, loop):
+ logger.debug("something @ level1")
+```
+:::
+::: tab blueprints/one/two/level3.py
+```python
+from sanic import Blueprint
+from sanic.log import logger
+
+level3 = Blueprint("level3")
+
+
+@level3.after_server_start
+def print_something(app, loop):
+ logger.debug("something @ level3")
+```
+:::
+::: tab listeners/something.py
+```python
+from sanic import Sanic
+from sanic.log import logger
+
+app = Sanic.get_app("auto")
+
+
+@app.after_server_start
+def print_something(app, loop):
+ logger.debug("something")
+```
+:::
+::: tab parent/child/__init__.py
+```python
+from sanic import Blueprint
+from sanic.log import logger
+
+bp = Blueprint("__init__")
+
+
+@bp.after_server_start
+def print_something(app, loop):
+ logger.debug("something inside __init__.py")
+```
+:::
+::: tab parent/child/nested.py
+```python
+from sanic import Blueprint
+from sanic.log import logger
+
+nested = Blueprint("nested")
+
+
+@nested.after_server_start
+def print_something(app, loop):
+ logger.debug("something @ nested")
+```
+:::
+::::
From 2090a4d123a1c5b730b8ce09c6c92b91f4001dd4 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:38 +0300
Subject: [PATCH 092/776] New translations README.md (Korean)
---
src/ko/guide/how-to/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/README.md
diff --git a/src/ko/guide/how-to/README.md b/src/ko/guide/how-to/README.md
new file mode 100644
index 0000000000..8e66fc0483
--- /dev/null
+++ b/src/ko/guide/how-to/README.md
@@ -0,0 +1 @@
+# How to ...
From 15b36fca62a02bd922a5dafbf97028b1731c3282 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:39 +0300
Subject: [PATCH 093/776] New translations README.md (Portuguese, Brazilian)
---
src/pt/guide/how-to/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/README.md
diff --git a/src/pt/guide/how-to/README.md b/src/pt/guide/how-to/README.md
new file mode 100644
index 0000000000..8e66fc0483
--- /dev/null
+++ b/src/pt/guide/how-to/README.md
@@ -0,0 +1 @@
+# How to ...
From 7c857324ee7379c60f89fe49f944fc3c2e1b9a59 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:40 +0300
Subject: [PATCH 094/776] New translations authentication.md (Japanese)
---
src/ja/guide/how-to/authentication.md | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/ja/guide/how-to/authentication.md b/src/ja/guide/how-to/authentication.md
index 0620baf7c6..25beb3e893 100644
--- a/src/ja/guide/how-to/authentication.md
+++ b/src/ja/guide/how-to/authentication.md
@@ -2,7 +2,7 @@
> 認証と認可を制御するにはどうすればよいですか。
-これは、いくつかのスニペットに詰め込むのが非常に複雑な問題です。しかし、これはこの問題に取り組む方法についてのアイデアを提供するはずです。この例では [JWT](https://jwt.io/)を使用していますが、この概念はセッションやその他のスキームにも同様に適用できます。
+これは、いくつかのスニペットに詰め込むのが非常に複雑な問題です。 しかし、これはこの問題に取り組む方法についてのアイデアを提供するはずです。 この例では [JWT](https://jwt.io/)を使用していますが、この概念はセッションやその他のスキームにも同様に適用できます。
:::: tabs
::: tab server.py
@@ -75,8 +75,8 @@ def protected(wrapped):
return decorator(wrapped)
```
-このデコレーターのパターンは、 [decorators page](/en/guide/best-practices/decorators.md) から取得されます。
-:::
+このデコレーターのパターンは、 [decorators page](/en/guide/best-practices/decorators.md) から取得されます。 :::
+:::: :::
::::
```bash
@@ -86,6 +86,14 @@ content-length: 21
connection: keep-alive
content-type: text/plain; charset=utf-8
+You are unauthorized.
+
+$ curl localhost:9999/secret -i
+HTTP/1.1 401 Unauthorized
+content-length: 21
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
あなたは許可されていません。
$ curl localhost:9999/login -X POST 7 ↵
From b5272a7b3fbd27610d4ed84279207fe885334b69 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:41 +0300
Subject: [PATCH 095/776] New translations authentication.md (Korean)
---
src/ko/guide/how-to/authentication.md | 113 ++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
create mode 100644 src/ko/guide/how-to/authentication.md
diff --git a/src/ko/guide/how-to/authentication.md b/src/ko/guide/how-to/authentication.md
new file mode 100644
index 0000000000..9d80fd4c0b
--- /dev/null
+++ b/src/ko/guide/how-to/authentication.md
@@ -0,0 +1,113 @@
+# Authentication
+
+> How do I control authentication and authorization?
+
+This is an _extremely_ complicated subject to cram into a few snippets. But, this should provide you with an idea on ways to tackle this problem. This example uses [JWTs](https://jwt.io/), but the concepts should be equally applicable to sessions or some other scheme.
+
+:::: tabs
+::: tab server.py
+```python
+from sanic import Sanic, text
+
+from auth import protected
+from login import login
+
+app = Sanic("AuthApp")
+app.config.SECRET = "KEEP_IT_SECRET_KEEP_IT_SAFE"
+app.blueprint(login)
+
+
+@app.get("/secret")
+@protected
+async def secret(request):
+ return text("To go fast, you must be fast.")
+```
+:::
+::: tab login.py
+```python
+import jwt
+from sanic import Blueprint, text
+
+login = Blueprint("login", url_prefix="/login")
+
+
+@login.post("/")
+async def do_login(request):
+ token = jwt.encode({}, request.app.config.SECRET)
+ return text(token)
+```
+:::
+::: tab auth.py
+```python
+from functools import wraps
+
+import jwt
+from sanic import text
+
+
+def check_token(request):
+ if not request.token:
+ return False
+
+ try:
+ jwt.decode(
+ request.token, request.app.config.SECRET, algorithms=["HS256"]
+ )
+ except jwt.exceptions.InvalidTokenError:
+ return False
+ else:
+ return True
+
+
+def protected(wrapped):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+ is_authenticated = check_token(request)
+
+ if is_authenticated:
+ response = await f(request, *args, **kwargs)
+ return response
+ else:
+ return text("You are unauthorized.", 401)
+
+ return decorated_function
+
+ return decorator(wrapped)
+```
+This decorator pattern is taken from the [decorators page](/en/guide/best-practices/decorators.md). :::
+::::
+
+```bash
+$ curl localhost:9999/secret -i
+HTTP/1.1 401 Unauthorized
+content-length: 21
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+You are unauthorized.
+
+$ curl localhost:9999/login -X POST 7 ↵
+eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30.rjxS7ztIGt5tpiRWS8BGLUqjQFca4QOetHcZTi061DE
+
+$ curl localhost:9999/secret -i -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30.rjxS7ztIGt5tpiRWS8BGLUqjQFca4QOetHcZTi061DE"
+HTTP/1.1 200 OK
+content-length: 29
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+To go fast, you must be fast.
+
+$ curl localhost:9999/secret -i -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30.BAD"
+HTTP/1.1 401 Unauthorized
+content-length: 21
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+You are unauthorized.
+```
+
+Also, checkout some resources from the community:
+
+- Awesome Sanic - [Authorization](https://github.com/mekicha/awesome-sanic/blob/master/README.md#authentication) & [Session](https://github.com/mekicha/awesome-sanic/blob/master/README.md#session)
+- [EuroPython 2020 - Overcoming access control in web APIs](https://www.youtube.com/watch?v=Uqgoj43ky6A)
From 325f89f94460c36d6e530be78e6e34e60c9428af Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:42 +0300
Subject: [PATCH 096/776] New translations authentication.md (Chinese
Simplified)
---
src/zh/guide/how-to/authentication.md | 43 ++++++++++++++-------------
1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/src/zh/guide/how-to/authentication.md b/src/zh/guide/how-to/authentication.md
index 5ffc401c56..ac346a8315 100644
--- a/src/zh/guide/how-to/authentication.md
+++ b/src/zh/guide/how-to/authentication.md
@@ -2,14 +2,9 @@
> 我该如何控制认证和权限?
-这是一个 *十分* 复杂的话题,很难用几行代码阐述清楚。尽管如此,本章节也许能够为您提供一些解决问题的思路。
+这是一个 *十分* 复杂的话题,很难用几行代码阐述清楚。 But, this should provide you with an idea on ways to tackle this problem. This example uses [JWTs](https://jwt.io/), but the concepts should be equally applicable to sessions or some other scheme.
下面的例子使用了 [JWTs](https://jwt.io/) 来实现,如果您想使用 session 或者是其他的方式,那做法应该是类似的。
-
-:::: tabs
-
-::: tab server.py
-
```python
from sanic import Sanic, text
@@ -26,10 +21,7 @@ app.blueprint(login)
async def secret(request):
return text("To go fast, you must be fast.")
```
-:::
-
-::: tab login.py
-
+:::: tabs
```python
import jwt
from sanic import Blueprint, text
@@ -42,10 +34,7 @@ async def do_login(request):
token = jwt.encode({}, request.app.config.SECRET)
return text(token)
```
-:::
-
-::: tab auth.py
-
+::: tab server.py
```python
from functools import wraps
@@ -83,11 +72,7 @@ def protected(wrapped):
return decorator(wrapped)
```
-
-这一段装饰器的代码来自于 [装饰器](/zh/guide/best-practices/decorators.md) 一节。
-
-:::
-
+这一段装饰器的代码来自于 [装饰器](/zh/guide/best-practices/decorators.md) 一节。 :::
::::
```bash
@@ -99,6 +84,14 @@ content-type: text/plain; charset=utf-8
You are unauthorized.
+$ curl localhost:9999/secret -i
+HTTP/1.1 401 Unauthorized
+content-length: 21
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+You are unauthorized.
+
$ curl localhost:9999/login -X POST 7 ↵
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30.rjxS7ztIGt5tpiRWS8BGLUqjQFca4QOetHcZTi061DE
@@ -116,10 +109,18 @@ content-length: 21
connection: keep-alive
content-type: text/plain; charset=utf-8
+You are unauthorized.
+
+$ curl localhost:9999/secret -i -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30.BAD"
+HTTP/1.1 401 Unauthorized
+content-length: 21
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
You are unauthorized.
```
-同时,您可以查看一下社区内提供的资源:
-
+::: tab login.py
+
- Awesome Sanic - [认证(Authentication)](https://github.com/mekicha/awesome-sanic/blob/master/README.md#authentication) & [会话(Session)](https://github.com/mekicha/awesome-sanic/blob/master/README.md#session)
- [EuroPython 2020 - Overcoming access control in web APIs](https://www.youtube.com/watch?v=Uqgoj43ky6A)
From b63002cec12b5fb616c1394d034a001b228e23da Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:43 +0300
Subject: [PATCH 097/776] New translations authentication.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/authentication.md | 113 ++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
create mode 100644 src/pt/guide/how-to/authentication.md
diff --git a/src/pt/guide/how-to/authentication.md b/src/pt/guide/how-to/authentication.md
new file mode 100644
index 0000000000..9d80fd4c0b
--- /dev/null
+++ b/src/pt/guide/how-to/authentication.md
@@ -0,0 +1,113 @@
+# Authentication
+
+> How do I control authentication and authorization?
+
+This is an _extremely_ complicated subject to cram into a few snippets. But, this should provide you with an idea on ways to tackle this problem. This example uses [JWTs](https://jwt.io/), but the concepts should be equally applicable to sessions or some other scheme.
+
+:::: tabs
+::: tab server.py
+```python
+from sanic import Sanic, text
+
+from auth import protected
+from login import login
+
+app = Sanic("AuthApp")
+app.config.SECRET = "KEEP_IT_SECRET_KEEP_IT_SAFE"
+app.blueprint(login)
+
+
+@app.get("/secret")
+@protected
+async def secret(request):
+ return text("To go fast, you must be fast.")
+```
+:::
+::: tab login.py
+```python
+import jwt
+from sanic import Blueprint, text
+
+login = Blueprint("login", url_prefix="/login")
+
+
+@login.post("/")
+async def do_login(request):
+ token = jwt.encode({}, request.app.config.SECRET)
+ return text(token)
+```
+:::
+::: tab auth.py
+```python
+from functools import wraps
+
+import jwt
+from sanic import text
+
+
+def check_token(request):
+ if not request.token:
+ return False
+
+ try:
+ jwt.decode(
+ request.token, request.app.config.SECRET, algorithms=["HS256"]
+ )
+ except jwt.exceptions.InvalidTokenError:
+ return False
+ else:
+ return True
+
+
+def protected(wrapped):
+ def decorator(f):
+ @wraps(f)
+ async def decorated_function(request, *args, **kwargs):
+ is_authenticated = check_token(request)
+
+ if is_authenticated:
+ response = await f(request, *args, **kwargs)
+ return response
+ else:
+ return text("You are unauthorized.", 401)
+
+ return decorated_function
+
+ return decorator(wrapped)
+```
+This decorator pattern is taken from the [decorators page](/en/guide/best-practices/decorators.md). :::
+::::
+
+```bash
+$ curl localhost:9999/secret -i
+HTTP/1.1 401 Unauthorized
+content-length: 21
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+You are unauthorized.
+
+$ curl localhost:9999/login -X POST 7 ↵
+eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30.rjxS7ztIGt5tpiRWS8BGLUqjQFca4QOetHcZTi061DE
+
+$ curl localhost:9999/secret -i -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30.rjxS7ztIGt5tpiRWS8BGLUqjQFca4QOetHcZTi061DE"
+HTTP/1.1 200 OK
+content-length: 29
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+To go fast, you must be fast.
+
+$ curl localhost:9999/secret -i -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e30.BAD"
+HTTP/1.1 401 Unauthorized
+content-length: 21
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+You are unauthorized.
+```
+
+Also, checkout some resources from the community:
+
+- Awesome Sanic - [Authorization](https://github.com/mekicha/awesome-sanic/blob/master/README.md#authentication) & [Session](https://github.com/mekicha/awesome-sanic/blob/master/README.md#session)
+- [EuroPython 2020 - Overcoming access control in web APIs](https://www.youtube.com/watch?v=Uqgoj43ky6A)
From 4b2dcdecf406e1c55f05d3db2d422feaa4dbad2b Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:44 +0300
Subject: [PATCH 098/776] New translations autodiscovery.md (Japanese)
---
src/ja/guide/how-to/autodiscovery.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/ja/guide/how-to/autodiscovery.md b/src/ja/guide/how-to/autodiscovery.md
index 74663a4228..0abea61ea4 100644
--- a/src/ja/guide/how-to/autodiscovery.md
+++ b/src/ja/guide/how-to/autodiscovery.md
@@ -7,11 +7,11 @@ title: Autodiscovery
> アプリケーションの構築に使用しているコンポーネントを自動検出するにはどうすればよいですか。
-アプリケーションを構築する際に直面する最初の問題の1つは、プロジェクトを 「どのように」 構築するかということです。Sanicはルートハンドラ、ミドルウェア、リスナーの登録にデコレータを多用しています。また、設計図を作成した後、アプリケーションにマウントする必要があります。
+アプリケーションを構築する際に直面する最初の問題の1つは、プロジェクトを 「どのように」 構築するかということです。 Sanicはルートハンドラ、ミドルウェア、リスナーの登録にデコレータを多用しています。 また、設計図を作成した後、アプリケーションにマウントする必要があります。
-可能な解決策は、**すべて**がインポートされ、Sanicインスタンスに適用される単一のファイルです。もう1つは、グローバル変数としてSanicインスタンスを渡す方法です。どちらの解決策にも欠点があります。
+可能な解決策は、**すべて**がインポートされ、Sanicインスタンスに適用される単一のファイルです。 もう1つは、グローバル変数としてSanicインスタンスを渡す方法です。 どちらの解決策にも欠点があります。
-もう1つの方法は、自動検出です。アプリケーションをモジュール(すでにインポートされている、または文字列)に向け、すべてを接続します。
+もう1つの方法は、自動検出です。 アプリケーションをモジュール(すでにインポートされている、または文字列)に向け、すべてを接続します。
:::: tabs
::: tab server.py
From 54dfc6aa10b0bdf6114b65bb1fd460582d7bd384 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:45 +0300
Subject: [PATCH 099/776] New translations autodiscovery.md (Chinese
Simplified)
---
src/zh/guide/how-to/autodiscovery.md | 45 +++++-----------------------
1 file changed, 7 insertions(+), 38 deletions(-)
diff --git a/src/zh/guide/how-to/autodiscovery.md b/src/zh/guide/how-to/autodiscovery.md
index 050b5bf492..ad2215060b 100644
--- a/src/zh/guide/how-to/autodiscovery.md
+++ b/src/zh/guide/how-to/autodiscovery.md
@@ -7,16 +7,13 @@ title: 自动发现(Autodiscovery)
> 我该如何自动发现我正在使用的组件来构建我的应用程序?
-当创建一个应用时,您可能碰到的第一个问题就是 *如何* 去组织一个项目。Sanic 十分依赖装饰器来注册路由、中间件和监听器。并且,在创建蓝图之后,也需要被挂载到应用上。
+当创建一个应用时,您可能碰到的第一个问题就是 *如何* 去组织一个项目。 Sanic 十分依赖装饰器来注册路由、中间件和监听器。 并且,在创建蓝图之后,也需要被挂载到应用上。
-一种解决方案是创建一个文件,在这个文件中导入 *所有* 的东西并且被应用于 Sanic 应用实例。另一种解决方式是将 Sanic 应用实例作为全局变量在不同文件中传递并使用。这两种方式都会有他的缺点。
+一种解决方案是创建一个文件,在这个文件中导入 *所有* 的东西并且被应用于 Sanic 应用实例。 另一种解决方式是将 Sanic 应用实例作为全局变量在不同文件中传递并使用。 这两种方式都会有他的缺点。
-而自动发现函数作为另一种补充。您可以把应用程序与模块(已经导入的对象或字符串)传入自动发现的函数中,该工具函数就会自动加载一切。
+而自动发现函数作为另一种补充。 您可以把应用程序与模块(已经导入的对象或字符串)传入自动发现的函数中,该工具函数就会自动加载一切。
:::: tabs
-
-::: tab server.py
-
```python
from sanic import Sanic
from sanic.response import empty
@@ -35,7 +32,6 @@ autodiscover(
app.route("/")(lambda _: empty())
```
-
```bash
[2021-03-02 21:37:02 +0200] [880451] [INFO] Goin' Fast @ http://127.0.0.1:9999
[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something
@@ -45,11 +41,7 @@ app.route("/")(lambda _: empty())
[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something inside __init__.py
[2021-03-02 21:37:02 +0200] [880451] [INFO] Starting worker [880451]
```
-
-:::
-
-::: tab utility.py
-
+::: tab server.py
```python
from glob import glob
@@ -98,11 +90,7 @@ def autodiscover(
for bp in blueprints:
app.blueprint(bp)
```
-
:::
-
-::: tab blueprints/level1.py
-
```python
from sanic import Blueprint
from sanic.log import logger
@@ -114,11 +102,7 @@ level1 = Blueprint("level1")
def print_something(app, loop):
logger.debug("something @ level1")
```
-
-:::
-
-::: tab blueprints/one/two/level3.py
-
+::: tab utility.py
```python
from sanic import Blueprint
from sanic.log import logger
@@ -130,11 +114,7 @@ level3 = Blueprint("level3")
def print_something(app, loop):
logger.debug("something @ level3")
```
-
:::
-
-::: tab listeners/something.py
-
```python
from sanic import Sanic
from sanic.log import logger
@@ -146,11 +126,7 @@ app = Sanic.get_app("auto")
def print_something(app, loop):
logger.debug("something")
```
-
-:::
-
-::: tab parent/child/__init__.py
-
+::: tab blueprints/level1.py
```python
from sanic import Blueprint
from sanic.log import logger
@@ -162,11 +138,7 @@ bp = Blueprint("__init__")
def print_something(app, loop):
logger.debug("something inside __init__.py")
```
-
:::
-
-::: tab parent/child/nested.py
-
```python
from sanic import Blueprint
from sanic.log import logger
@@ -178,7 +150,4 @@ nested = Blueprint("nested")
def print_something(app, loop):
logger.debug("something @ nested")
```
-
-:::
-
-::::
+::: tab blueprints/one/two/level3.py
From afbcf77cdf9a16ea229c30ebfd758f29cb3f1349 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:47 +0300
Subject: [PATCH 100/776] New translations autodiscovery.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/autodiscovery.md | 161 +++++++++++++++++++++++++++
1 file changed, 161 insertions(+)
create mode 100644 src/pt/guide/how-to/autodiscovery.md
diff --git a/src/pt/guide/how-to/autodiscovery.md b/src/pt/guide/how-to/autodiscovery.md
new file mode 100644
index 0000000000..4cf319357b
--- /dev/null
+++ b/src/pt/guide/how-to/autodiscovery.md
@@ -0,0 +1,161 @@
+---
+title: Autodiscovery
+---
+
+
+# Autodiscovery of Blueprints, Middleware, and Listeners
+
+> How do I autodiscover the components I am using to build my application?
+
+One of the first problems someone faces when building an application, is *how* to structure the project. Sanic makes heavy use of decorators to register route handlers, middleware, and listeners. And, after creating blueprints, they need to be mounted to the application.
+
+A possible solution is a single file in which **everything** is imported and applied to the Sanic instance. Another is passing around the Sanic instance as a global variable. Both of these solutions have their drawbacks.
+
+An alternative is autodiscovery. You point your application at modules (already imported, or strings), and let it wire everything up.
+
+:::: tabs
+::: tab server.py
+```python
+from sanic import Sanic
+from sanic.response import empty
+
+import blueprints
+from utility import autodiscover
+
+app = Sanic("auto", register=True)
+autodiscover(
+ app,
+ blueprints,
+ "parent.child",
+ "listeners.something",
+ recursive=True,
+)
+
+app.route("/")(lambda _: empty())
+```
+```bash
+[2021-03-02 21:37:02 +0200] [880451] [INFO] Goin' Fast @ http://127.0.0.1:9999
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something @ nested
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something @ level1
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something @ level3
+[2021-03-02 21:37:02 +0200] [880451] [DEBUG] something inside __init__.py
+[2021-03-02 21:37:02 +0200] [880451] [INFO] Starting worker [880451]
+```
+:::
+::: tab utility.py
+```python
+
+from glob import glob
+from importlib import import_module, util
+from inspect import getmembers
+from pathlib import Path
+from types import ModuleType
+from typing import Union
+
+from sanic.blueprints import Blueprint
+
+
+def autodiscover(
+ app, *module_names: Union[str, ModuleType], recursive: bool = False
+):
+ mod = app.__module__
+ blueprints = set()
+ _imported = set()
+
+ def _find_bps(module):
+ nonlocal blueprints
+
+ for _, member in getmembers(module):
+ if isinstance(member, Blueprint):
+ blueprints.add(member)
+
+ for module in module_names:
+ if isinstance(module, str):
+ module = import_module(module, mod)
+ _imported.add(module.__file__)
+ _find_bps(module)
+
+ if recursive:
+ base = Path(module.__file__).parent
+ for path in glob(f"{base}/**/*.py", recursive=True):
+ if path not in _imported:
+ name = "module"
+ if "__init__" in path:
+ *_, name, __ = path.split("/")
+ spec = util.spec_from_file_location(name, path)
+ specmod = util.module_from_spec(spec)
+ _imported.add(path)
+ spec.loader.exec_module(specmod)
+ _find_bps(specmod)
+
+ for bp in blueprints:
+ app.blueprint(bp)
+```
+:::
+::: tab blueprints/level1.py
+```python
+from sanic import Blueprint
+from sanic.log import logger
+
+level1 = Blueprint("level1")
+
+
+@level1.after_server_start
+def print_something(app, loop):
+ logger.debug("something @ level1")
+```
+:::
+::: tab blueprints/one/two/level3.py
+```python
+from sanic import Blueprint
+from sanic.log import logger
+
+level3 = Blueprint("level3")
+
+
+@level3.after_server_start
+def print_something(app, loop):
+ logger.debug("something @ level3")
+```
+:::
+::: tab listeners/something.py
+```python
+from sanic import Sanic
+from sanic.log import logger
+
+app = Sanic.get_app("auto")
+
+
+@app.after_server_start
+def print_something(app, loop):
+ logger.debug("something")
+```
+:::
+::: tab parent/child/__init__.py
+```python
+from sanic import Blueprint
+from sanic.log import logger
+
+bp = Blueprint("__init__")
+
+
+@bp.after_server_start
+def print_something(app, loop):
+ logger.debug("something inside __init__.py")
+```
+:::
+::: tab parent/child/nested.py
+```python
+from sanic import Blueprint
+from sanic.log import logger
+
+nested = Blueprint("nested")
+
+
+@nested.after_server_start
+def print_something(app, loop):
+ logger.debug("something @ nested")
+```
+:::
+::::
From 80aa44826f11038a303bf194eae218886427b110 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:49 +0300
Subject: [PATCH 101/776] New translations cors.md (Korean)
---
src/ko/guide/how-to/cors.md | 135 ++++++++++++++++++++++++++++++++++++
1 file changed, 135 insertions(+)
create mode 100644 src/ko/guide/how-to/cors.md
diff --git a/src/ko/guide/how-to/cors.md b/src/ko/guide/how-to/cors.md
new file mode 100644
index 0000000000..f230137703
--- /dev/null
+++ b/src/ko/guide/how-to/cors.md
@@ -0,0 +1,135 @@
+---
+title: CORS
+---
+
+
+# Cross-origin resource sharing (CORS)
+
+> How do I configure my application for CORS?
+
+:::: tabs
+::: tab server.py
+```python
+from sanic import Sanic, text
+
+from cors import add_cors_headers
+from options import setup_options
+
+app = Sanic("app")
+
+
+@app.route("/", methods=["GET", "POST"])
+async def do_stuff(request):
+ return text("...")
+
+
+# Add OPTIONS handlers to any route that is missing it
+app.register_listener(setup_options, "before_server_start")
+
+# Fill in CORS headers
+app.register_middleware(add_cors_headers, "response")
+```
+:::
+::: tab cors.py
+```python
+from typing import Iterable
+
+
+def _add_cors_headers(response, methods: Iterable[str]) -> None:
+ allow_methods = list(set(methods))
+ if "OPTIONS" not in allow_methods:
+ allow_methods.append("OPTIONS")
+ headers = {
+ "Access-Control-Allow-Methods": ",".join(allow_methods),
+ "Access-Control-Allow-Origin": "mydomain.com",
+ "Access-Control-Allow-Credentials": "true",
+ "Access-Control-Allow-Headers": (
+ "origin, content-type, accept, "
+ "authorization, x-xsrf-token, x-request-id"
+ ),
+ }
+ response.headers.extend(headers)
+
+
+def add_cors_headers(request, response):
+ if request.method != "OPTIONS":
+ methods = [method for method in request.route.methods]
+ _add_cors_headers(response, methods)
+```
+:::
+::: tab options.py
+```python
+from collections import defaultdict
+from typing import Dict, FrozenSet
+
+from sanic import Sanic, response
+from sanic.router import Route
+
+from cors import _add_cors_headers
+
+
+def _compile_routes_needing_options(
+ routes: Dict[str, Route]
+) -> Dict[str, FrozenSet]:
+ needs_options = defaultdict(list)
+ # This is 21.12 and later. You will need to change this for older versions.
+ for route in routes.values():
+ if "OPTIONS" not in route.methods:
+ needs_options[route.uri].extend(route.methods)
+
+ return {
+ uri: frozenset(methods) for uri, methods in dict(needs_options).items()
+ }
+
+
+def _options_wrapper(handler, methods):
+ def wrapped_handler(request, *args, **kwargs):
+ nonlocal methods
+ return handler(request, methods)
+
+ return wrapped_handler
+
+
+async def options_handler(request, methods) -> response.HTTPResponse:
+ resp = response.empty()
+ _add_cors_headers(resp, methods)
+ return resp
+
+
+def setup_options(app: Sanic, _):
+ app.router.reset()
+ needs_options = _compile_routes_needing_options(app.router.routes_all)
+ for uri, methods in needs_options.items():
+ app.add_route(
+ _options_wrapper(options_handler, methods),
+ uri,
+ methods=["OPTIONS"],
+ )
+ app.router.finalize()
+```
+:::
+::::
+```
+$ curl localhost:9999/ -i
+HTTP/1.1 200 OK
+Access-Control-Allow-Methods: OPTIONS,POST,GET
+Access-Control-Allow-Origin: mydomain.com
+Access-Control-Allow-Credentials: true
+Access-Control-Allow-Headers: origin, content-type, accept, authorization, x-xsrf-token, x-request-id
+content-length: 3
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+...
+
+$ curl localhost:9999/ -i -X OPTIONS
+HTTP/1.1 204 No Content
+Access-Control-Allow-Methods: GET,POST,OPTIONS
+Access-Control-Allow-Origin: mydomain.com
+Access-Control-Allow-Credentials: true
+Access-Control-Allow-Headers: origin, content-type, accept, authorization, x-xsrf-token, x-request-id
+connection: keep-alive
+```
+Also, checkout some resources from the community:
+
+- [Awesome Sanic](https://github.com/mekicha/awesome-sanic/blob/master/README.md#frontend)
From c780c9ce0ead3239d2483650b424b9da806d85ef Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:50 +0300
Subject: [PATCH 102/776] New translations cors.md (Chinese Simplified)
---
src/zh/guide/how-to/cors.md | 64 +++++++++++++++++++++++++++----------
1 file changed, 48 insertions(+), 16 deletions(-)
diff --git a/src/zh/guide/how-to/cors.md b/src/zh/guide/how-to/cors.md
index 6fa13f5973..69605009a0 100644
--- a/src/zh/guide/how-to/cors.md
+++ b/src/zh/guide/how-to/cors.md
@@ -8,9 +8,6 @@ title: 跨域资源共享(CORS)
> 我该如何配置跨域资源共享?
:::: tabs
-
-::: tab server.py
-
```python
from sanic import Sanic, text
@@ -30,12 +27,15 @@ app.register_listener(setup_options, "before_server_start")
# Fill in CORS headers
app.register_middleware(add_cors_headers, "response")
-```
-:::
-::: tab cors.py
+# Add OPTIONS handlers to any route that is missing it
+app.register_listener(setup_options, "before_server_start")
+# Fill in CORS headers
+app.register_middleware(add_cors_headers, "response")
+```
+::: tab server.py
```python
from typing import Iterable
@@ -65,11 +65,7 @@ def add_cors_headers(request, response):
]
_add_cors_headers(response, methods)
```
-
:::
-
-::: tab options.py
-
```python
from collections import defaultdict
from typing import Dict, FrozenSet
@@ -117,13 +113,42 @@ def setup_options(app: Sanic, _):
uri,
methods=["OPTIONS"],
)
- app.router.finalize()
-```
+ app.router.finalize() You will need to change this for older versions.
+ for route in routes.values():
+ if "OPTIONS" not in route.methods:
+ needs_options[route.uri].extend(route.methods)
-:::
+ return {
+ uri: frozenset(methods) for uri, methods in dict(needs_options).items()
+ }
+
+
+def _options_wrapper(handler, methods):
+ def wrapped_handler(request, *args, **kwargs):
+ nonlocal methods
+ return handler(request, methods)
+
+ return wrapped_handler
+
+
+async def options_handler(request, methods) -> response.HTTPResponse:
+ resp = response.empty()
+ _add_cors_headers(resp, methods)
+ return resp
-::::
+def setup_options(app: Sanic, _):
+ app.router.reset()
+ needs_options = _compile_routes_needing_options(app.router.routes_all)
+ for uri, methods in needs_options.items():
+ app.add_route(
+ _options_wrapper(options_handler, methods),
+ uri,
+ methods=["OPTIONS"],
+ )
+ app.router.finalize()
+```
+::: tab cors.py
```
$ curl localhost:9999/ -i
HTTP/1.1 200 OK
@@ -144,8 +169,15 @@ Access-Control-Allow-Origin: mydomain.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: origin, content-type, accept, authorization, x-xsrf-token, x-request-id
connection: keep-alive
-```
-同时,您可以查看一下社区内提供的资源:
+$ curl localhost:9999/ -i -X OPTIONS
+HTTP/1.1 204 No Content
+Access-Control-Allow-Methods: GET,POST,OPTIONS
+Access-Control-Allow-Origin: mydomain.com
+Access-Control-Allow-Credentials: true
+Access-Control-Allow-Headers: origin, content-type, accept, authorization, x-xsrf-token, x-request-id
+connection: keep-alive
+```
+:::
- [Awesome Sanic](https://github.com/mekicha/awesome-sanic/blob/master/README.md#frontend)
From ae2775047ec55ad136246ea0b379536f452ebc29 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:51 +0300
Subject: [PATCH 103/776] New translations cors.md (Portuguese, Brazilian)
---
src/pt/guide/how-to/cors.md | 135 ++++++++++++++++++++++++++++++++++++
1 file changed, 135 insertions(+)
create mode 100644 src/pt/guide/how-to/cors.md
diff --git a/src/pt/guide/how-to/cors.md b/src/pt/guide/how-to/cors.md
new file mode 100644
index 0000000000..f230137703
--- /dev/null
+++ b/src/pt/guide/how-to/cors.md
@@ -0,0 +1,135 @@
+---
+title: CORS
+---
+
+
+# Cross-origin resource sharing (CORS)
+
+> How do I configure my application for CORS?
+
+:::: tabs
+::: tab server.py
+```python
+from sanic import Sanic, text
+
+from cors import add_cors_headers
+from options import setup_options
+
+app = Sanic("app")
+
+
+@app.route("/", methods=["GET", "POST"])
+async def do_stuff(request):
+ return text("...")
+
+
+# Add OPTIONS handlers to any route that is missing it
+app.register_listener(setup_options, "before_server_start")
+
+# Fill in CORS headers
+app.register_middleware(add_cors_headers, "response")
+```
+:::
+::: tab cors.py
+```python
+from typing import Iterable
+
+
+def _add_cors_headers(response, methods: Iterable[str]) -> None:
+ allow_methods = list(set(methods))
+ if "OPTIONS" not in allow_methods:
+ allow_methods.append("OPTIONS")
+ headers = {
+ "Access-Control-Allow-Methods": ",".join(allow_methods),
+ "Access-Control-Allow-Origin": "mydomain.com",
+ "Access-Control-Allow-Credentials": "true",
+ "Access-Control-Allow-Headers": (
+ "origin, content-type, accept, "
+ "authorization, x-xsrf-token, x-request-id"
+ ),
+ }
+ response.headers.extend(headers)
+
+
+def add_cors_headers(request, response):
+ if request.method != "OPTIONS":
+ methods = [method for method in request.route.methods]
+ _add_cors_headers(response, methods)
+```
+:::
+::: tab options.py
+```python
+from collections import defaultdict
+from typing import Dict, FrozenSet
+
+from sanic import Sanic, response
+from sanic.router import Route
+
+from cors import _add_cors_headers
+
+
+def _compile_routes_needing_options(
+ routes: Dict[str, Route]
+) -> Dict[str, FrozenSet]:
+ needs_options = defaultdict(list)
+ # This is 21.12 and later. You will need to change this for older versions.
+ for route in routes.values():
+ if "OPTIONS" not in route.methods:
+ needs_options[route.uri].extend(route.methods)
+
+ return {
+ uri: frozenset(methods) for uri, methods in dict(needs_options).items()
+ }
+
+
+def _options_wrapper(handler, methods):
+ def wrapped_handler(request, *args, **kwargs):
+ nonlocal methods
+ return handler(request, methods)
+
+ return wrapped_handler
+
+
+async def options_handler(request, methods) -> response.HTTPResponse:
+ resp = response.empty()
+ _add_cors_headers(resp, methods)
+ return resp
+
+
+def setup_options(app: Sanic, _):
+ app.router.reset()
+ needs_options = _compile_routes_needing_options(app.router.routes_all)
+ for uri, methods in needs_options.items():
+ app.add_route(
+ _options_wrapper(options_handler, methods),
+ uri,
+ methods=["OPTIONS"],
+ )
+ app.router.finalize()
+```
+:::
+::::
+```
+$ curl localhost:9999/ -i
+HTTP/1.1 200 OK
+Access-Control-Allow-Methods: OPTIONS,POST,GET
+Access-Control-Allow-Origin: mydomain.com
+Access-Control-Allow-Credentials: true
+Access-Control-Allow-Headers: origin, content-type, accept, authorization, x-xsrf-token, x-request-id
+content-length: 3
+connection: keep-alive
+content-type: text/plain; charset=utf-8
+
+...
+
+$ curl localhost:9999/ -i -X OPTIONS
+HTTP/1.1 204 No Content
+Access-Control-Allow-Methods: GET,POST,OPTIONS
+Access-Control-Allow-Origin: mydomain.com
+Access-Control-Allow-Credentials: true
+Access-Control-Allow-Headers: origin, content-type, accept, authorization, x-xsrf-token, x-request-id
+connection: keep-alive
+```
+Also, checkout some resources from the community:
+
+- [Awesome Sanic](https://github.com/mekicha/awesome-sanic/blob/master/README.md#frontend)
From 22a46be581fdb2ad83911ca0c75a1b6c93ae9e31 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:53 +0300
Subject: [PATCH 104/776] New translations csrf.md (Korean)
---
src/ko/guide/how-to/csrf.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/csrf.md
diff --git a/src/ko/guide/how-to/csrf.md b/src/ko/guide/how-to/csrf.md
new file mode 100644
index 0000000000..7f982ff12f
--- /dev/null
+++ b/src/ko/guide/how-to/csrf.md
@@ -0,0 +1 @@
+csrf
From 2ee431e6f005383c2c8c9afde14784520ea83637 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:54 +0300
Subject: [PATCH 105/776] New translations csrf.md (Portuguese, Brazilian)
---
src/pt/guide/how-to/csrf.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/csrf.md
diff --git a/src/pt/guide/how-to/csrf.md b/src/pt/guide/how-to/csrf.md
new file mode 100644
index 0000000000..7f982ff12f
--- /dev/null
+++ b/src/pt/guide/how-to/csrf.md
@@ -0,0 +1 @@
+csrf
From 834802d310cf490c0309736c23e748a6912603e7 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:56 +0300
Subject: [PATCH 106/776] New translations server-choice.md (Portuguese,
Brazilian)
---
src/pt/guide/deployment/server-choice.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/deployment/server-choice.md
diff --git a/src/pt/guide/deployment/server-choice.md b/src/pt/guide/deployment/server-choice.md
new file mode 100644
index 0000000000..9af6345235
--- /dev/null
+++ b/src/pt/guide/deployment/server-choice.md
@@ -0,0 +1 @@
+# Choosing a server
From 19ac4391042c31dfae98de24f1f5e56e8663aef0 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:57 +0300
Subject: [PATCH 107/776] New translations server-choice.md (Korean)
---
src/ko/guide/deployment/server-choice.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/deployment/server-choice.md
diff --git a/src/ko/guide/deployment/server-choice.md b/src/ko/guide/deployment/server-choice.md
new file mode 100644
index 0000000000..9af6345235
--- /dev/null
+++ b/src/ko/guide/deployment/server-choice.md
@@ -0,0 +1 @@
+# Choosing a server
From 4a86775d55da5cbaaf95a4bbbb4cdbd373c2900a Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:58 +0300
Subject: [PATCH 108/776] New translations configuration.md (Korean)
---
src/ko/guide/deployment/configuration.md | 224 +++++++++++++++++++++++
1 file changed, 224 insertions(+)
create mode 100644 src/ko/guide/deployment/configuration.md
diff --git a/src/ko/guide/deployment/configuration.md b/src/ko/guide/deployment/configuration.md
new file mode 100644
index 0000000000..fa25b1c6be
--- /dev/null
+++ b/src/ko/guide/deployment/configuration.md
@@ -0,0 +1,224 @@
+# Configuration
+
+## Basics
+
+
+---:1
+
+Sanic holds the configuration in the config attribute of the application object. The configuration object is merely an object that can be modified either using dot-notation or like a dictionary. :--:1
+```python
+app = Sanic("myapp")
+app.config.DB_NAME = "appdb"
+app.config["DB_USER"] = "appuser"
+```
+:---
+
+---:1
+
+You can also use the `update()` method like on regular dictionaries. :--:1
+```python
+db_settings = {
+ 'DB_HOST': 'localhost',
+ 'DB_NAME': 'appdb',
+ 'DB_USER': 'appuser'
+}
+app.config.update(db_settings)
+```
+:---
+
+::: tip It is standard practice in Sanic to name your config values in **uppercase letters**. Indeed, you may experience weird behaviors if you start mixing uppercase and lowercase names. :::
+
+## Loading
+
+### Environment variables
+
+---:1
+
+Any environment variables defined with the `SANIC_` prefix will be applied to the Sanic config. For example, setting `SANIC_REQUEST_TIMEOUT` will be loaded by the application automatically and fed into the `REQUEST_TIMEOUT` config variable. :--:1
+```bash
+$ export SANIC_REQUEST_TIMEOUT=10
+```
+```python
+>>> print(app.config.REQUEST_TIMEOUT)
+10
+```
+:---
+
+---:1
+
+You can change the prefix that Sanic is expecting at startup. :--:1
+```bash
+$ export MYAPP_REQUEST_TIMEOUT=10
+```
+```python
+>>> app = Sanic(__name__, env_prefix='MYAPP_')
+>>> print(app.config.REQUEST_TIMEOUT)
+10
+```
+:---
+
+---:1
+
+You can also disable environment variable loading completely. :--:1
+```python
+app = Sanic(__name__, load_env=False)
+```
+:---
+
+### Using Sanic.update_config
+
+The `Sanic` instance has a _very_ versatile method for loading config: `app.update_config`. You can feed it a path to a file, a dictionary, a class, or just about any other sort of object.
+
+#### From a file
+
+---:1
+
+Let's say you have `my_config.py` file that looks like this. :--:1
+```python
+# my_config.py
+A = 1
+B = 2
+```
+:---
+
+---:1
+
+You can load this as config values by passing its path to `app.update_config`. :--:1
+```python
+>>> app.update_config("/path/to/my_config.py")
+>>> print(app.config.A)
+1
+```
+:---
+
+---:1
+
+This path also accepts bash style environment variables. :--:1
+```bash
+$ export my_path="/path/to"
+```
+```python
+app.update_config("${my_path}/my_config.py")
+```
+:---
+
+::: tip Just remember that you have to provide environment variables in the format `${environment_variable}` and that `$environment_variable` is not expanded (is treated as "plain" text). :::
+#### From a dict
+
+---:1
+
+The `app.update_config` method also works on plain dictionaries. :--:1
+```python
+app.update_config({"A": 1, "B": 2})
+```
+:---
+
+#### From a class or object
+
+---:1
+
+You can define your own config class, and pass it to `app.update_config` :--:1
+```python
+class MyConfig:
+ A = 1
+ B = 2
+
+app.update_config(MyConfig)
+```
+:---
+
+---:1
+
+It even could be instantiated. :--:1
+```python
+app.update_config(MyConfig())
+```
+:---
+
+### Type casting
+
+When loading from environment variables, Sanic will attempt to cast the values to expected Python types. This particularly applies to:
+
+- `int`
+- `float`
+- `bool`
+
+In regards to `bool`, the following _case insensitive_ values are allowed:
+
+- **`True`**: `y`, `yes`, `yep`, `yup`, `t`, `true`, `on`, `enable`, `enabled`, `1`
+- **`False`**: `n`, `no`, `f`, `false`, `off`, `disable`, `disabled`, `0`
+
+---:1 Additionally, Sanic can be configured to cast additional types using additional type converters. This should be any callable that returns the value or raises a `ValueError`. :--:1
+```python
+app = Sanic(..., config=Config(converters=[UUID]))
+```
+:---
+
+## Builtin values
+
+
+| **Variable** | **Default** | **Description** |
+| --------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
+| ACCESS_LOG | True | Disable or enable access log |
+| AUTO_EXTEND ^ | True | Control whether [Sanic Extensions](../../plugins/sanic-ext/getting-started.md) will load if it is in the existing virtual environment |
+| AUTO_RELOAD | True | Control whether the application will automatically reload when a file changes |
+| EVENT_AUTOREGISTER | True | When `True` using the `app.event()` method on a non-existing signal will automatically create it and not raise an exception |
+| FALLBACK_ERROR_FORMAT | html | Format of error response if an exception is not caught and handled |
+| FORWARDED_FOR_HEADER | X-Forwarded-For | The name of "X-Forwarded-For" HTTP header that contains client and proxy ip |
+| FORWARDED_SECRET | None | Used to securely identify a specific proxy server (see below) |
+| GRACEFUL_SHUTDOWN_TIMEOUT | 15.0 | How long to wait to force close non-idle connection (sec) |
+| KEEP_ALIVE | True | Disables keep-alive when False |
+| KEEP_ALIVE_TIMEOUT | 5 | How long to hold a TCP connection open (sec) |
+| MOTD ^ | True | Whether to display the MOTD (message of the day) at startup |
+| MOTD_DISPLAY ^ | {} | Key/value pairs to display additional, arbitrary data in the MOTD |
+| NOISY_EXCEPTIONS ^ | False | Force all `quiet` exceptions to be logged |
+| PROXIES_COUNT | None | The number of proxy servers in front of the app (e.g. nginx; see below) |
+| REAL_IP_HEADER | None | The name of "X-Real-IP" HTTP header that contains real client ip |
+| REGISTER | True | Whether the app registry should be enabled |
+| REQUEST_BUFFER_SIZE | 65536 | Request buffer size before request is paused, default is 64 Kib |
+| REQUEST_ID_HEADER | X-Request-ID | The name of "X-Request-ID" HTTP header that contains request/correlation ID |
+| REQUEST_MAX_SIZE | 100000000 | How big a request may be (bytes), default is 100 megabytes |
+| REQUEST_TIMEOUT | 60 | How long a request can take to arrive (sec) |
+| RESPONSE_TIMEOUT | 60 | How long a response can take to process (sec) |
+| USE_UVLOOP | True | Whether to override the loop policy to use `uvloop`. Supported only with `app.run`. |
+| WEBSOCKET_MAX_SIZE | 2^20 | Maximum size for incoming messages (bytes) |
+| WEBSOCKET_PING_INTERVAL | 20 | A Ping frame is sent every ping_interval seconds. |
+| WEBSOCKET_PING_TIMEOUT | 20 | Connection is closed when Pong is not received after ping_timeout seconds |
+
+::: tip FYI
+- The `USE_UVLOOP` value will be ignored if running with Gunicorn. Defaults to `False` on non-supported platforms (Windows).
+- The `WEBSOCKET_` values will be ignored if in ASGI mode. :::
+
+## Timeouts
+
+### REQUEST_TIMEOUT
+
+A request timeout measures the duration of time between the instant when a new open TCP connection is passed to the Sanic backend server, and the instant when the whole HTTP request is received. If the time taken exceeds the `REQUEST_TIMEOUT` value (in seconds), this is considered a Client Error so Sanic generates an `HTTP 408` response and sends that to the client. Set this parameter's value higher if your clients routinely pass very large request payloads or upload requests very slowly.
+
+### RESPONSE_TIMEOUT
+
+A response timeout measures the duration of time between the instant the Sanic server passes the HTTP request to the Sanic App, and the instant a HTTP response is sent to the client. If the time taken exceeds the `RESPONSE_TIMEOUT` value (in seconds), this is considered a Server Error so Sanic generates an `HTTP 503` response and sends that to the client. Set this parameter's value higher if your application is likely to have long-running process that delay the generation of a response.
+
+### KEEP_ALIVE_TIMEOUT
+
+#### What is Keep Alive? And what does the Keep Alive Timeout value do?
+
+`Keep-Alive` is a HTTP feature introduced in `HTTP 1.1`. When sending a HTTP request, the client (usually a web browser application) can set a `Keep-Alive` header to indicate the http server (Sanic) to not close the TCP connection after it has send the response. This allows the client to reuse the existing TCP connection to send subsequent HTTP requests, and ensures more efficient network traffic for both the client and the server.
+
+The `KEEP_ALIVE` config variable is set to `True` in Sanic by default. If you don't need this feature in your application, set it to `False` to cause all client connections to close immediately after a response is sent, regardless of the `Keep-Alive` header on the request.
+
+The amount of time the server holds the TCP connection open is decided by the server itself. In Sanic, that value is configured using the `KEEP_ALIVE_TIMEOUT` value. By default, it is set to 5 seconds. This is the same default setting as the Apache HTTP server and is a good balance between allowing enough time for the client to send a new request, and not holding open too many connections at once. Do not exceed 75 seconds unless you know your clients are using a browser which supports TCP connections held open for that long.
+
+For reference:
+
+* Apache httpd server default keepalive timeout = 5 seconds
+* Nginx server default keepalive timeout = 75 seconds
+* Nginx performance tuning guidelines uses keepalive = 15 seconds
+* IE (5-9) client hard keepalive limit = 60 seconds
+* Firefox client hard keepalive limit = 115 seconds
+* Opera 11 client hard keepalive limit = 120 seconds
+* Chrome 13+ client keepalive limit > 300+ seconds
+
+## Proxy configuration
+
+See [proxy configuration section](/guide/advanced/proxy-headers.md)
From 5aee4f7dd93b857837588afa68e84ae0e4c245ab Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:44:59 +0300
Subject: [PATCH 109/776] New translations configuration.md (Chinese
Simplified)
---
src/zh/guide/deployment/configuration.md | 191 ++++++++---------------
1 file changed, 64 insertions(+), 127 deletions(-)
diff --git a/src/zh/guide/deployment/configuration.md b/src/zh/guide/deployment/configuration.md
index e3f3470dd0..21ce7662a6 100644
--- a/src/zh/guide/deployment/configuration.md
+++ b/src/zh/guide/deployment/configuration.md
@@ -2,26 +2,20 @@
## 基础(Basics)
----:1
-
-Sanic 会将配置保存在应用程序对象的 Config 属性中,它是一个可以通过字典的形式或者属性的形式进行操作的对象。
-:--:1
+---:1
+Sanic 会将配置保存在应用程序对象的 Config 属性中,它是一个可以通过字典的形式或者属性的形式进行操作的对象。 The configuration object is merely an object that can be modified either using dot-notation or like a dictionary. :--:1
```python
app = Sanic("myapp")
app.config.DB_NAME = "appdb"
app.config["DB_USER"] = "appuser"
```
-
:---
---:1
-因此,您也可以使用 `update()` 方法来更新配置。
-
-:--:1
-
+因此,您也可以使用 `update()` 方法来更新配置。 :--:1
```python
db_settings = {
'DB_HOST': 'localhost',
@@ -30,14 +24,9 @@ db_settings = {
}
app.config.update(db_settings)
```
-
:---
-::: tip 小提示
-
-在 Sanic 中, 标准做法是使用 **大写字母** 来命名您的配置名称,如果您将大写名称和小写名称混合使用,可能会导致某些配置无法正常读取,遇到无法解释的状况。
-
-:::
+在 Sanic 中, 标准做法是使用 **大写字母** 来命名您的配置名称,如果您将大写名称和小写名称混合使用,可能会导致某些配置无法正常读取,遇到无法解释的状况。 Indeed, you may experience weird behaviors if you start mixing uppercase and lowercase names. :::
## 配置加载(Loading)
@@ -45,119 +34,83 @@ app.config.update(db_settings)
---:1
-任何使用 `SANIC_` 作为前缀的环境变量都会被加载并应用于 Sanic 配置。例如:在环境变量中设置 `SANIC_REQUEST_TIMEOUT` 环境变量后,将会被应用程序自动加载,并传递到 `REQUEST_TIMEOUT` 配置变量中。
-
-:--:1
-
+任何使用 `SANIC_` 作为前缀的环境变量都会被加载并应用于 Sanic 配置。 例如:在环境变量中设置 `SANIC_REQUEST_TIMEOUT` 环境变量后,将会被应用程序自动加载,并传递到 `REQUEST_TIMEOUT` 配置变量中。 :--:1
```bash
$ export SANIC_REQUEST_TIMEOUT=10
```
-
```python
>>> print(app.config.REQUEST_TIMEOUT)
10
```
-
:---
---:1
-您可以自动选择启动时应用程序要读取的变量前缀。
-
-:--:1
-
+You can change the prefix that Sanic is expecting at startup. :--:1
```bash
$ export MYAPP_REQUEST_TIMEOUT=10
```
-
```python
>>> app = Sanic(__name__, load_env='MYAPP_')
>>> print(app.config.REQUEST_TIMEOUT)
10
```
-
:---
---:1
-同样,您可以完全禁用环境变量的加载。
-
-:--:1
-
+同样,您可以完全禁用环境变量的加载。 :--:1
```python
app = Sanic(__name__, load_env=False)
```
-
:---
### 使用通用方法加载(Using Sanic.update_config)
-`Sanic` 中有一种通用的方法用于加载配置:`app.update_config` 。您可以通过向它提供文件路径、字典、类或者几乎任何其他种类的对象的路径来更新配置。
+`Sanic` 中有一种通用的方法用于加载配置:`app.update_config` 。 您可以通过向它提供文件路径、字典、类或者几乎任何其他种类的对象的路径来更新配置。
#### 通过文件加载(From a file)
---:1
-假设您有一个名为 `my_config.py` 的文件,它的内容如下:
-
-:--:1
-
+假设您有一个名为 `my_config.py` 的文件,它的内容如下: :--:1
```python
# my_config.py
A = 1
B = 2
```
-
:---
---:1
-您可以通过将文件路径传递给 `app.update_config` 进行配置加载。
-
-:--:1
-
+您可以通过将文件路径传递给 `app.update_config` 进行配置加载。 :--:1
```python
>>> app.update_config("/path/to/my_config.py")
>>> print(app.config.A)
1
```
-
:---
---:1
-它同样接受 bash 风格的环境变量。
-
-:--:1
-
+它同样接受 bash 风格的环境变量。 :--:1
```bash
$ export my_path="/path/to"
```
-
```python
app.update_config("${my_path}/my_config.py")
```
-
:---
-::: tip 小提示
-
-请记住,您必须以 `$environment_variable` 的格式来提供环境变量。而且 `${environment_variable}` 被视作纯文本(没有使用字符串格式化)
-
-:::
-
+请记住,您必须以 `$environment_variable` 的格式来提供环境变量。 :::
#### 通过字典加载(From a dict)
---:1
-`app.update_config` 的方法同样适用于字典
-
-:--:1
-
+The `app.update_config` method also works on plain dictionaries. :--:1
```python
app.update_config({"A": 1, "B": 2})
```
-
:---
#### 通过类加载(From a class or object)
@@ -165,9 +118,6 @@ app.update_config({"A": 1, "B": 2})
---:1
您可以自定义配置类,并将该类传递给 `app.update_config`
-
-:--:1
-
```python
class MyConfig:
A = 1
@@ -175,24 +125,19 @@ class MyConfig:
app.update_config(MyConfig)
```
-
:---
---:1
-甚至您可以向它传递一个实例化好的对象
-
-:--:1
-
+It even could be instantiated. :--:1
```python
app.update_config(MyConfig())
```
-
:---
### 类型转换(Type casting)
-从环境变量加载时,Sanic 将尝试将值转换为预期的 Python 类型。这尤其适用于:
+从环境变量加载时,Sanic 将尝试将值转换为预期的 Python 类型。 这尤其适用于:
- `int`
- `float`
@@ -203,84 +148,76 @@ app.update_config(MyConfig())
- **`True`**: `y`, `yes`, `yep`, `yup`, `t`, `true`, `on`, `enable`, `enabled`, `1`
- **`False`**: `n`, `no`, `f`, `false`, `off`, `disable`, `disabled`, `0`
----:1
-
-此外,Sanic 可以通过配置类型转换器来进行类型转换。这应该是一个能够返回任何值且能触发 `ValueError` 的可调用函数。
-
-:--:1
-
+此外,Sanic 可以通过配置类型转换器来进行类型转换。 这应该是一个能够返回任何值且能触发 `ValueError` 的可调用函数。 :--:1
```python
app = Sanic(..., config=Config(converters=[UUID]))
```
-
:---
## 内置配置(Builtin values)
-| 变量名称 | 默认值 | 说明 |
-| :------------------------ | --------------- | -------------------------------------------------- |
-| ACCESS_LOG | True | 访问日志开关 |
-| AUTO_EXTEND^ | True | Sanic 拓展启用开关 |
-| AUTO_RELOAD | True | 自动重载开关 |
-| EVENT_AUTOREGISTER | True | 自动注册信号开关(开启后不存在的事件将会自动注册) |
-| FALLBACK_ERROR_FORMAT | html | 异常返回格式 |
-| FORWARDED_FOR_HEADER | X-Forwarded-For | 客户端 IP 和代理 IP:X-Forwarded-For |
-| FORWARDED_SECRET | None | 用于安全地识别特定的代理服务器(见下文) |
-| GRACEFUL_SHUTDOWN_TIMEOUT | 15.0 | 强制关闭非空闲连接的等待时间(秒) |
-| KEEP_ALIVE | True | 是否启用长连接 |
-| KEEP_ALIVE_TIMEOUT | 5 | 长连接超时时间 |
-| MOTD^ | True | 是否在启动时展示 MOTD 信息 |
-| MOTD_DISPLAY | {} | 键/值对显示 MOTD 中的附加任意数据 |
-| NOISY_EXCEPTIONS ^ | False | 强制禁止异常输出 |
-| PROXIES_COUNT | None | 应用程序钱代理服务器的数量(见下文) |
-| REAL_IP_HEADER | None | 客户端真实 IP: X-Real-IP |
-| REGISTER | True | 是否启用应用程序注册表 |
-| REQUEST_BUFFER_QUEUE_SIZE | 100 | 请求流缓冲区队列大小 |
-| REQUEST_ID_HEADER | X-Request-ID | 请求头中的请求 ID 名称:X-Request-ID |
-| REQUEST_MAX_SIZE | 100000000 | Request 的最大字节数 |
-| REQUEST_TIMEOUT | 60 | 请求超时时间 |
-| RESPONSE_TIMEOUT | 60 | 响应超时时间 |
-| WEBSOCKET_MAX_SIZE | 2^20 | websocket 传入消息最大字节数 |
-| WEBSOCKET_PING_INTERVAL | 20 | websocket ping 帧 发送间隔 |
-| WEBSOCKET_PING_TIMEOUT | 20 | websocket pong 帧 响应超时时间 |
-
-::: tip
-
-如果您使用 Gunicorn 运行,那么 `USE_UVLOOP` 将会被忽略。在不支持的平台(Windows)上该值默认为 False。
-
-如果您处于 ASGI 模式, 那么 `WEBSOCKET_` 的值将会被忽略
-
-:::
+
+| **变量名称** | **默认值** | **说明** |
+| --------------------------- | --------------- | ----------------------------------------------------------------------------------- |
+| ACCESS_LOG | True | 访问日志开关 |
+| AUTO_EXTEND^ | True | Sanic 拓展启用开关 |
+| AUTO_RELOAD | True | 自动重载开关 |
+| EVENT_AUTOREGISTER | True | 自动注册信号开关(开启后不存在的事件将会自动注册) |
+| FALLBACK_ERROR_FORMAT | html | 异常返回格式 |
+| FORWARDED_FOR_HEADER | X-Forwarded-For | 客户端 IP 和代理 IP:X-Forwarded-For |
+| FORWARDED_SECRET | None | 用于安全地识别特定的代理服务器(见下文) |
+| GRACEFUL_SHUTDOWN_TIMEOUT | 15.0 | 强制关闭非空闲连接的等待时间(秒) |
+| KEEP_ALIVE | True | 是否启用长连接 |
+| KEEP_ALIVE_TIMEOUT | 5 | 长连接超时时间 |
+| MOTD^ | True | 是否在启动时展示 MOTD 信息 |
+| MOTD_DISPLAY | {} | 键/值对显示 MOTD 中的附加任意数据 |
+| NOISY_EXCEPTIONS ^ | False | 强制禁止异常输出 |
+| PROXIES_COUNT | None | 应用程序钱代理服务器的数量(见下文) |
+| REAL_IP_HEADER | None | 客户端真实 IP: X-Real-IP |
+| REGISTER | True | 是否启用应用程序注册表 |
+| REQUEST_BUFFER_QUEUE_SIZE | 100 | 请求流缓冲区队列大小 |
+| REQUEST_ID_HEADER | X-Request-ID | 请求头中的请求 ID 名称:X-Request-ID |
+| REQUEST_MAX_SIZE | 100000000 | Request 的最大字节数 |
+| REQUEST_TIMEOUT | 60 | 请求超时时间 |
+| RESPONSE_TIMEOUT | 60 | 响应超时时间 |
+| USE_UVLOOP | True | Whether to override the loop policy to use `uvloop`. Supported only with `app.run`. |
+| WEBSOCKET_MAX_SIZE | 2^20 | websocket ping 帧 发送间隔 |
+| WEBSOCKET_PING_INTERVAL | 20 | websocket pong 帧 响应超时时间 |
+| WEBSOCKET_PING_TIMEOUT | 20 | Connection is closed when Pong is not received after ping_timeout seconds |
+
+`app.update_config` 的方法同样适用于字典
+- 如果您使用 Gunicorn 运行,那么 `USE_UVLOOP` 将会被忽略。 在不支持的平台(Windows)上该值默认为 False。
+- 如果您处于 ASGI 模式, 那么 `WEBSOCKET_` 的值将会被忽略 :::
## 超时(Timeouts)
-### 请求超时(REQUEST_TIMEOUT)
+### REQUEST_TIMEOUT
-请求时间用于衡量从建立 TCP 连接到整个 HTTP 请求接收完成所花费的时间。如果请求时间超过了设定的 `REQUEST_TIMEOUT` ,Sanic 会将其视为客户端错误并将 HTTP 408 作为响应发送给客户端。如果您的客户端需要频繁传递大量的数据, 请您将此参数调至更高或减少传输数据。
+请求时间用于衡量从建立 TCP 连接到整个 HTTP 请求接收完成所花费的时间。 如果请求时间超过了设定的 `REQUEST_TIMEOUT` ,Sanic 会将其视为客户端错误并将 HTTP 408 作为响应发送给客户端。 如果您的客户端需要频繁传递大量的数据, 请您将此参数调至更高或减少传输数据。
-### 响应超时(RESPONSE_TIMEOUT)
+### RESPONSE_TIMEOUT
-响应时间用于衡量从整个 HTTP 请求接收完成到 Sanic 将响应完整发送至客户端所花费的时间。如果响应时间超过了设定的 `RESONSE_TIMEOUT` ,Sanic 会将其视为服务端错误并将 HTTP 503 作为响应发送给客户端。如果您的应用程序需要消耗大量的时间来进行响应,请尝试将此参数调至更高或优化响应效率。
+响应时间用于衡量从整个 HTTP 请求接收完成到 Sanic 将响应完整发送至客户端所花费的时间。 如果响应时间超过了设定的 `RESONSE_TIMEOUT` ,Sanic 会将其视为服务端错误并将 HTTP 503 作为响应发送给客户端。 如果您的应用程序需要消耗大量的时间来进行响应,请尝试将此参数调至更高或优化响应效率。
-### 长连接超时(KEEP_ALIVE_TIMEOUT)
+### KEEP_ALIVE_TIMEOUT
-#### 什么是长连接?长连接超时有什么作用?
+#### What is Keep Alive? And what does the Keep Alive Timeout value do?
-`Keep-Alive` 中文叫做长连接,它是 HTTP1.1 中引入的 HTTP 功能。当发送 HTTP 请求时,客户端(通常是浏览器)可以通过设置 `Keep-Alive` 标头来指示 http 服务器(Sanic)在发送响应之后不关闭 TCP 连接。这将允许客户端重用现有的 TCP 连接来发送后续的 HTTP 请求,以提高客户端和服务端之间的通讯效率。
+`Keep-Alive` 中文叫做长连接,它是 HTTP1.1 中引入的 HTTP 功能。 当发送 HTTP 请求时,客户端(通常是浏览器)可以通过设置 `Keep-Alive` 标头来指示 http 服务器(Sanic)在发送响应之后不关闭 TCP 连接。 这将允许客户端重用现有的 TCP 连接来发送后续的 HTTP 请求,以提高客户端和服务端之间的通讯效率。
-在默认情况下,Sanic 中的 `Keep-Alive` 的值为 `True` 。如果您的应用程序不需要此功能,可以将其设置为 False。不过此举将导致 Sanic 无视 `Keep_Alive` 标头,且所有的客户端连接在响应发送完成之后被立即关闭。
+在默认情况下,Sanic 中的 `Keep-Alive` 的值为 `True` 。 如果您的应用程序不需要此功能,可以将其设置为 False。 不过此举将导致 Sanic 无视 `Keep_Alive` 标头,且所有的客户端连接在响应发送完成之后被立即关闭。
-TCP 连接打开的时长本质上由服务器自身决定,在 Sanic 中,使用 `KEEP_ALIVE_TIMEOUT` 作为该值。默认情况下它设置为 5 秒。这与 Apache 的默认值相同。该值足够客户端发送一个新的请求。如非必要请勿更改此项。如需更改,请勿超过 75 秒,除非您确认客户端支持 TCP 连接保持足够久。
+The amount of time the server holds the TCP connection open is decided by the server itself. TCP 连接打开的时长本质上由服务器自身决定,在 Sanic 中,使用 `KEEP_ALIVE_TIMEOUT` 作为该值。 默认情况下它设置为 5 秒。 This is the same default setting as the Apache HTTP server and is a good balance between allowing enough time for the client to send a new request, and not holding open too many connections at once. 如需更改,请勿超过 75 秒,除非您确认客户端支持 TCP 连接保持足够久。
小提示:
-- Apache httpd 服务器默认 KEEP_ALIVE_TIMEOUT = 5 秒
-- Nginx 服务器默认 KEEP_ALIVE_TIMEOUT = 75 秒
-- Nginx 性能调整准则使用 KEEP_ALIVE_TIMEOUT = 15 秒
-- IE(5-9)客户端 KEEP_ALIVE_LIMIT = 60 秒
-- Firefox 客户端 KEEP_ALIVE_LIMIT = 115 秒
-- Opera 11 客户端 KEEP_ALIVE_LIMIT = 120 秒
-- Chrome 13+ 客户端 KEEP_ALIVE_LIMIT > 300+秒
+* Apache httpd 服务器默认 KEEP_ALIVE_TIMEOUT = 5 秒
+* Nginx 服务器默认 KEEP_ALIVE_TIMEOUT = 75 秒
+* Nginx 性能调整准则使用 KEEP_ALIVE_TIMEOUT = 15 秒
+* IE(5-9)客户端 KEEP_ALIVE_LIMIT = 60 秒
+* Firefox 客户端 KEEP_ALIVE_LIMIT = 115 秒
+* Opera 11 客户端 KEEP_ALIVE_LIMIT = 120 秒
+* Chrome 13+ 客户端 KEEP_ALIVE_LIMIT > 300+秒
## 代理配置(Proxy configuration)
From 1db6b4aa4aa6e109f859605386c0fe5c7a856992 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:01 +0300
Subject: [PATCH 110/776] New translations configuration.md (Portuguese,
Brazilian)
---
src/pt/guide/deployment/configuration.md | 224 +++++++++++++++++++++++
1 file changed, 224 insertions(+)
create mode 100644 src/pt/guide/deployment/configuration.md
diff --git a/src/pt/guide/deployment/configuration.md b/src/pt/guide/deployment/configuration.md
new file mode 100644
index 0000000000..fa25b1c6be
--- /dev/null
+++ b/src/pt/guide/deployment/configuration.md
@@ -0,0 +1,224 @@
+# Configuration
+
+## Basics
+
+
+---:1
+
+Sanic holds the configuration in the config attribute of the application object. The configuration object is merely an object that can be modified either using dot-notation or like a dictionary. :--:1
+```python
+app = Sanic("myapp")
+app.config.DB_NAME = "appdb"
+app.config["DB_USER"] = "appuser"
+```
+:---
+
+---:1
+
+You can also use the `update()` method like on regular dictionaries. :--:1
+```python
+db_settings = {
+ 'DB_HOST': 'localhost',
+ 'DB_NAME': 'appdb',
+ 'DB_USER': 'appuser'
+}
+app.config.update(db_settings)
+```
+:---
+
+::: tip It is standard practice in Sanic to name your config values in **uppercase letters**. Indeed, you may experience weird behaviors if you start mixing uppercase and lowercase names. :::
+
+## Loading
+
+### Environment variables
+
+---:1
+
+Any environment variables defined with the `SANIC_` prefix will be applied to the Sanic config. For example, setting `SANIC_REQUEST_TIMEOUT` will be loaded by the application automatically and fed into the `REQUEST_TIMEOUT` config variable. :--:1
+```bash
+$ export SANIC_REQUEST_TIMEOUT=10
+```
+```python
+>>> print(app.config.REQUEST_TIMEOUT)
+10
+```
+:---
+
+---:1
+
+You can change the prefix that Sanic is expecting at startup. :--:1
+```bash
+$ export MYAPP_REQUEST_TIMEOUT=10
+```
+```python
+>>> app = Sanic(__name__, env_prefix='MYAPP_')
+>>> print(app.config.REQUEST_TIMEOUT)
+10
+```
+:---
+
+---:1
+
+You can also disable environment variable loading completely. :--:1
+```python
+app = Sanic(__name__, load_env=False)
+```
+:---
+
+### Using Sanic.update_config
+
+The `Sanic` instance has a _very_ versatile method for loading config: `app.update_config`. You can feed it a path to a file, a dictionary, a class, or just about any other sort of object.
+
+#### From a file
+
+---:1
+
+Let's say you have `my_config.py` file that looks like this. :--:1
+```python
+# my_config.py
+A = 1
+B = 2
+```
+:---
+
+---:1
+
+You can load this as config values by passing its path to `app.update_config`. :--:1
+```python
+>>> app.update_config("/path/to/my_config.py")
+>>> print(app.config.A)
+1
+```
+:---
+
+---:1
+
+This path also accepts bash style environment variables. :--:1
+```bash
+$ export my_path="/path/to"
+```
+```python
+app.update_config("${my_path}/my_config.py")
+```
+:---
+
+::: tip Just remember that you have to provide environment variables in the format `${environment_variable}` and that `$environment_variable` is not expanded (is treated as "plain" text). :::
+#### From a dict
+
+---:1
+
+The `app.update_config` method also works on plain dictionaries. :--:1
+```python
+app.update_config({"A": 1, "B": 2})
+```
+:---
+
+#### From a class or object
+
+---:1
+
+You can define your own config class, and pass it to `app.update_config` :--:1
+```python
+class MyConfig:
+ A = 1
+ B = 2
+
+app.update_config(MyConfig)
+```
+:---
+
+---:1
+
+It even could be instantiated. :--:1
+```python
+app.update_config(MyConfig())
+```
+:---
+
+### Type casting
+
+When loading from environment variables, Sanic will attempt to cast the values to expected Python types. This particularly applies to:
+
+- `int`
+- `float`
+- `bool`
+
+In regards to `bool`, the following _case insensitive_ values are allowed:
+
+- **`True`**: `y`, `yes`, `yep`, `yup`, `t`, `true`, `on`, `enable`, `enabled`, `1`
+- **`False`**: `n`, `no`, `f`, `false`, `off`, `disable`, `disabled`, `0`
+
+---:1 Additionally, Sanic can be configured to cast additional types using additional type converters. This should be any callable that returns the value or raises a `ValueError`. :--:1
+```python
+app = Sanic(..., config=Config(converters=[UUID]))
+```
+:---
+
+## Builtin values
+
+
+| **Variable** | **Default** | **Description** |
+| --------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
+| ACCESS_LOG | True | Disable or enable access log |
+| AUTO_EXTEND ^ | True | Control whether [Sanic Extensions](../../plugins/sanic-ext/getting-started.md) will load if it is in the existing virtual environment |
+| AUTO_RELOAD | True | Control whether the application will automatically reload when a file changes |
+| EVENT_AUTOREGISTER | True | When `True` using the `app.event()` method on a non-existing signal will automatically create it and not raise an exception |
+| FALLBACK_ERROR_FORMAT | html | Format of error response if an exception is not caught and handled |
+| FORWARDED_FOR_HEADER | X-Forwarded-For | The name of "X-Forwarded-For" HTTP header that contains client and proxy ip |
+| FORWARDED_SECRET | None | Used to securely identify a specific proxy server (see below) |
+| GRACEFUL_SHUTDOWN_TIMEOUT | 15.0 | How long to wait to force close non-idle connection (sec) |
+| KEEP_ALIVE | True | Disables keep-alive when False |
+| KEEP_ALIVE_TIMEOUT | 5 | How long to hold a TCP connection open (sec) |
+| MOTD ^ | True | Whether to display the MOTD (message of the day) at startup |
+| MOTD_DISPLAY ^ | {} | Key/value pairs to display additional, arbitrary data in the MOTD |
+| NOISY_EXCEPTIONS ^ | False | Force all `quiet` exceptions to be logged |
+| PROXIES_COUNT | None | The number of proxy servers in front of the app (e.g. nginx; see below) |
+| REAL_IP_HEADER | None | The name of "X-Real-IP" HTTP header that contains real client ip |
+| REGISTER | True | Whether the app registry should be enabled |
+| REQUEST_BUFFER_SIZE | 65536 | Request buffer size before request is paused, default is 64 Kib |
+| REQUEST_ID_HEADER | X-Request-ID | The name of "X-Request-ID" HTTP header that contains request/correlation ID |
+| REQUEST_MAX_SIZE | 100000000 | How big a request may be (bytes), default is 100 megabytes |
+| REQUEST_TIMEOUT | 60 | How long a request can take to arrive (sec) |
+| RESPONSE_TIMEOUT | 60 | How long a response can take to process (sec) |
+| USE_UVLOOP | True | Whether to override the loop policy to use `uvloop`. Supported only with `app.run`. |
+| WEBSOCKET_MAX_SIZE | 2^20 | Maximum size for incoming messages (bytes) |
+| WEBSOCKET_PING_INTERVAL | 20 | A Ping frame is sent every ping_interval seconds. |
+| WEBSOCKET_PING_TIMEOUT | 20 | Connection is closed when Pong is not received after ping_timeout seconds |
+
+::: tip FYI
+- The `USE_UVLOOP` value will be ignored if running with Gunicorn. Defaults to `False` on non-supported platforms (Windows).
+- The `WEBSOCKET_` values will be ignored if in ASGI mode. :::
+
+## Timeouts
+
+### REQUEST_TIMEOUT
+
+A request timeout measures the duration of time between the instant when a new open TCP connection is passed to the Sanic backend server, and the instant when the whole HTTP request is received. If the time taken exceeds the `REQUEST_TIMEOUT` value (in seconds), this is considered a Client Error so Sanic generates an `HTTP 408` response and sends that to the client. Set this parameter's value higher if your clients routinely pass very large request payloads or upload requests very slowly.
+
+### RESPONSE_TIMEOUT
+
+A response timeout measures the duration of time between the instant the Sanic server passes the HTTP request to the Sanic App, and the instant a HTTP response is sent to the client. If the time taken exceeds the `RESPONSE_TIMEOUT` value (in seconds), this is considered a Server Error so Sanic generates an `HTTP 503` response and sends that to the client. Set this parameter's value higher if your application is likely to have long-running process that delay the generation of a response.
+
+### KEEP_ALIVE_TIMEOUT
+
+#### What is Keep Alive? And what does the Keep Alive Timeout value do?
+
+`Keep-Alive` is a HTTP feature introduced in `HTTP 1.1`. When sending a HTTP request, the client (usually a web browser application) can set a `Keep-Alive` header to indicate the http server (Sanic) to not close the TCP connection after it has send the response. This allows the client to reuse the existing TCP connection to send subsequent HTTP requests, and ensures more efficient network traffic for both the client and the server.
+
+The `KEEP_ALIVE` config variable is set to `True` in Sanic by default. If you don't need this feature in your application, set it to `False` to cause all client connections to close immediately after a response is sent, regardless of the `Keep-Alive` header on the request.
+
+The amount of time the server holds the TCP connection open is decided by the server itself. In Sanic, that value is configured using the `KEEP_ALIVE_TIMEOUT` value. By default, it is set to 5 seconds. This is the same default setting as the Apache HTTP server and is a good balance between allowing enough time for the client to send a new request, and not holding open too many connections at once. Do not exceed 75 seconds unless you know your clients are using a browser which supports TCP connections held open for that long.
+
+For reference:
+
+* Apache httpd server default keepalive timeout = 5 seconds
+* Nginx server default keepalive timeout = 75 seconds
+* Nginx performance tuning guidelines uses keepalive = 15 seconds
+* IE (5-9) client hard keepalive limit = 60 seconds
+* Firefox client hard keepalive limit = 115 seconds
+* Opera 11 client hard keepalive limit = 120 seconds
+* Chrome 13+ client keepalive limit > 300+ seconds
+
+## Proxy configuration
+
+See [proxy configuration section](/guide/advanced/proxy-headers.md)
From 8cc9a5f7b285bceec0f4f07faa6807407cf23e7b Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:02 +0300
Subject: [PATCH 111/776] New translations development.md (Japanese)
---
src/ja/guide/deployment/development.md | 68 ++++++++++++++++++++++++--
1 file changed, 65 insertions(+), 3 deletions(-)
diff --git a/src/ja/guide/deployment/development.md b/src/ja/guide/deployment/development.md
index df8759e7a2..bec5572a6a 100644
--- a/src/ja/guide/deployment/development.md
+++ b/src/ja/guide/deployment/development.md
@@ -24,14 +24,76 @@ if __name__ == "__main__":
::: warning
Sanicのデバッグモードは、サーバのパフォーマンスを低下させるため、開発環境でのみ有効にすることをお勧めします。
-:::
+::: :::
## 自動的に読み込む
---:1
-Sanicでは、Automatic Reloaderを手動で (デバッグモードから独立して) 有効または無効にする方法を提供しています。`auto_reload`引数は、自動リローダーをアクティブまたは非アクティブにします。
-:--:1
+Sanicでは、Automatic Reloaderを手動で (デバッグモードから独立して) 有効または無効にする方法を提供しています。 `auto_reload`引数は、自動リローダーをアクティブまたは非アクティブにします。 :--:1 Every time a Python file is changed, the reloader will restart your application automatically. This is very convenient while developing. :--:1
```python
app.run(auto_reload=True)
```
:---
+
+---:1 If you have additional directories that you would like to automatically reload on file save (for example, a directory of HTML templates), you can add that at run time. :--:1
+```python
+app.run(auto_reload=True, reload_dir="/path/to/templates")
+# or multiple directories
+app.run(auto_reload=True, reload_dir=["/path/to/one", "/path/to/two"])
+```
+:---
+
+## Best of both worlds
+---:1 If you would like to be in debug mode **and** have the Automatic Reloader running, you can pass `dev=True`. This is equivalent to **debug + auto reload**.
+
+*Added in v22.3* :--:1
+```python
+app.run(dev=True)
+```
+:---
+
+
+::: new NEW in v22.6
+## Automatic TLS certificate
+
+When running in `DEBUG` mode, you can ask Sanic to handle setting up localhost temporary TLS certificates. This is helpful if you want to access your local development environment with `https://`.
+
+This functionality is provided by either [mkcert](https://github.com/FiloSottile/mkcert) or [trustme](https://github.com/python-trio/trustme). Both are good choices, but there are some differences. `trustme` is a Python library and can be installed into your environment with `pip`. This makes for easy envrionment handling, but it is not compatible when running a HTTP/3 server. `mkcert` might be a more involved installation process, but can install a local CA and make it easier to use.
+
+---:1 You can choose which platform to use by setting `config.LOCAL_CERT_CREATOR`. When set to `"auto"`, it will select either option, preferring `mkcert` if possible. :--:1
+```python
+app.config.LOCAL_CERT_CREATOR = "auto"
+app.config.LOCAL_CERT_CREATOR = "mkcert"
+app.config.LOCAL_CERT_CREATOR = "trustme"
+```
+:---
+
+
+---:1 Automatic TLS can be enabled at Sanic server run time: :--:1
+```
+$ sanic path.to.server:app --auto-tls --debug
+```
+
+```python
+app.run(debug=True, auto_tls=True)
+```
+:---
+
+::: warning
+
+Localhost TLS certificates (like those generated by both `mkcert` and `trustme`) are **NOT** suitable for production environments. If you are not familiar with how to obtain a *real* TLS certificate, checkout the [How to...](../how-to/tls.md) section.
+
+:::
+
+## CLI
+
+It should be noted that all of these have an equivalent in the Sanic CLI:
+
+```
+Development:
+ --debug Run the server in debug mode
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+ -d, --dev debug + auto reload
+ --auto-tls Create a temporary TLS certificate for local development (requires mkcert or trustme)
+```
From 5f1a6cfe0786e7721f8f1f492d5def6105031e5c Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:04 +0300
Subject: [PATCH 112/776] New translations development.md (Korean)
---
src/ko/guide/deployment/development.md | 99 ++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
create mode 100644 src/ko/guide/deployment/development.md
diff --git a/src/ko/guide/deployment/development.md b/src/ko/guide/deployment/development.md
new file mode 100644
index 0000000000..4c47f89427
--- /dev/null
+++ b/src/ko/guide/deployment/development.md
@@ -0,0 +1,99 @@
+# Development
+
+The first thing that should be mentioned is that the webserver that is integrated into Sanic is **not** just a development server.
+
+It is production ready, provided you are *not* in debug mode.
+
+## Debug mode
+
+By setting the debug mode, Sanic will be more verbose in its output and will disable several run-time optimizations.
+
+```python
+from sanic import Sanic
+from sanic.response import json
+
+app = Sanic(__name__)
+
+@app.route("/")
+async def hello_world(request):
+ return json({"hello": "world"})
+
+if __name__ == "__main__":
+ app.run(host="0.0.0.0", port=1234, debug=True)
+```
+
+::: warning
+Sanic's debug mode will slow down the server's performance and is therefore advised to enable it only in development environments.
+:::
+## Automatic Reloader
+
+---:1
+
+Sanic offers a way to enable or disable the Automatic Reloader. The `auto_reload` argument will activate or deactivate the Automatic Reloader. Every time a Python file is changed, the reloader will restart your application automatically. This is very convenient while developing. :--:1
+```python
+app.run(auto_reload=True)
+```
+:---
+
+---:1 If you have additional directories that you would like to automatically reload on file save (for example, a directory of HTML templates), you can add that at run time. :--:1
+```python
+app.run(auto_reload=True, reload_dir="/path/to/templates")
+# or multiple directories
+app.run(auto_reload=True, reload_dir=["/path/to/one", "/path/to/two"])
+```
+:---
+
+## Best of both worlds
+---:1 If you would like to be in debug mode **and** have the Automatic Reloader running, you can pass `dev=True`. This is equivalent to **debug + auto reload**.
+
+*Added in v22.3* :--:1
+```python
+app.run(dev=True)
+```
+:---
+
+
+::: new NEW in v22.6
+## Automatic TLS certificate
+
+When running in `DEBUG` mode, you can ask Sanic to handle setting up localhost temporary TLS certificates. This is helpful if you want to access your local development environment with `https://`.
+
+This functionality is provided by either [mkcert](https://github.com/FiloSottile/mkcert) or [trustme](https://github.com/python-trio/trustme). Both are good choices, but there are some differences. `trustme` is a Python library and can be installed into your environment with `pip`. This makes for easy envrionment handling, but it is not compatible when running a HTTP/3 server. `mkcert` might be a more involved installation process, but can install a local CA and make it easier to use.
+
+---:1 You can choose which platform to use by setting `config.LOCAL_CERT_CREATOR`. When set to `"auto"`, it will select either option, preferring `mkcert` if possible. :--:1
+```python
+app.config.LOCAL_CERT_CREATOR = "auto"
+app.config.LOCAL_CERT_CREATOR = "mkcert"
+app.config.LOCAL_CERT_CREATOR = "trustme"
+```
+:---
+
+
+---:1 Automatic TLS can be enabled at Sanic server run time: :--:1
+```
+$ sanic path.to.server:app --auto-tls --debug
+```
+
+```python
+app.run(debug=True, auto_tls=True)
+```
+:---
+
+::: warning
+
+Localhost TLS certificates (like those generated by both `mkcert` and `trustme`) are **NOT** suitable for production environments. If you are not familiar with how to obtain a *real* TLS certificate, checkout the [How to...](../how-to/tls.md) section.
+
+:::
+
+## CLI
+
+It should be noted that all of these have an equivalent in the Sanic CLI:
+
+```
+Development:
+ --debug Run the server in debug mode
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+ -d, --dev debug + auto reload
+ --auto-tls Create a temporary TLS certificate for local development (requires mkcert or trustme)
+```
From cecd61f6e149b676e0c77069ab28f4855899737b Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:05 +0300
Subject: [PATCH 113/776] New translations development.md (Chinese Simplified)
---
src/zh/guide/deployment/development.md | 64 +++++++++++++++-----------
1 file changed, 36 insertions(+), 28 deletions(-)
diff --git a/src/zh/guide/deployment/development.md b/src/zh/guide/deployment/development.md
index 42d7cf6cfc..f2b77d71cf 100644
--- a/src/zh/guide/deployment/development.md
+++ b/src/zh/guide/deployment/development.md
@@ -22,67 +22,75 @@ if __name__ == "__main__":
app.run(host="0.0.0.0", port=1234, debug=True)
```
-::: warning 警告
-
-Sanic 的调试模式会降低服务器的性能,因此建议只在开发环境中启用它。
-
-:::
-
+Sanic 的调试模式会降低服务器的性能,因此建议只在开发环境中启用它。 :::
## 自动重载(Automatic Reloader)
---:1
-在调试模式之外,Sanic 还提供了一种手动开关自动重载的方法。`auto_reload` 参数将开启或关闭自动重载功能。
-
-:--:1
-
+在调试模式之外,Sanic 还提供了一种手动开关自动重载的方法。 `auto_reload` 参数将开启或关闭自动重载功能。 Every time a Python file is changed, the reloader will restart your application automatically. This is very convenient while developing. :--:1
```python
app.run(auto_reload=True)
```
-
:---
----:1
-
-如果您有额外的目录想要在文件保存时自动重新加载(例如,HTML 模板的目录),您可以在运行时添加它。
-
-:--:1
-
+如果您有额外的目录想要在文件保存时自动重新加载(例如,HTML 模板的目录),您可以在运行时添加它。 :--:1
```python
app.run(auto_reload=True, reload_dir="/path/to/templates")
# or multiple directories
app.run(auto_reload=True, reload_dir=["/path/to/one", "/path/to/two"])
```
-
:---
## 两全其美(Best of both worlds)
+如果您想在调试模式中使用自动重载功能,您可以设置 `dev=True`,这相当于您开启了 **调试模式 + 自动重载** This is equivalent to **debug + auto reload**.
-::: new v22.3 新特征
-
----:1
+*Added in v22.3* :--:1
+```python
+app.run(dev=True)
+```
+:---
-如果您想在调试模式中使用自动重载功能,您可以设置 `dev=True`,这相当于您开启了 **调试模式 + 自动重载**
:--:1
+## 客户端(CLI)
+
+When running in `DEBUG` mode, you can ask Sanic to handle setting up localhost temporary TLS certificates. This is helpful if you want to access your local development environment with `https://`.
+
+This functionality is provided by either [mkcert](https://github.com/FiloSottile/mkcert) or [trustme](https://github.com/python-trio/trustme). Both are good choices, but there are some differences. `trustme` is a Python library and can be installed into your environment with `pip`. This makes for easy envrionment handling, but it is not compatible when running a HTTP/3 server. `mkcert` might be a more involved installation process, but can install a local CA and make it easier to use.
+---:1 You can choose which platform to use by setting `config.LOCAL_CERT_CREATOR`. When set to `"auto"`, it will select either option, preferring `mkcert` if possible. :--:1
```python
-app.run(dev=True)
+app.config.LOCAL_CERT_CREATOR = "auto"
+app.config.LOCAL_CERT_CREATOR = "mkcert"
+app.config.LOCAL_CERT_CREATOR = "trustme"
+```
+:---
+
+
+:--:1
+```
+$ sanic path.to.server:app --auto-tls --debug
```
+```python
+app.run(debug=True, auto_tls=True)
+```
:---
+::: warning 警告
+
+Localhost TLS certificates (like those generated by both `mkcert` and `trustme`) are **NOT** suitable for production environments. If you are not familiar with how to obtain a *real* TLS certificate, checkout the [How to...](../how-to/tls.md) section.
+
:::
-## 客户端(CLI)
+## CLI
值得注意的是,所有这些在 Sanic CLI 中都有对应的内容:
```
- Development:
- --debug 在调试模式下运行服务器。它包括调试日志、关于异常的附加上下文,
- 以及对生产不安全但有助于调试问题的其他设置。
- -r, --reload, --auto-reload 监听文件的修改,并在修改时重新加载
+Development:
+ --debug 在调试模式下运行服务器。 它包括调试日志、关于异常的附加上下文,
+ 以及对生产不安全但有助于调试问题的其他设置。 -r, --reload, --auto-reload 监听文件的修改,并在修改时重新加载
-R PATH, --reload-dir PATH 更改时需要监听和重新加载的额外目录
-d, --dev 调试模式 + 自动重载
```
From 58527bbad5de5cf32985951343ea885b9289df2c Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:06 +0300
Subject: [PATCH 114/776] New translations development.md (Portuguese,
Brazilian)
---
src/pt/guide/deployment/development.md | 99 ++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
create mode 100644 src/pt/guide/deployment/development.md
diff --git a/src/pt/guide/deployment/development.md b/src/pt/guide/deployment/development.md
new file mode 100644
index 0000000000..4c47f89427
--- /dev/null
+++ b/src/pt/guide/deployment/development.md
@@ -0,0 +1,99 @@
+# Development
+
+The first thing that should be mentioned is that the webserver that is integrated into Sanic is **not** just a development server.
+
+It is production ready, provided you are *not* in debug mode.
+
+## Debug mode
+
+By setting the debug mode, Sanic will be more verbose in its output and will disable several run-time optimizations.
+
+```python
+from sanic import Sanic
+from sanic.response import json
+
+app = Sanic(__name__)
+
+@app.route("/")
+async def hello_world(request):
+ return json({"hello": "world"})
+
+if __name__ == "__main__":
+ app.run(host="0.0.0.0", port=1234, debug=True)
+```
+
+::: warning
+Sanic's debug mode will slow down the server's performance and is therefore advised to enable it only in development environments.
+:::
+## Automatic Reloader
+
+---:1
+
+Sanic offers a way to enable or disable the Automatic Reloader. The `auto_reload` argument will activate or deactivate the Automatic Reloader. Every time a Python file is changed, the reloader will restart your application automatically. This is very convenient while developing. :--:1
+```python
+app.run(auto_reload=True)
+```
+:---
+
+---:1 If you have additional directories that you would like to automatically reload on file save (for example, a directory of HTML templates), you can add that at run time. :--:1
+```python
+app.run(auto_reload=True, reload_dir="/path/to/templates")
+# or multiple directories
+app.run(auto_reload=True, reload_dir=["/path/to/one", "/path/to/two"])
+```
+:---
+
+## Best of both worlds
+---:1 If you would like to be in debug mode **and** have the Automatic Reloader running, you can pass `dev=True`. This is equivalent to **debug + auto reload**.
+
+*Added in v22.3* :--:1
+```python
+app.run(dev=True)
+```
+:---
+
+
+::: new NEW in v22.6
+## Automatic TLS certificate
+
+When running in `DEBUG` mode, you can ask Sanic to handle setting up localhost temporary TLS certificates. This is helpful if you want to access your local development environment with `https://`.
+
+This functionality is provided by either [mkcert](https://github.com/FiloSottile/mkcert) or [trustme](https://github.com/python-trio/trustme). Both are good choices, but there are some differences. `trustme` is a Python library and can be installed into your environment with `pip`. This makes for easy envrionment handling, but it is not compatible when running a HTTP/3 server. `mkcert` might be a more involved installation process, but can install a local CA and make it easier to use.
+
+---:1 You can choose which platform to use by setting `config.LOCAL_CERT_CREATOR`. When set to `"auto"`, it will select either option, preferring `mkcert` if possible. :--:1
+```python
+app.config.LOCAL_CERT_CREATOR = "auto"
+app.config.LOCAL_CERT_CREATOR = "mkcert"
+app.config.LOCAL_CERT_CREATOR = "trustme"
+```
+:---
+
+
+---:1 Automatic TLS can be enabled at Sanic server run time: :--:1
+```
+$ sanic path.to.server:app --auto-tls --debug
+```
+
+```python
+app.run(debug=True, auto_tls=True)
+```
+:---
+
+::: warning
+
+Localhost TLS certificates (like those generated by both `mkcert` and `trustme`) are **NOT** suitable for production environments. If you are not familiar with how to obtain a *real* TLS certificate, checkout the [How to...](../how-to/tls.md) section.
+
+:::
+
+## CLI
+
+It should be noted that all of these have an equivalent in the Sanic CLI:
+
+```
+Development:
+ --debug Run the server in debug mode
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+ -d, --dev debug + auto reload
+ --auto-tls Create a temporary TLS certificate for local development (requires mkcert or trustme)
+```
From 32ac8776bcd84b33481d4935836b391d7e623188 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:07 +0300
Subject: [PATCH 115/776] New translations docker.md (Japanese)
---
src/ja/guide/deployment/docker.md | 182 ++++++++++++++++++++++++++++++
1 file changed, 182 insertions(+)
diff --git a/src/ja/guide/deployment/docker.md b/src/ja/guide/deployment/docker.md
index c597eaa5eb..4f757cd309 100644
--- a/src/ja/guide/deployment/docker.md
+++ b/src/ja/guide/deployment/docker.md
@@ -1 +1,183 @@
# Docker
+
+## Introduction
+
+For a long time, the environment has always been a difficult problem for deployment. If there are conflicting configurations in your project, you have to spend a lot of time resolving them. Fortunately, virtualization provides us with a good solution. Docker is one of them. If you don't know Docker, you can visit [Docker official website](https://www.docker.com/) to learn more.
+
+## Build Image
+
+Let's start with a simple project. We will use a Sanic project as an example. Assume the project path is `/path/to/SanicDocker`.
+
+---:1
+
+The directory structure looks like this:
+
+:--:1
+
+```text
+# /path/to/SanicDocker
+SanicDocker
+├── requirements.txt
+├── dockerfile
+└── server.py
+```
+
+:---
+
+---:1
+
+And the `server.py` code looks like this:
+
+:--:1
+
+```python
+app = Sanic("MySanicApp")
+
+@app.get('/')
+async def hello(request):
+ return text("OK!")
+
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=8000)
+```
+
+:---
+
+::: tip
+
+Please note that the host cannot be 127.0.0.1 . In docker container, 127.0.0.1 is the default network interface of the container, only the container can communicate with other containers. more information please visit [Docker network](https://docs.docker.com/engine/reference/commandline/network/)
+
+:::
+
+Code is ready, let's write the `Dockerfile`:
+
+```Dockerfile
+
+FROM sanicframework/sanic:3.8-latest
+
+WORKDIR /sanic
+
+COPY . .
+
+RUN pip install -r requirements.txt
+
+EXPOSE 8000
+
+CMD ["python", "server.py"]
+```
+
+Run the following command to build the image:
+
+```shell
+docker build -t my-sanic-image .
+```
+
+## Start Container
+
+---:1
+
+After the image built, we can start the container use `my-sanic-image`:
+
+:--:1
+
+```shell
+docker run --name mysanic -p 8000:8000 -d my-sanic-image
+```
+
+:---
+
+---:1
+
+Now we can visit `http://localhost:8000` to see the result:
+
+:--:1
+
+```text
+OK!
+```
+
+:---
+
+## Use docker-compose
+
+If your project consist of multiple services, you can use [docker-compose](https://docs.docker.com/compose/) to manage them.
+
+for example, we will deploy `my-sanic-image` and `nginx`, achieve through nginx access sanic server.
+
+---:1
+
+First of all, we need prepare nginx configuration file. create a file named `mysanic.conf`:
+
+:--:1
+
+```nginx
+server {
+ listen 80;
+ listen [::]:80;
+ location / {
+ proxy_pass http://mysanic:8000/;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection upgrade;
+ proxy_set_header Accept-Encoding gzip;
+ }
+}
+```
+
+:---
+
+---:1
+
+Then, we need to prepare `docker-compose.yml` file. The content follows:
+
+:--:1
+
+```yml
+version: "3"
+
+services:
+ mysanic:
+ image: my-sanic-image
+ ports:
+ - "8000:8000"
+ restart: always
+
+ mynginx:
+ image: nginx:1.13.6-alpine
+ ports:
+ - "80:80"
+ depends_on:
+ - mysanic
+ volumes:
+ - ./mysanic.conf:/etc/nginx/conf.d/mysanic.conf
+ restart: always
+
+networks:
+ default:
+ driver: bridge
+```
+
+:---
+
+---:1
+
+After that, we can start them:
+
+:--:1
+
+```shell
+docker-compose up -d
+```
+
+:---
+
+---:1
+
+Now, we can visit `http://localhost:80` to see the result:
+
+:--:1
+
+```text
+OK!
+```
+
+:---
From 6296b2f852c2afda9ab7ee470515000de0d50468 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:08 +0300
Subject: [PATCH 116/776] New translations docker.md (Korean)
---
src/ko/guide/deployment/docker.md | 183 ++++++++++++++++++++++++++++++
1 file changed, 183 insertions(+)
create mode 100644 src/ko/guide/deployment/docker.md
diff --git a/src/ko/guide/deployment/docker.md b/src/ko/guide/deployment/docker.md
new file mode 100644
index 0000000000..47f4966b27
--- /dev/null
+++ b/src/ko/guide/deployment/docker.md
@@ -0,0 +1,183 @@
+# Docker Deployment
+
+## Introduction
+
+For a long time, the environment has always been a difficult problem for deployment. If there are conflicting configurations in your project, you have to spend a lot of time resolving them. Fortunately, virtualization provides us with a good solution. Docker is one of them. If you don't know Docker, you can visit [Docker official website](https://www.docker.com/) to learn more.
+
+## Build Image
+
+Let's start with a simple project. We will use a Sanic project as an example. Assume the project path is `/path/to/SanicDocker`.
+
+---:1
+
+The directory structure looks like this:
+
+:--:1
+
+```text
+# /path/to/SanicDocker
+SanicDocker
+├── requirements.txt
+├── dockerfile
+└── server.py
+```
+
+:---
+
+---:1
+
+And the `server.py` code looks like this:
+
+:--:1
+
+```python
+app = Sanic("MySanicApp")
+
+@app.get('/')
+async def hello(request):
+ return text("OK!")
+
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=8000)
+```
+
+:---
+
+::: tip
+
+Please note that the host cannot be 127.0.0.1 . In docker container, 127.0.0.1 is the default network interface of the container, only the container can communicate with other containers. more information please visit [Docker network](https://docs.docker.com/engine/reference/commandline/network/)
+
+:::
+
+Code is ready, let's write the `Dockerfile`:
+
+```Dockerfile
+
+FROM sanicframework/sanic:3.8-latest
+
+WORKDIR /sanic
+
+COPY . .
+
+RUN pip install -r requirements.txt
+
+EXPOSE 8000
+
+CMD ["python", "server.py"]
+```
+
+Run the following command to build the image:
+
+```shell
+docker build -t my-sanic-image .
+```
+
+## Start Container
+
+---:1
+
+After the image built, we can start the container use `my-sanic-image`:
+
+:--:1
+
+```shell
+docker run --name mysanic -p 8000:8000 -d my-sanic-image
+```
+
+:---
+
+---:1
+
+Now we can visit `http://localhost:8000` to see the result:
+
+:--:1
+
+```text
+OK!
+```
+
+:---
+
+## Use docker-compose
+
+If your project consist of multiple services, you can use [docker-compose](https://docs.docker.com/compose/) to manage them.
+
+for example, we will deploy `my-sanic-image` and `nginx`, achieve through nginx access sanic server.
+
+---:1
+
+First of all, we need prepare nginx configuration file. create a file named `mysanic.conf`:
+
+:--:1
+
+```nginx
+server {
+ listen 80;
+ listen [::]:80;
+ location / {
+ proxy_pass http://mysanic:8000/;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection upgrade;
+ proxy_set_header Accept-Encoding gzip;
+ }
+}
+```
+
+:---
+
+---:1
+
+Then, we need to prepare `docker-compose.yml` file. The content follows:
+
+:--:1
+
+```yml
+version: "3"
+
+services:
+ mysanic:
+ image: my-sanic-image
+ ports:
+ - "8000:8000"
+ restart: always
+
+ mynginx:
+ image: nginx:1.13.6-alpine
+ ports:
+ - "80:80"
+ depends_on:
+ - mysanic
+ volumes:
+ - ./mysanic.conf:/etc/nginx/conf.d/mysanic.conf
+ restart: always
+
+networks:
+ default:
+ driver: bridge
+```
+
+:---
+
+---:1
+
+After that, we can start them:
+
+:--:1
+
+```shell
+docker-compose up -d
+```
+
+:---
+
+---:1
+
+Now, we can visit `http://localhost:80` to see the result:
+
+:--:1
+
+```text
+OK!
+```
+
+:---
From efc3ec0d3f3ea166ff50b4d37c9d5b85b7fd2a57 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:09 +0300
Subject: [PATCH 117/776] New translations docker.md (Chinese Simplified)
---
src/zh/guide/deployment/docker.md | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/src/zh/guide/deployment/docker.md b/src/zh/guide/deployment/docker.md
index 0b39dd6a51..f934013184 100644
--- a/src/zh/guide/deployment/docker.md
+++ b/src/zh/guide/deployment/docker.md
@@ -2,11 +2,11 @@
## 介绍(Introduction)
-长期以来,环境一直是部署的难题。如果您的项目中有冲突的配置,您将不得不花费大量时间来解决它们。幸运的是,虚拟化为我们提供了一个很好的解决思路。Docker 就是其中之一。如果您不了解 Docker,可以访问 [Docker 官网](https://www.docker.com/) 了解更多。
+长期以来,环境一直是部署的难题。 如果您的项目中有冲突的配置,您将不得不花费大量时间来解决它们。 幸运的是,虚拟化为我们提供了一个很好的解决思路。 Docker 就是其中之一。 如果您不了解 Docker,可以访问 [Docker 官网](https://www.docker.com/) 了解更多。
## 构建镜像(Build Image)
-我们以一个最简单的 Sanic 工程作为例子。假设项目`SanicDocker` 的路径是`/path/to/SanicDocker`。
+Let's start with a simple project. 我们以一个最简单的 Sanic 工程作为例子。 假设项目`SanicDocker` 的路径是`/path/to/SanicDocker`。
---:1
@@ -37,6 +37,9 @@ app = Sanic("MySanicApp")
async def hello(request):
return text("OK!")
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=8000)
+
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
```
@@ -45,7 +48,7 @@ if __name__ == '__main__':
::: tip 小提示
-请注意这里的 host 不能为 127.0.0.1 。在 docker 容器中,127.0.0.1 只表示本机本容器中的一个虚拟网卡,只接受本容器中的应用相互通讯。更多信息请参考 [Docker 网络](https://docs.docker.com/engine/reference/commandline/network/)
+请注意这里的 host 不能为 127.0.0.1 。 在 docker 容器中,127.0.0.1 只表示本机本容器中的一个虚拟网卡,只接受本容器中的应用相互通讯。 更多信息请参考 [Docker 网络](https://docs.docker.com/engine/reference/commandline/network/)
:::
@@ -59,6 +62,12 @@ WORKDIR /sanic
COPY . .
+FROM sanicframework/sanic:3.8-latest
+
+WORKDIR /sanic
+
+COPY . .
+
RUN pip install -r requirements.txt
EXPOSE 8000
@@ -100,11 +109,13 @@ OK!
## 使用 docker-compose 编排(Use docker-compose)
-当您的项目中涵盖了多个不同的组件或服务时,您可以使用 [docker-compose](https://docs.docker.com/compose/) 来编排容器。以刚才打包好的 `my-sanic-image` 和 `nginx` 为例,我们来实现通过 `nginx` 代理 `Sanic` 服务器。
+当您的项目中涵盖了多个不同的组件或服务时,您可以使用 [docker-compose](https://docs.docker.com/compose/) 来编排容器。
+
+首先我们需要准备 nginx 的配置文件,将其命名为 `mysanic.conf` 并写入内容:
---:1
-首先我们需要准备 nginx 的配置文件,将其命名为 `mysanic.conf` 并写入内容:
+First of all, we need prepare nginx configuration file. create a file named `mysanic.conf`:
:--:1
@@ -125,7 +136,7 @@ server {
---:1
-然后我们来准备 `docker-compose.yml` 文件,其内容为:
+然后我们来准备 `docker-compose.yml` 文件,其内容为: The content follows:
:--:1
From a5aa700ebe0f0bfb0eb803d91e0b7576bcd58dac Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:10 +0300
Subject: [PATCH 118/776] New translations docker.md (Portuguese, Brazilian)
---
src/pt/guide/deployment/docker.md | 183 ++++++++++++++++++++++++++++++
1 file changed, 183 insertions(+)
create mode 100644 src/pt/guide/deployment/docker.md
diff --git a/src/pt/guide/deployment/docker.md b/src/pt/guide/deployment/docker.md
new file mode 100644
index 0000000000..47f4966b27
--- /dev/null
+++ b/src/pt/guide/deployment/docker.md
@@ -0,0 +1,183 @@
+# Docker Deployment
+
+## Introduction
+
+For a long time, the environment has always been a difficult problem for deployment. If there are conflicting configurations in your project, you have to spend a lot of time resolving them. Fortunately, virtualization provides us with a good solution. Docker is one of them. If you don't know Docker, you can visit [Docker official website](https://www.docker.com/) to learn more.
+
+## Build Image
+
+Let's start with a simple project. We will use a Sanic project as an example. Assume the project path is `/path/to/SanicDocker`.
+
+---:1
+
+The directory structure looks like this:
+
+:--:1
+
+```text
+# /path/to/SanicDocker
+SanicDocker
+├── requirements.txt
+├── dockerfile
+└── server.py
+```
+
+:---
+
+---:1
+
+And the `server.py` code looks like this:
+
+:--:1
+
+```python
+app = Sanic("MySanicApp")
+
+@app.get('/')
+async def hello(request):
+ return text("OK!")
+
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=8000)
+```
+
+:---
+
+::: tip
+
+Please note that the host cannot be 127.0.0.1 . In docker container, 127.0.0.1 is the default network interface of the container, only the container can communicate with other containers. more information please visit [Docker network](https://docs.docker.com/engine/reference/commandline/network/)
+
+:::
+
+Code is ready, let's write the `Dockerfile`:
+
+```Dockerfile
+
+FROM sanicframework/sanic:3.8-latest
+
+WORKDIR /sanic
+
+COPY . .
+
+RUN pip install -r requirements.txt
+
+EXPOSE 8000
+
+CMD ["python", "server.py"]
+```
+
+Run the following command to build the image:
+
+```shell
+docker build -t my-sanic-image .
+```
+
+## Start Container
+
+---:1
+
+After the image built, we can start the container use `my-sanic-image`:
+
+:--:1
+
+```shell
+docker run --name mysanic -p 8000:8000 -d my-sanic-image
+```
+
+:---
+
+---:1
+
+Now we can visit `http://localhost:8000` to see the result:
+
+:--:1
+
+```text
+OK!
+```
+
+:---
+
+## Use docker-compose
+
+If your project consist of multiple services, you can use [docker-compose](https://docs.docker.com/compose/) to manage them.
+
+for example, we will deploy `my-sanic-image` and `nginx`, achieve through nginx access sanic server.
+
+---:1
+
+First of all, we need prepare nginx configuration file. create a file named `mysanic.conf`:
+
+:--:1
+
+```nginx
+server {
+ listen 80;
+ listen [::]:80;
+ location / {
+ proxy_pass http://mysanic:8000/;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection upgrade;
+ proxy_set_header Accept-Encoding gzip;
+ }
+}
+```
+
+:---
+
+---:1
+
+Then, we need to prepare `docker-compose.yml` file. The content follows:
+
+:--:1
+
+```yml
+version: "3"
+
+services:
+ mysanic:
+ image: my-sanic-image
+ ports:
+ - "8000:8000"
+ restart: always
+
+ mynginx:
+ image: nginx:1.13.6-alpine
+ ports:
+ - "80:80"
+ depends_on:
+ - mysanic
+ volumes:
+ - ./mysanic.conf:/etc/nginx/conf.d/mysanic.conf
+ restart: always
+
+networks:
+ default:
+ driver: bridge
+```
+
+:---
+
+---:1
+
+After that, we can start them:
+
+:--:1
+
+```shell
+docker-compose up -d
+```
+
+:---
+
+---:1
+
+Now, we can visit `http://localhost:80` to see the result:
+
+:--:1
+
+```text
+OK!
+```
+
+:---
From c27301752a04b57aa2b45132675deb6dce6f4647 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:11 +0300
Subject: [PATCH 119/776] New translations kubernetes.md (Korean)
---
src/ko/guide/deployment/kubernetes.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/deployment/kubernetes.md
diff --git a/src/ko/guide/deployment/kubernetes.md b/src/ko/guide/deployment/kubernetes.md
new file mode 100644
index 0000000000..8d6340de1c
--- /dev/null
+++ b/src/ko/guide/deployment/kubernetes.md
@@ -0,0 +1 @@
+# Kubernetes
From 53579dd0eda737a939f5d719a5f12a14778a2d40 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:13 +0300
Subject: [PATCH 120/776] New translations kubernetes.md (Portuguese,
Brazilian)
---
src/pt/guide/deployment/kubernetes.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/deployment/kubernetes.md
diff --git a/src/pt/guide/deployment/kubernetes.md b/src/pt/guide/deployment/kubernetes.md
new file mode 100644
index 0000000000..8d6340de1c
--- /dev/null
+++ b/src/pt/guide/deployment/kubernetes.md
@@ -0,0 +1 @@
+# Kubernetes
From 2b6037daf6bf2532e5ab452568e4335ddcd24bd7 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:14 +0300
Subject: [PATCH 121/776] New translations nginx.md (Japanese)
---
src/ja/guide/deployment/nginx.md | 30 +++++++++++-------------------
1 file changed, 11 insertions(+), 19 deletions(-)
diff --git a/src/ja/guide/deployment/nginx.md b/src/ja/guide/deployment/nginx.md
index 4bde3db20e..9c50484053 100644
--- a/src/ja/guide/deployment/nginx.md
+++ b/src/ja/guide/deployment/nginx.md
@@ -3,16 +3,14 @@
## イントロダクション
-Sanicはインターネット上で直接実行できますが、プロキシを使用すると便利な場合があります。
-Nginxのようなサーバーを目の前にします。これは、同じIP上で複数の仮想ホストを実行したり、単一のSanicアプリに加えてNodeJSやその他のサービスを提供したり、静的ファイルを効率的に提供したりする場合に特に便利です。
-SSLとHTTP/2も、このようなプロキシに簡単に実装できます。
+Sanicはインターネット上で直接実行できますが、プロキシを使用すると便利な場合があります。 Nginxのようなサーバーを目の前にします。 これは、同じIP上で複数の仮想ホストを実行したり、単一のSanicアプリに加えてNodeJSやその他のサービスを提供したり、静的ファイルを効率的に提供したりする場合に特に便利です。 SSLとHTTP/2も、このようなプロキシに簡単に実装できます。 SSL and HTTP/2 are also easily implemented on such proxy.
-私たちはSanicのアプリを`127.0.0.1:8000`でローカルのみにサービスを提供するように設定していますが、Nginxのインストールはドメイン`example.com`上のパブリックインターネットにサービスを提供する責任があります。静的ファイルは`/var/www/`。
+私たちはSanicのアプリを`127.0.0.1:8000`でローカルのみにサービスを提供するように設定していますが、Nginxのインストールはドメイン`example.com`上のパブリックインターネットにサービスを提供する責任があります。 静的ファイルは`/var/www/`。
## プロキシSanicアプリ
-信頼できるプロキシを識別するために使用される秘密キーを使用してアプリを設定し、実際のクライアントIPおよびその他の情報を識別できるようにする必要があります。これにより、IPアドレスやその他の詳細を偽装するために、インターネット上で偽のヘッダーを送信するすべてのユーザーを保護できます。任意のランダムな文字列を選択し、アプリとNginx configの両方で設定します。
+信頼できるプロキシを識別するために使用される秘密キーを使用してアプリを設定し、実際のクライアントIPおよびその他の情報を識別できるようにする必要があります。 これにより、IPアドレスやその他の詳細を偽装するために、インターネット上で偽のヘッダーを送信するすべてのユーザーを保護できます。 任意のランダムな文字列を選択し、アプリとNginx configの両方で設定します。
```python
from sanic import Sanic
@@ -33,8 +31,7 @@ if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000, workers=8, access_log=False)
```
-これはシステムサービスになるので、コードを次の場所に保存します。
-`/srv/sanicexample/sanicexample.py`
+これはシステムサービスになるので、コードを次の場所に保存します。 `/srv/sanicexample/sanicexample.py`
テストでは、ターミナルでアプリを実行します。
@@ -42,7 +39,7 @@ if __name__ == "__main__":
高速透過プロキシを可能にするためにはかなり多くの設定が必要ですが、これらの大部分は修正する必要がないので、私に我慢してください。
-HTTPキープアライブを有効にするには、アップストリームサーバを個別の`upstream`ブロックで設定する必要があります。これにより、パフォーマンスが大幅に向上します。そこで、`proxy_pass`ディレクティブでアップストリームアドレスを直接指定する代わりに、これを使用します。この例では、アップストリーム・セクションの名前`server_name`、つまりパブリック・ドメイン名であり、これも`Host`ヘッダーでSanicに渡されます。必要に応じて名前を変更できます。ロード・バランシングとフェイルオーバーのために、複数のサーバを用意することもできます。
+HTTPキープアライブを有効にするには、アップストリームサーバを個別の`upstream`ブロックで設定する必要があります。 これにより、パフォーマンスが大幅に向上します。 そこで、`proxy_pass`ディレクティブでアップストリームアドレスを直接指定する代わりに、これを使用します。 この例では、アップストリーム・セクションの名前`server_name`、つまりパブリック・ドメイン名であり、これも`Host`ヘッダーでSanicに渡されます。 必要に応じて名前を変更できます。 ロード・バランシングとフェイルオーバーのために、複数のサーバを用意することもできます。
`example.com`の2つの出現箇所を実際のドメイン名に変更し、`YOUR SECRET`の代わりにアプリ用に選択したシークレットを使用します。
@@ -77,9 +74,7 @@ server {
}
```
-Cookieの可視性の問題および検索エンジンでのアドレスの一貫性を回避するには、次の手順を実行します。
-すべての訪問者を1つの真のドメインにリダイレクトすることをお勧めします。
-HTTPS:
+Cookieの可視性の問題および検索エンジンでのアドレスの一貫性を回避するには、次の手順を実行します。 すべての訪問者を1つの真のドメインにリダイレクトすることをお勧めします。 HTTPS:
```nginx
# Redirect all HTTP to HTTPS with no-WWW
@@ -101,9 +96,7 @@ server {
上記の設定セクションは、`/etc/nginx/sites-available/default`または他のサイト設定に配置できます (新しい設定セクションを作成する場合は、必ず`sites-enabled`にシンボリックリンクしてください) 。
-SSL証明書がメイン設定で設定されていることを確認します。
-それぞれに`ssl_certificate`ディレクティブと`ssl_certificate_key`ディレクティブを追加します。
-SSLでリスニングする`server`セクション。
+SSL証明書がメイン設定で設定されていることを確認します。 それぞれに`ssl_certificate`ディレクティブと`ssl_certificate_key`ディレクティブを追加します。 SSLでリスニングする`server`セクション。
さらに、これらすべてを`nginx/conf.d/forwarded.conf`にコピー&ペーストします。
@@ -146,8 +139,7 @@ map $http_forwarded $proxy_add_forwarded {
}
```
-::: tip Note
-`conf.d`と`sites-available`を使用しないインストールの場合、上記の設定はすべて、メインの`nginx.conf`の`http`セクション内に配置することもできます。
+::: tip Note `conf.d`と`sites-available`を使用しないインストールの場合、上記の設定はすべて、メインの`nginx.conf`の`http`セクション内に配置することもできます。 :::
:::
変更後にNginxの設定をリロード:
@@ -156,11 +148,11 @@ map $http_forwarded $proxy_add_forwarded {
sudo nginx -s reload
```
-これで、`https://example.com/`でアプリを接続できるようになります。404エラーなどはすべてSanicのエラーページで処理され、静的ファイルが与えられたパスに存在する時はいつでもNginxによって提供されます。
+これで、`https://example.com/`でアプリを接続できるようになります。 404エラーなどはすべてSanicのエラーページで処理され、静的ファイルが与えられたパスに存在する時はいつでもNginxによって提供されます。
## SSL certificates
-サーバで有効な証明書をまだ設定していない場合は、ここで設定します。`certbot`と`python 3-certbot-nginx`をインストールしてください。
+サーバで有効な証明書をまだ設定していない場合は、ここで設定します。 `certbot`と`python 3-certbot-nginx`をインストールしてください。
```bash
certbot --nginx -d example.com -d www.example.com
@@ -170,7 +162,7 @@ certbot --nginx -d example.com -d www.example.com
## サービスとして実行
-このパートは`systemd`に基づくLinuxディストリビューション用です。ユニットファイル`/etc/systemd/system/sanicexample.service`を作成します。
+このパートは`systemd`に基づくLinuxディストリビューション用です。 ユニットファイル`/etc/systemd/system/sanicexample.service`を作成します。
```text
[Unit]
From c0c7581cdccfd006b2fc5bb2bb9710416b460180 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:15 +0300
Subject: [PATCH 122/776] New translations nginx.md (Korean)
---
src/ko/guide/deployment/nginx.md | 186 +++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
create mode 100644 src/ko/guide/deployment/nginx.md
diff --git a/src/ko/guide/deployment/nginx.md b/src/ko/guide/deployment/nginx.md
new file mode 100644
index 0000000000..09d0ce7fe7
--- /dev/null
+++ b/src/ko/guide/deployment/nginx.md
@@ -0,0 +1,186 @@
+# Nginx Deployment
+
+## Introduction
+
+
+Although Sanic can be run directly on Internet, it may be useful to use a proxy server such as Nginx in front of it. This is particularly useful for running multiple virtual hosts on the same IP, serving NodeJS or other services beside a single Sanic app, and it also allows for efficient serving of static files. SSL and HTTP/2 are also easily implemented on such proxy.
+
+We are setting the Sanic app to serve only locally at `127.0.0.1:8000`, while the Nginx installation is responsible for providing the service to public Internet on domain `example.com`. Static files will be served from `/var/www/`.
+
+
+## Proxied Sanic app
+
+The app needs to be setup with a secret key used to identify a trusted proxy, so that real client IP and other information can be identified. This protects against anyone on the Internet sending fake headers to spoof their IP addresses and other details. Choose any random string and configure it both on the app and in Nginx config.
+
+```python
+from sanic import Sanic
+from sanic.response import text
+
+app = Sanic("proxied_example")
+app.config.FORWARDED_SECRET = "YOUR SECRET"
+
+@app.get("/")
+def index(request):
+ # This should display external (public) addresses:
+ return text(
+ f"{request.remote_addr} connected to {request.url_for('index')}\n"
+ f"Forwarded: {request.forwarded}\n"
+ )
+
+if __name__ == "__main__":
+ app.run(host="127.0.0.1", port=8000, workers=8, access_log=False)
+```
+
+Since this is going to be a system service, save your code to `/srv/sanicexample/sanicexample.py`.
+
+For testing, run your app in a terminal.
+
+## Nginx configuration
+
+Quite much configuration is required to allow fast transparent proxying, but for the most part these don't need to be modified, so bear with me.
+
+Upstream servers need to be configured in a separate `upstream` block to enable HTTP keep-alive, which can drastically improve performance, so we use this instead of directly providing an upstream address in `proxy_pass` directive. In this example, the upstream section is named by `server_name`, i.e. the public domain name, which then also gets passed to Sanic in the `Host` header. You may change the naming as you see fit. Multiple servers may also be provided for load balancing and failover.
+
+Change the two occurrences of `example.com` to your true domain name, and instead of `YOUR SECRET` use the secret you chose for your app.
+
+```nginx
+upstream example.com {
+ keepalive 100;
+ server 127.0.0.1:8000;
+ #server unix:/tmp/sanic.sock;
+}
+
+server {
+ server_name example.com;
+ listen 443 ssl http2 default_server;
+ listen [::]:443 ssl http2 default_server;
+ # Serve static files if found, otherwise proxy to Sanic
+ location / {
+ root /var/www;
+ try_files $uri @sanic;
+ }
+ location @sanic {
+ proxy_pass http://$server_name;
+ # Allow fast streaming HTTP/1.1 pipes (keep-alive, unbuffered)
+ proxy_http_version 1.1;
+ proxy_request_buffering off;
+ proxy_buffering off;
+ # Proxy forwarding (password configured in app.config.FORWARDED_SECRET)
+ proxy_set_header forwarded "$proxy_forwarded;secret=\"YOUR SECRET\"";
+ # Allow websockets and keep-alive (avoid connection: close)
+ proxy_set_header connection "upgrade";
+ proxy_set_header upgrade $http_upgrade;
+ }
+}
+```
+
+To avoid cookie visibility issues and inconsistent addresses on search engines, it is a good idea to redirect all visitors to one true domain, always using HTTPS:
+
+```nginx
+# Redirect all HTTP to HTTPS with no-WWW
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ server_name ~^(?:www\.)?(.*)$;
+ return 301 https://$1$request_uri;
+}
+
+# Redirect WWW to no-WWW
+server {
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ server_name ~^www\.(.*)$;
+ return 301 $scheme://$1$request_uri;
+}
+```
+
+The above config sections may be placed in `/etc/nginx/sites-available/default` or in other site configs (be sure to symlink them to `sites-enabled` if you create new ones).
+
+Make sure that your SSL certificates are configured in the main config, or add the `ssl_certificate` and `ssl_certificate_key` directives to each `server` section that listens on SSL.
+
+Additionally, copy&paste all of this into `nginx/conf.d/forwarded.conf`:
+
+```nginx
+# RFC 7239 Forwarded header for Nginx proxy_pass
+
+# Add within your server or location block:
+# proxy_set_header forwarded "$proxy_forwarded;secret=\"YOUR SECRET\"";
+
+# Configure your upstream web server to identify this proxy by that password
+# because otherwise anyone on the Internet could spoof these headers and fake
+# their real IP address and other information to your service.
+
+
+# Provide the full proxy chain in $proxy_forwarded
+map $proxy_add_forwarded $proxy_forwarded {
+ default "$proxy_add_forwarded;by=\"_$hostname\";proto=$scheme;host=\"$http_host\";path=\"$request_uri\"";
+}
+
+# The following mappings are based on
+# https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
+
+map $remote_addr $proxy_forwarded_elem {
+ # IPv4 addresses can be sent as-is
+ ~^[0-9.]+$ "for=$remote_addr";
+
+ # IPv6 addresses need to be bracketed and quoted
+ ~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\"";
+
+ # Unix domain socket names cannot be represented in RFC 7239 syntax
+ default "for=unknown";
+}
+
+map $http_forwarded $proxy_add_forwarded {
+ # If the incoming Forwarded header is syntactically valid, append to it
+ "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
+
+ # Otherwise, replace it
+ default "$proxy_forwarded_elem";
+}
+```
+
+::: tip Note For installs that don't use `conf.d` and `sites-available`, all of the above configs may also be placed inside the `http` section of the main `nginx.conf`. :::
+
+Reload Nginx config after changes:
+
+```bash
+sudo nginx -s reload
+```
+
+Now you should be able to connect your app on `https://example.com/`. Any 404 errors and such will be handled by Sanic's error pages, and whenever a static file is present at a given path, it will be served by Nginx.
+
+## SSL certificates
+
+If you haven't already configured valid certificates on your server, now is a good time to do so. Install `certbot` and `python3-certbot-nginx`, then run
+
+```bash
+certbot --nginx -d example.com -d www.example.com
+```
+
+``_
+
+## Running as a service
+
+This part is for Linux distributions based on `systemd`. Create a unit file `/etc/systemd/system/sanicexample.service`
+
+```text
+[Unit]
+Description=Sanic Example
+
+[Service]
+User=nobody
+WorkingDirectory=/srv/sanicexample
+ExecStart=/usr/bin/env python3 sanicexample.py
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
+```
+
+Then reload service files, start your service and enable it on boot:
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl start sanicexample
+sudo systemctl enable sanicexample
+```
From a311f99591d92c4e64bc761999074b05e47ed984 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:16 +0300
Subject: [PATCH 123/776] New translations nginx.md (Chinese Simplified)
---
src/zh/guide/deployment/nginx.md | 50 +++++++++++++++-----------------
1 file changed, 23 insertions(+), 27 deletions(-)
diff --git a/src/zh/guide/deployment/nginx.md b/src/zh/guide/deployment/nginx.md
index 4ccaf8e3bb..1b5401080c 100644
--- a/src/zh/guide/deployment/nginx.md
+++ b/src/zh/guide/deployment/nginx.md
@@ -2,19 +2,15 @@
## 介绍(Introduction)
-尽管 Sanic 可以直接运行在 Internet 中,但是使用代理服务器可能会更好。
-例如在 Sanic 服务器之前添加 Nginx 代理服务器。这将有助于在同一台机器上同时提供多个不同的服务。
-这样做还可以简单快捷的提供静态文件。包括 SSL 和 HTTP2 等协议也可以在此类代理上轻松实现。
-我们将 Sanic 应用部署在本地,监听 `127.0.0.1`,
-然后使用 Nginx 代理 `/var/www` 下的静态文件,
-最后使用 Nginx 绑定域名 `example.com` 向公网提供服务
+尽管 Sanic 可以直接运行在 Internet 中,但是使用代理服务器可能会更好。 例如在 Sanic 服务器之前添加 Nginx 代理服务器。 This is particularly useful for running multiple virtual hosts on the same IP, serving NodeJS or other services beside a single Sanic app, and it also allows for efficient serving of static files. 包括 SSL 和 HTTP2 等协议也可以在此类代理上轻松实现。
+
+我们将 Sanic 应用部署在本地,监听 `127.0.0.1`, 然后使用 Nginx 代理 `/var/www` 下的静态文件, 最后使用 Nginx 绑定域名 `example.com` 向公网提供服务 Static files will be served from `/var/www/`.
+
## 代理 Sanic(Proxied Sanic app)
-被代理的应用应该设置 `FORWARDED_SECRET`(受信任代理的密钥)用于识别真实的客户端 IP 以及其他信息。
-这可以有效的防止网络中发送的伪造标头来隐藏其 IP 地址的请求。
-您可以设置任意随机字符串,同时,您需要在 Nginx 中进行相同的配置。
+被代理的应用应该设置 `FORWARDED_SECRET`(受信任代理的密钥)用于识别真实的客户端 IP 以及其他信息。 这可以有效的防止网络中发送的伪造标头来隐藏其 IP 地址的请求。 您可以设置任意随机字符串,同时,您需要在 Nginx 中进行相同的配置。
```python
from sanic import Sanic
@@ -43,11 +39,9 @@ if __name__ == "__main__":
允许快速透明代理需要相当多的配置,但是在大多数情况下,这些并不需要修改。
-在单独的 `upstream` 模块中配置 `keepalive` 来启用长连接,这可以极大的提高性能,而不是直接在 `server` 中 配置 `proxy_pass`。
-在此示例中,`upstream` 命名为 `server_name` 及域名,该名称将通过 Host 标头传递给 Sanic, 您可以按需修改该名称,也可以提供多个服务器以达到负载均衡和故障转移。
+在单独的 `upstream` 模块中配置 `keepalive` 来启用长连接,这可以极大的提高性能,而不是直接在 `server` 中 配置 `proxy_pass`。 在此示例中,`upstream` 命名为 `server_name` 及域名,该名称将通过 Host 标头传递给 Sanic, 您可以按需修改该名称,也可以提供多个服务器以达到负载均衡和故障转移。 You may change the naming as you see fit. Multiple servers may also be provided for load balancing and failover.
-将两次出现的 `example.com` 更改为您的域名,然后
-将 `YOUR SECRET` 替换为您应用中配置的 `FORWARDED_SECRET`
+将两次出现的 `example.com` 更改为您的域名,然后 将 `YOUR SECRET` 替换为您应用中配置的 `FORWARDED_SECRET`
```nginx
upstream example.com {
@@ -80,9 +74,7 @@ server {
}
```
-为避免 Cookie 可见性问题和搜索引擎上的地址不一致的问题,
-您可以使用以下方法将所有的访问都重定向到真实的域名上。
-以确保始终为 HTTPS 访问:
+为避免 Cookie 可见性问题和搜索引擎上的地址不一致的问题, 您可以使用以下方法将所有的访问都重定向到真实的域名上。 以确保始终为 HTTPS 访问:
```nginx
# Redirect all HTTP to HTTPS with no-WWW
@@ -119,6 +111,16 @@ server {
# their real IP address and other information to your service.
+# RFC 7239 Forwarded header for Nginx proxy_pass
+
+# Add within your server or location block:
+# proxy_set_header forwarded "$proxy_forwarded;secret=\"YOUR SECRET\"";
+
+# Configure your upstream web server to identify this proxy by that password
+# because otherwise anyone on the Internet could spoof these headers and fake
+# their real IP address and other information to your service.
+
+
# Provide the full proxy chain in $proxy_forwarded
map $proxy_add_forwarded $proxy_forwarded {
default "$proxy_add_forwarded;by=\"_$hostname\";proto=$scheme;host=\"$http_host\";path=\"$request_uri\"";
@@ -147,31 +149,25 @@ map $http_forwarded $proxy_add_forwarded {
}
```
-::: tip 小提示
+::: tip Note For installs that don't use `conf.d` and `sites-available`, all of the above configs may also be placed inside the `http` section of the main `nginx.conf`. :::
如果您的 Nginx 中不使用 `conf.d` 和 `sites-available`,以上配置也可以放在 `nginx.conf` 的 `http` 中。
-:::
-
-保存修改之后,重新启动 Nginx 服务:
-
```bash
sudo nginx -s reload
```
-现在,您应该可以在 `https://example.com/` 上访问您的应用了。
-任何的 404 以及类似的错误都将交由 Sanic 进行处理。
-静态文件存储在指定的目录下,将由 Nginx 提供访问。
+现在,您应该可以在 `https://example.com/` 上访问您的应用了。 任何的 404 以及类似的错误都将交由 Sanic 进行处理。 静态文件存储在指定的目录下,将由 Nginx 提供访问。
## SSL 证书(SSL certificates)
-如果您尚未在服务器上配置有效证书,您可以安装 `certbot` 和 `python3-certbot-nginx` 以使用免费的 SSL/TLS 证书,然后运行:
+If you haven't already configured valid certificates on your server, now is a good time to do so. Install `certbot` and `python3-certbot-nginx`, then run
```bash
certbot --nginx -d example.com -d www.example.com
```
-相关资料请参考:[使用免费的 SSL/TLS 证书](https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/)
+如果您尚未在服务器上配置有效证书,您可以安装 `certbot` 和 `python3-certbot-nginx` 以使用免费的 SSL/TLS 证书,然后运行:_
## 作为服务运行(Running as a service)
@@ -191,7 +187,7 @@ Restart=always
WantedBy=multi-user.target
```
-之后重新加载服务文件,启动服务并允许开机启动:
+相关资料请参考:[使用免费的 SSL/TLS 证书](https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/)
```bash
sudo systemctl daemon-reload
From 895ab60aa5f3d781d1a4231ee434a2d89d6032a5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:17 +0300
Subject: [PATCH 124/776] New translations nginx.md (Portuguese, Brazilian)
---
src/pt/guide/deployment/nginx.md | 186 +++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
create mode 100644 src/pt/guide/deployment/nginx.md
diff --git a/src/pt/guide/deployment/nginx.md b/src/pt/guide/deployment/nginx.md
new file mode 100644
index 0000000000..09d0ce7fe7
--- /dev/null
+++ b/src/pt/guide/deployment/nginx.md
@@ -0,0 +1,186 @@
+# Nginx Deployment
+
+## Introduction
+
+
+Although Sanic can be run directly on Internet, it may be useful to use a proxy server such as Nginx in front of it. This is particularly useful for running multiple virtual hosts on the same IP, serving NodeJS or other services beside a single Sanic app, and it also allows for efficient serving of static files. SSL and HTTP/2 are also easily implemented on such proxy.
+
+We are setting the Sanic app to serve only locally at `127.0.0.1:8000`, while the Nginx installation is responsible for providing the service to public Internet on domain `example.com`. Static files will be served from `/var/www/`.
+
+
+## Proxied Sanic app
+
+The app needs to be setup with a secret key used to identify a trusted proxy, so that real client IP and other information can be identified. This protects against anyone on the Internet sending fake headers to spoof their IP addresses and other details. Choose any random string and configure it both on the app and in Nginx config.
+
+```python
+from sanic import Sanic
+from sanic.response import text
+
+app = Sanic("proxied_example")
+app.config.FORWARDED_SECRET = "YOUR SECRET"
+
+@app.get("/")
+def index(request):
+ # This should display external (public) addresses:
+ return text(
+ f"{request.remote_addr} connected to {request.url_for('index')}\n"
+ f"Forwarded: {request.forwarded}\n"
+ )
+
+if __name__ == "__main__":
+ app.run(host="127.0.0.1", port=8000, workers=8, access_log=False)
+```
+
+Since this is going to be a system service, save your code to `/srv/sanicexample/sanicexample.py`.
+
+For testing, run your app in a terminal.
+
+## Nginx configuration
+
+Quite much configuration is required to allow fast transparent proxying, but for the most part these don't need to be modified, so bear with me.
+
+Upstream servers need to be configured in a separate `upstream` block to enable HTTP keep-alive, which can drastically improve performance, so we use this instead of directly providing an upstream address in `proxy_pass` directive. In this example, the upstream section is named by `server_name`, i.e. the public domain name, which then also gets passed to Sanic in the `Host` header. You may change the naming as you see fit. Multiple servers may also be provided for load balancing and failover.
+
+Change the two occurrences of `example.com` to your true domain name, and instead of `YOUR SECRET` use the secret you chose for your app.
+
+```nginx
+upstream example.com {
+ keepalive 100;
+ server 127.0.0.1:8000;
+ #server unix:/tmp/sanic.sock;
+}
+
+server {
+ server_name example.com;
+ listen 443 ssl http2 default_server;
+ listen [::]:443 ssl http2 default_server;
+ # Serve static files if found, otherwise proxy to Sanic
+ location / {
+ root /var/www;
+ try_files $uri @sanic;
+ }
+ location @sanic {
+ proxy_pass http://$server_name;
+ # Allow fast streaming HTTP/1.1 pipes (keep-alive, unbuffered)
+ proxy_http_version 1.1;
+ proxy_request_buffering off;
+ proxy_buffering off;
+ # Proxy forwarding (password configured in app.config.FORWARDED_SECRET)
+ proxy_set_header forwarded "$proxy_forwarded;secret=\"YOUR SECRET\"";
+ # Allow websockets and keep-alive (avoid connection: close)
+ proxy_set_header connection "upgrade";
+ proxy_set_header upgrade $http_upgrade;
+ }
+}
+```
+
+To avoid cookie visibility issues and inconsistent addresses on search engines, it is a good idea to redirect all visitors to one true domain, always using HTTPS:
+
+```nginx
+# Redirect all HTTP to HTTPS with no-WWW
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ server_name ~^(?:www\.)?(.*)$;
+ return 301 https://$1$request_uri;
+}
+
+# Redirect WWW to no-WWW
+server {
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ server_name ~^www\.(.*)$;
+ return 301 $scheme://$1$request_uri;
+}
+```
+
+The above config sections may be placed in `/etc/nginx/sites-available/default` or in other site configs (be sure to symlink them to `sites-enabled` if you create new ones).
+
+Make sure that your SSL certificates are configured in the main config, or add the `ssl_certificate` and `ssl_certificate_key` directives to each `server` section that listens on SSL.
+
+Additionally, copy&paste all of this into `nginx/conf.d/forwarded.conf`:
+
+```nginx
+# RFC 7239 Forwarded header for Nginx proxy_pass
+
+# Add within your server or location block:
+# proxy_set_header forwarded "$proxy_forwarded;secret=\"YOUR SECRET\"";
+
+# Configure your upstream web server to identify this proxy by that password
+# because otherwise anyone on the Internet could spoof these headers and fake
+# their real IP address and other information to your service.
+
+
+# Provide the full proxy chain in $proxy_forwarded
+map $proxy_add_forwarded $proxy_forwarded {
+ default "$proxy_add_forwarded;by=\"_$hostname\";proto=$scheme;host=\"$http_host\";path=\"$request_uri\"";
+}
+
+# The following mappings are based on
+# https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
+
+map $remote_addr $proxy_forwarded_elem {
+ # IPv4 addresses can be sent as-is
+ ~^[0-9.]+$ "for=$remote_addr";
+
+ # IPv6 addresses need to be bracketed and quoted
+ ~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\"";
+
+ # Unix domain socket names cannot be represented in RFC 7239 syntax
+ default "for=unknown";
+}
+
+map $http_forwarded $proxy_add_forwarded {
+ # If the incoming Forwarded header is syntactically valid, append to it
+ "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
+
+ # Otherwise, replace it
+ default "$proxy_forwarded_elem";
+}
+```
+
+::: tip Note For installs that don't use `conf.d` and `sites-available`, all of the above configs may also be placed inside the `http` section of the main `nginx.conf`. :::
+
+Reload Nginx config after changes:
+
+```bash
+sudo nginx -s reload
+```
+
+Now you should be able to connect your app on `https://example.com/`. Any 404 errors and such will be handled by Sanic's error pages, and whenever a static file is present at a given path, it will be served by Nginx.
+
+## SSL certificates
+
+If you haven't already configured valid certificates on your server, now is a good time to do so. Install `certbot` and `python3-certbot-nginx`, then run
+
+```bash
+certbot --nginx -d example.com -d www.example.com
+```
+
+``_
+
+## Running as a service
+
+This part is for Linux distributions based on `systemd`. Create a unit file `/etc/systemd/system/sanicexample.service`
+
+```text
+[Unit]
+Description=Sanic Example
+
+[Service]
+User=nobody
+WorkingDirectory=/srv/sanicexample
+ExecStart=/usr/bin/env python3 sanicexample.py
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
+```
+
+Then reload service files, start your service and enable it on boot:
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl start sanicexample
+sudo systemctl enable sanicexample
+```
From 54205a33f10793c4f39b0e67a3ce6b3b75492985 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:18 +0300
Subject: [PATCH 125/776] New translations running.md (Japanese)
---
src/ja/guide/deployment/running.md | 155 ++++++++++++++++++-----------
1 file changed, 98 insertions(+), 57 deletions(-)
diff --git a/src/ja/guide/deployment/running.md b/src/ja/guide/deployment/running.md
index 47e2fd9b18..ace67bc3fa 100644
--- a/src/ja/guide/deployment/running.md
+++ b/src/ja/guide/deployment/running.md
@@ -1,23 +1,23 @@
# Sanicの実行
-Sanicには、独自の内部Webサーバが付属しています。ほとんどの状況では、これがデプロイメントに適した方法です。さらに、Sanicは、ASGI対応ウェブサーバーにバンドルされたASGIアプリとして、またはgunicornを使用してデプロイすることもできます。
+Sanicには、独自の内部Webサーバが付属しています。 ほとんどの状況では、これがデプロイメントに適した方法です。 さらに、Sanicは、ASGI対応ウェブサーバーにバンドルされたASGIアプリとして、またはgunicornを使用してデプロイすることもできます。
## Sanicサーバー
`sanic.Sanic`の場合、次のキーワード引数を使用してrunメソッドを呼び出すことができます。
-| Parameter | Default | Description |
-| :-------------: | :------------: | :---------------------------------------------------------------------------------------- |
-| **host** | `"127.0.0.1"` | サーバーをホストするアドレス。 |
-| **port** | `8000` | サーバをホストするポート。 |
-| **unix** | `None` | サーバをホストするUnixソケット名 (TCPではありません) |
-| **debug** | `False` | デバッグ出力をイネーブルにします (サーバの速度が低下します) |
-| **ssl** | `None` | workersのSSL暗号化のためのSSLContext。 |
-| **sock** | `None` | サーバーがからの接続を受け入れるためのソケット。 |
-| **workers** | `1` | 作成するworkersもしくはprocessの数 |
-| **loop** | `None` | 非同期互換イベントループ。何も指定しないのであれば、独自のイベントループが作成されます |
-| **protocol** | `HttpProtocol` | asyncio.protocolのサブクラス。 |
-| **access_log** | `True` | 要求の処理でログオンを有効にします (サーバの処理速度が大幅に低下します) 。 |
+| Parameter | Default | Description |
+|:--------------:|:--------------:|:-------------------------------------------- |
+| **host** | `"127.0.0.1"` | サーバーをホストするアドレス。 |
+| **port** | `8000` | サーバをホストするポート。 |
+| **unix** | `None` | サーバをホストするUnixソケット名 (TCPではありません) |
+| **debug** | `False` | デバッグ出力をイネーブルにします (サーバの速度が低下します) |
+| **ssl** | `None` | workersのSSL暗号化のためのSSLContext。 |
+| **sock** | `None` | サーバーがからの接続を受け入れるためのソケット。 |
+| **workers** | `1` | 作成するworkersもしくはprocessの数 |
+| **loop** | `None` | 非同期互換イベントループ。 何も指定しないのであれば、独自のイベントループが作成されます |
+| **protocol** | `HttpProtocol` | asyncio.protocolのサブクラス。 |
+| **access_log** | `True` | 要求の処理でログオンを有効にします (サーバの処理速度が大幅に低下します) 。 |
---:1
@@ -47,20 +47,15 @@ python server.py
### Workers
----:1
-デフォルトでは、Sanicは1つのCPUコアだけを使用してメインプロセスをリッスンします。具体的には、run引数にworkersの数を指定します。
-:--:1
+---:1 デフォルトでは、Sanicは1つのCPUコアだけを使用してメインプロセスをリッスンします。 具体的には、run引数にworkersの数を指定します。 :--:1 :--:1
```python
app.run(host='0.0.0.0', port=1337, workers=4)
```
:---
-Sanicは自動的に複数のプロセスを起動し、それらの間でトラフィックをルーティングする。使用可能なプロセッサと同じ数のworkersを推奨します。
+Sanicは自動的に複数のプロセスを起動し、それらの間でトラフィックをルーティングする。 使用可能なプロセッサと同じ数のworkersを推奨します。
-::: new NEW in v21.12
----:1
-CPUの性能を最大限に引き出す最も簡単な方法は、 `fast` オプションを使用することです。これは、システムの制約を考慮して、自動的に最大数のワーカーを実行します。
-:--:1
+CPUの性能を最大限に引き出す最も簡単な方法は、 `fast` オプションを使用することです。 これは、システムの制約を考慮して、自動的に最大数のワーカーを実行します。 :--:1 :--:1
```python
app.run(host='0.0.0.0', port=1337, fast=True)
```
@@ -68,9 +63,8 @@ app.run(host='0.0.0.0', port=1337, fast=True)
$ sanic server:app --host=0.0.0.0 --port=1337 --fast
```
:---
-:::
-古いバージョンのSanicで `fast` オプションがない場合、LinuxベースのOSでよくある確認方法を試してみてください。。
+古いバージョンのSanicで `fast` オプションがない場合、LinuxベースのOSでよくある確認方法を試してみてください。
```
$ nproc
@@ -88,18 +82,17 @@ app.run(..., workers=workers)
#### Sanic CLI
----:1
-コマンドラインから起動できるシンプルなCLIも用意されています。
+---:1 コマンドラインから起動できるシンプルなCLIも用意されています。
-たとえば、`server.py`という名前のファイルでアプリケーションとしてSanicを初期化した場合、次のようにサーバを実行できます。
-:--:1
+たとえば、`server.py`という名前のファイルでアプリケーションとしてSanicを初期化した場合、次のようにサーバを実行できます。 :--:1
```bash
sanic server.app --host=0.0.0.0 --port=1337 --workers=4
```
-:---
+:---
すべてのオプションを表示するには、`sanic --help`を使用します。
+
```text
$ sanic --help
usage: sanic [-h] [--version] [--factory] [-s] [-H HOST] [-p PORT] [-u UNIX] [--cert CERT] [--key KEY] [--tls DIR] [--tls-strict-host]
@@ -180,16 +173,14 @@ Optional
#### モジュールとして
----:1
-モジュールとして直接呼び出すこともできます。
-:--:1
+---:1 モジュールとして直接呼び出すこともできます。 :--:1 :--:1
```bash
python -m sanic server.app --host=0.0.0.0 --port=1337 --workers=4
```
:---
-::: tip FYI
-どちらの方法(CLIまたはモジュール)でも、Pythonファイルの`app.run()`を*呼び出さない*でください。もしも実行する場合は、インタプリタによって直接実行される場合にのみ実行されるようにラップしてください。
+::: tip FYI どちらの方法(CLIまたはモジュール)でも、Pythonファイルの`app.run()`を*呼び出さない*でください。 もしも実行する場合は、インタプリタによって直接実行される場合にのみ実行されるようにラップしてください。
+
```python
if __name__ == '__main__':
app.run(host='0.0.0.0', port=1337, workers=4)
@@ -197,30 +188,27 @@ if __name__ == '__main__':
:::
-#### Sanicシンプルサーバー
+### Sanicシンプルサーバー
----:1
-提供する必要がある静的ファイルのディレクトリだけがある場合もあります。これは特に、localhostサーバーを素早く立ち上げる場合に便利です。SanicにはSimple Serverが付属しており、ディレクトリを指定するだけです。
-:--:1
+---:1 提供する必要がある静的ファイルのディレクトリだけがある場合もあります。 これは特に、localhostサーバーを素早く立ち上げる場合に便利です。 SanicにはSimple Serverが付属しており、ディレクトリを指定するだけです。 :--:1 :--:1
```bash
sanic ./path/to/dir --simple
```
:---
----:1
-自動リロードと組み合わせることもできます。
-:--:1
+---:1 自動リロードと組み合わせることもできます。 :--:1 :--:1
```bash
sanic ./path/to/dir --simple --reload --reload-dir=./path/to/dir
```
:---
-## ASGI
-SanicもASGIに準拠しています。つまり、任意のASGI Webサーバを使用してSanicを実行できます。ASGIの3つの主要な実装は、[Daphne](http://github.com/django/daphne),[Uvicorn](https://www.uvicorn.org/),と[Hypercorn](https://pgjones.gitlab.io/hypercorn/index.html)です。
+::: new NEW in v21.12 ---:1
+
+### HTTP/3
+
-実行方法は次のようになります。
-※適切な実行方法についてはドキュメントを参照してください。
+Sanic server offers HTTP/3 support using [aioquic](https://github.com/aiortc/aioquic). This **must** be installed to use HTTP/3:
```
daphne myapp:app
@@ -228,10 +216,68 @@ uvicorn myapp:app
hypercorn myapp:app
```
+```
+pip install sanic[http3]
+```
+
ASGIを使用する際には、次の点に注意してください。
-1. Sanic Webサーバを使用する場合、websocketsは`websockets`パッケージを使用して実行されますが。ASGIモードでは、websocketsはASGIサーバで管理されるため、このパッケージは必要ありません。
-2. ASGIライフスパンプロトコルは、スタートアップとシャットダウンの2つのサーバイベントだけをサポートします。Sanicには、起動前、起動後、シャットダウン前、シャットダウン後の4つがあります。したがって、ASGIモードでは、スタートアップイベントとシャットダウンイベントは連続して実行され、実際にはサーバプロセスの開始と終了の前後では実行されません(なぜなら現在、ASGIサーバによって制御されているためです)。したがって、`after_server_start`および`before_server_stop`を使用することをお薦めします。
+---:1
+```
+$ sanic path.to.server:app --http=3
+```
+
+```
+$ sanic path.to.server:app -3
+```
+:--:1
+
+```python
+app.run(version=3)
+```
+:---
+
+To run both an HTTP/3 and HTTP/1.1 server simultaneously, you can use [application multi-serve](http://localhost:8080/en/guide/release-notes/v22.3.html#application-multi-serve) introduced in v22.3. This will automatically add an [Alt-Svc](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc) header to your HTTP/1.1 requests to let the client know that it is also available as HTTP/3.
+
+
+---:1
+```
+$ sanic path.to.server:app --http=3 --http=1
+```
+
+```
+$ sanic path.to.server:app -3 -1
+```
+:--:1
+
+```python
+app.prepre(version=3)
+app.prepre(version=1)
+Sanic.serve()
+```
+:---
+
+Because HTTP/3 requires TLS, you cannot start a HTTP/3 server without a TLS certificate. You should [set it up yourself](http://localhost:8080/en/guide/how-to/tls.html) or use `mkcert` if in `DEBUG` mode. Currently, automatic TLS setup for HTTP/3 is not compatible with `trustme`. See [development](./development.md) for more details.
+
+:::
+
+## ASGI
+
+SanicもASGIに準拠しています。 つまり、任意のASGI Webサーバを使用してSanicを実行できます。 ASGIの3つの主要な実装は、[Daphne](http://github.com/django/daphne),[Uvicorn](https://www.uvicorn.org/),と[Hypercorn](https://pgjones.gitlab.io/hypercorn/index.html)です。
+
+::: warning Daphne does not support the ASGI `lifespan` protocol, and therefore cannot be used to run Sanic. See [Issue #264](https://github.com/django/daphne/issues/264) for more details. :::
+
+実行方法は次のようになります。 ※適切な実行方法についてはドキュメントを参照してください。
+
+```
+uvicorn myapp:app
+hypercorn myapp:app
+```
+
+A couple things to note when using ASGI:
+
+1. Sanic Webサーバを使用する場合、websocketsは`websockets`パッケージを使用して実行されますが。 ASGIモードでは、websocketsはASGIサーバで管理されるため、このパッケージは必要ありません。
+2. ASGIライフスパンプロトコルは、スタートアップとシャットダウンの2つのサーバイベントだけをサポートします。 Sanicには、起動前、起動後、シャットダウン前、シャットダウン後の4つがあります。 したがって、ASGIモードでは、スタートアップイベントとシャットダウンイベントは連続して実行され、実際にはサーバプロセスの開始と終了の前後では実行されません(なぜなら現在、ASGIサーバによって制御されているためです)。 したがって、`after_server_start`および`before_server_stop`を使用することをお薦めします。
### Trio
@@ -244,7 +290,7 @@ hypercorn -k trio myapp:app
## Gunicorn
-[Gunicorn](http://gunicorn.org/)("Green Unicorn")は、UNIXベースのオペレーティング・システム用のWSGI HTTP Serverです。これはRubyのUnicornプロジェクトから移植されたフォーク前のworkerモデルです。
+[Gunicorn](http://gunicorn.org/)("Green Unicorn")は、UNIXベースのオペレーティング・システム用のWSGI HTTP Serverです。 これはRubyのUnicornプロジェクトから移植されたフォーク前のworkerモデルです。
GunicornでSanicアプリケーションを実行するには、特殊な`sanic.worker.GunicornWorker`を実行する必要があります:
@@ -252,29 +298,24 @@ GunicornでSanicアプリケーションを実行するには、特殊な`sanic.
gunicorn myapp:app --bind 0.0.0.0:1337 --worker-class sanic.worker.GunicornWorker
```
-アプリケーションでメモリリークが発生した場合、Gunicornを設定して、指定した数のリクエストを処理したあとでワーカーを正常に再起動できます。これは、メモリリークの影響を制限するのに役立つ便利な方法です。
+アプリケーションでメモリリークが発生した場合、Gunicornを設定して、指定した数のリクエストを処理したあとでワーカーを正常に再起動できます。 これは、メモリリークの影響を制限するのに役立つ便利な方法です。
詳細については、[Gunicorn Docs](http://docs.gunicorn.org/en/latest/settings.html#max-requests) を参照してください。
-::: warning
-`gunicorn`経由でSanicを実行すると、`async/await`のパフォーマンス上の利点の多くを失うことになります。慎重に検討してから選択してください。Gunicornには多くの設定オプションが用意されていますが、Sanicを最速で動作させるには最適な選択肢ではありません。
+::: warning `gunicorn`経由でSanicを実行すると、`async/await`のパフォーマンス上の利点の多くを失うことになります。 Weigh your considerations carefully before making this choice. Gunicornには多くの設定オプションが用意されていますが、Sanicを最速で動作させるには最適な選択肢ではありません。 :::
:::
## パフォーマンスに関する考慮事項
----:1
-本番環境で実行する場合は、`debug`を必ずオフにしてください。
-:--:1
+---:1 本番環境で実行する場合は、`debug`を必ずオフにしてください。 :--:1 :--:1
```python
app.run(..., debug=False)
```
:---
----:1
-また、`access_log`をオフにすると、Sanicは最も高速に動作します。
+---:1 また、`access_log`をオフにすると、Sanicは最も高速に動作します。
-それでもアクセスログが必要だが、このパフォーマンス向上を享受したい場合は、[Nginxをプロキシとして](./nginx.md)使用すればアクセスログを処理できます。Pythonが処理できるものよりもはるかに高速になります。
-:--:1
+それでもアクセスログが必要だが、このパフォーマンス向上を享受したい場合は、[Nginxをプロキシとして](./nginx.md)使用すればアクセスログを処理できます。 Pythonが処理できるものよりもはるかに高速になります。 :--:1 :--:1
```python
app.run(..., access_log=False)
```
From 77ed65ccf6e23956ad466e245fa766b3fd64aa6d Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:19 +0300
Subject: [PATCH 126/776] New translations running.md (Korean)
---
src/ko/guide/deployment/running.md | 319 +++++++++++++++++++++++++++++
1 file changed, 319 insertions(+)
create mode 100644 src/ko/guide/deployment/running.md
diff --git a/src/ko/guide/deployment/running.md b/src/ko/guide/deployment/running.md
new file mode 100644
index 0000000000..51a6a5c2a0
--- /dev/null
+++ b/src/ko/guide/deployment/running.md
@@ -0,0 +1,319 @@
+# Running Sanic
+
+Sanic ships with its own internal web server. Under most circumstances, this is the preferred method for deployment. In addition, you can also deploy Sanic as an ASGI app bundled with an ASGI-able web server, or using gunicorn.
+
+## Sanic Server
+
+After defining an instance of `sanic.Sanic`, we can call the run method with the following keyword arguments:
+
+| Parameter | Default | Description |
+|:--------------:|:--------------:|:----------------------------------------------------------------------------------------- |
+| **host** | `"127.0.0.1"` | Address to host the server on. |
+| **port** | `8000` | Port to host the server on. |
+| **unix** | `None` | Unix socket name to host the server on (instead of TCP). |
+| **debug** | `False` | Enables debug output (slows server). |
+| **ssl** | `None` | SSLContext for SSL encryption of worker(s). |
+| **sock** | `None` | Socket for the server to accept connections from. |
+| **workers** | `1` | Number of worker processes to spawn. |
+| **loop** | `None` | An asyncio-compatible event loop. If none is specified, Sanic creates its own event loop. |
+| **protocol** | `HttpProtocol` | Subclass of asyncio.protocol. |
+| **access_log** | `True` | Enables log on handling requests (significantly slows server). |
+
+---:1
+
+In the above example, we decided to turn off the access log in order to increase performance.
+
+:--:1
+
+```python
+# server.py
+app = Sanic("My App")
+app.run(host='0.0.0.0', port=1337, access_log=False)
+```
+
+:---
+
+---:1
+
+Now, just execute the python script that has `app.run(...)`
+
+:--:1
+
+```bash
+python server.py
+```
+
+:---
+
+### Workers
+
+---:1 By default, Sanic listens in the main process using only one CPU core. To crank up the juice, just specify the number of workers in the run arguments. :--:1
+```python
+app.run(host='0.0.0.0', port=1337, workers=4)
+```
+:---
+
+Sanic will automatically spin up multiple processes and route traffic between them. We recommend as many workers as you have available processors.
+
+---:1 The easiest way to get the maximum CPU performance is to use the `fast` option. This will automatically run the maximum number of workers given the system constraints. :--:1
+```python
+app.run(host='0.0.0.0', port=1337, fast=True)
+```
+```python
+$ sanic server:app --host=0.0.0.0 --port=1337 --fast
+```
+:---
+
+In older versions of Sanic without the `fast` option, a common way to check this on Linux based operating systems:
+
+```
+$ nproc
+```
+
+Or, let Python do it:
+
+```python
+import multiprocessing
+workers = multiprocessing.cpu_count()
+app.run(..., workers=workers)
+```
+
+### Running via command
+
+#### Sanic CLI
+
+---:1 Sanic also has a simple CLI to launch via command line.
+
+For example, if you initialized Sanic as app in a file named `server.py`, you could run the server like so: :--:1
+```bash
+sanic server.app --host=0.0.0.0 --port=1337 --workers=4
+```
+
+:---
+
+Use `sanic --help` to see all the options.
+
+```text
+$ sanic --help
+usage: sanic [-h] [--version] [--factory] [-s] [-H HOST] [-p PORT] [-u UNIX] [--cert CERT] [--key KEY] [--tls DIR] [--tls-strict-host]
+ [-w WORKERS | --fast] [--access-logs | --no-access-logs] [--debug] [-d] [-r] [-R PATH] [--motd | --no-motd] [-v]
+ [--noisy-exceptions | --no-noisy-exceptions]
+ module
+
+ ▄███ █████ ██ ▄█▄ ██ █ █ ▄██████████
+ ██ █ █ █ ██ █ █ ██
+ ▀███████ ███▄ ▀ █ █ ██ ▄ █ ██
+ ██ █████████ █ ██ █ █ ▄▄
+ ████ ████████▀ █ █ █ ██ █ ▀██ ███████
+
+ To start running a Sanic application, provide a path to the module, where
+ app is a Sanic() instance:
+
+ $ sanic path.to.server:app
+
+ Or, a path to a callable that returns a Sanic() instance:
+
+ $ sanic path.to.factory:create_app --factory
+
+ Or, a path to a directory to run as a simple HTTP server:
+
+ $ sanic ./path/to/static --simple
+
+Required
+========
+ Positional:
+ module Path to your Sanic app. Example: path.to.server:app
+ If running a Simple Server, path to directory to serve. Example: ./
+
+Optional
+========
+ General:
+ -h, --help show this help message and exit
+ --version show program's version number and exit
+
+ Application:
+ --factory Treat app as an application factory, i.e. a () -> callable
+ -s, --simple Run Sanic as a Simple Server, and serve the contents of a directory
+ (module arg should be a path)
+
+ Socket binding:
+ -H HOST, --host HOST Host address [default 127.0.0.1]
+ -p PORT, --port PORT Port to serve on [default 8000]
+ -u UNIX, --unix UNIX location of unix socket
+
+ TLS certificate:
+ --cert CERT Location of fullchain.pem, bundle.crt or equivalent
+ --key KEY Location of privkey.pem or equivalent .key file
+ --tls DIR TLS certificate folder with fullchain.pem and privkey.pem
+ May be specified multiple times to choose multiple certificates
+ --tls-strict-host Only allow clients that send an SNI matching server certs
+
+ Worker:
+ -w WORKERS, --workers WORKERS Number of worker processes [default 1]
+ --fast Set the number of workers to max allowed
+ --access-logs Display access logs
+ --no-access-logs No display access logs
+
+ Development:
+ --debug Run the server in debug mode
+ -d, --dev Currently is an alias for --debug. But starting in v22.3,
+ --debug will no longer automatically trigger auto_restart.
+ However, --dev will continue, effectively making it the
+ same as debug + auto_reload.
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+
+ Output:
+ --motd Show the startup display
+ --no-motd No show the startup display
+ -v, --verbosity Control logging noise, eg. -vv or --verbosity=2 [default 0]
+ --noisy-exceptions Output stack traces for all exceptions
+ --no-noisy-exceptions No output stack traces for all exceptions
+```
+
+#### As a module
+
+---:1 It can also be called directly as a module. :--:1
+```bash
+python -m sanic server.app --host=0.0.0.0 --port=1337 --workers=4
+```
+:---
+
+::: tip FYI With either method (CLI or module), you shoud *not* invoke `app.run()` in your Python file. If you do, make sure you wrap it so that it only executes when directly run by the interpreter.
+
+```python
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=1337, workers=4)
+```
+:::
+
+
+### Sanic Simple Server
+
+---:1 Sometimes you just have a directory of static files that need to be served. This especially can be handy for quickly standing up a localhost server. Sanic ships with a Simple Server, where you only need to point it at a directory. :--:1
+```bash
+sanic ./path/to/dir --simple
+```
+:---
+
+---:1 This could also be paired with auto-reloading. :--:1
+```bash
+sanic ./path/to/dir --simple --reload --reload-dir=./path/to/dir
+```
+:---
+
+
+::: new NEW in v22.6
+
+### HTTP/3
+
+
+Sanic server offers HTTP/3 support using [aioquic](https://github.com/aiortc/aioquic). This **must** be installed to use HTTP/3:
+
+```
+pip install sanic aioquic
+```
+
+```
+pip install sanic[http3]
+```
+
+To start HTTP/3, you must explicitly request it when running your application.
+
+---:1
+```
+$ sanic path.to.server:app --http=3
+```
+
+```
+$ sanic path.to.server:app -3
+```
+:--:1
+
+```python
+app.run(version=3)
+```
+:---
+
+To run both an HTTP/3 and HTTP/1.1 server simultaneously, you can use [application multi-serve](http://localhost:8080/en/guide/release-notes/v22.3.html#application-multi-serve) introduced in v22.3. This will automatically add an [Alt-Svc](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc) header to your HTTP/1.1 requests to let the client know that it is also available as HTTP/3.
+
+
+---:1
+```
+$ sanic path.to.server:app --http=3 --http=1
+```
+
+```
+$ sanic path.to.server:app -3 -1
+```
+:--:1
+
+```python
+app.prepre(version=3)
+app.prepre(version=1)
+Sanic.serve()
+```
+:---
+
+Because HTTP/3 requires TLS, you cannot start a HTTP/3 server without a TLS certificate. You should [set it up yourself](http://localhost:8080/en/guide/how-to/tls.html) or use `mkcert` if in `DEBUG` mode. Currently, automatic TLS setup for HTTP/3 is not compatible with `trustme`. See [development](./development.md) for more details.
+
+:::
+
+## ASGI
+
+Sanic is also ASGI-compliant. This means you can use your preferred ASGI webserver to run Sanic. The three main implementations of ASGI are [Daphne](http://github.com/django/daphne), [Uvicorn](https://www.uvicorn.org/), and [Hypercorn](https://pgjones.gitlab.io/hypercorn/index.html).
+
+::: warning Daphne does not support the ASGI `lifespan` protocol, and therefore cannot be used to run Sanic. See [Issue #264](https://github.com/django/daphne/issues/264) for more details. :::
+
+Follow their documentation for the proper way to run them, but it should look something like:
+
+```
+uvicorn myapp:app
+hypercorn myapp:app
+```
+
+A couple things to note when using ASGI:
+
+1. When using the Sanic webserver, websockets will run using the `websockets` package. In ASGI mode, there is no need for this package since websockets are managed in the ASGI server.
+2. The ASGI lifespan protocol , supports only two server events: startup and shutdown. Sanic has four: before startup, after startup, before shutdown, and after shutdown. Therefore, in ASGI mode, the startup and shutdown events will run consecutively and not actually around the server process beginning and ending (since that is now controlled by the ASGI server). Therefore, it is best to use `after_server_start` and `before_server_stop`.
+
+### Trio
+
+Sanic has experimental support for running on Trio with:
+
+```
+hypercorn -k trio myapp:app
+```
+
+
+## Gunicorn
+
+[Gunicorn](http://gunicorn.org/) ("Green Unicorn") is a WSGI HTTP Server for UNIX based operating systems. It is a pre-fork worker model ported from Ruby’s Unicorn project.
+
+In order to run Sanic application with Gunicorn, you need to use the special `sanic.worker.GunicornWorker` for Gunicorn worker-class argument:
+
+```bash
+gunicorn myapp:app --bind 0.0.0.0:1337 --worker-class sanic.worker.GunicornWorker
+```
+
+If your application suffers from memory leaks, you can configure Gunicorn to gracefully restart a worker after it has processed a given number of requests. This can be a convenient way to help limit the effects of the memory leak.
+
+See the [Gunicorn Docs](http://docs.gunicorn.org/en/latest/settings.html#max-requests) for more information.
+
+::: warning When running Sanic via `gunicorn`, you are losing out on a lot of the performance benefits of `async`/`await`. Weigh your considerations carefully before making this choice. Gunicorn does provide a lot of configuration options, but it is not the best choice for getting Sanic to run at its fastest. :::
+
+## Performance considerations
+
+---:1 When running in production, make sure you turn off `debug`. :--:1
+```python
+app.run(..., debug=False)
+```
+:---
+
+---:1 Sanic will also perform fastest if you turn off `access_log`.
+
+If you still require access logs, but want to enjoy this performance boost, consider using [Nginx as a proxy](./nginx.md), and letting that handle your access logging. It will be much faster than anything Python can handle. :--:1
+```python
+app.run(..., access_log=False)
+```
+:---
From 0e60284e6a8ff8faf426056232c7b85b72e348f8 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:20 +0300
Subject: [PATCH 127/776] New translations running.md (Chinese Simplified)
---
src/zh/guide/deployment/running.md | 226 +++++++++++++++++------------
1 file changed, 135 insertions(+), 91 deletions(-)
diff --git a/src/zh/guide/deployment/running.md b/src/zh/guide/deployment/running.md
index 0962a1e4b7..6cdef5ed8c 100644
--- a/src/zh/guide/deployment/running.md
+++ b/src/zh/guide/deployment/running.md
@@ -1,23 +1,23 @@
# 运行 Sanic(Running Sanic)
-Sanic 自带了一个 Web 服务器。在大多数情况下,推荐使用该服务器来部署您的 Sanic 应用。除此之外,您还可以使用支持 ASGI 应用的服务器来部署 Sanic,或者使用 Gunicorn。
+Sanic 自带了一个 Web 服务器。 在大多数情况下,推荐使用该服务器来部署您的 Sanic 应用。 除此之外,您还可以使用支持 ASGI 应用的服务器来部署 Sanic,或者使用 Gunicorn。
## Sanic 服务器(Sanic Server)
当定义了 `sanic.Sanic` 实例后,我们可以调用其 `run` 方法,该方法支持以下几个关键字参数:
-| 参数名称 | 默认值 | 参数说明 |
-| :------------: | :------------: | :---------------------------------------------------------------------- |
-| **host** | `"127.0.0.1"` | 服务器监听的地址。 |
-| **port** | `8000` | 服务器监听的端口。 |
-| **unix** | `None` | Unix 套接字文件(不是 TCP)。 |
-| **debug** | `False` | 开启 DEBUG 输出 (降低服务器性能)。 |
-| **ssl** | `None` | SSLContext,子进程用于 SSL 加密。 |
-| **sock** | `None` | 服务器接受连接的套接字。 |
-| **workers** | `1` | 要生成的子进程数量。 |
-| **loop** | `None` | 一个兼容 asyncio 的事件循环。如果没有指定,Sanic 会创建自己的事件循环。 |
-| **protocol** | `HttpProtocol` | asyncio.protocol 子类。 |
-| **access_log** | `True` | 启用请求访问日志(显著降低服务器速度)。 |
+| 参数名称 | 默认值 | 参数说明 |
+|:--------------:|:--------------:|:-------------------------------------------- |
+| **host** | `"127.0.0.1"` | 服务器监听的地址。 |
+| **port** | `8000` | 服务器监听的端口。 |
+| **unix** | `None` | Unix 套接字文件(不是 TCP)。 |
+| **debug** | `False` | 开启 DEBUG 输出 (降低服务器性能)。 |
+| **ssl** | `None` | SSLContext,子进程用于 SSL 加密。 |
+| **sock** | `None` | 服务器接受连接的套接字。 |
+| **workers** | `1` | 要生成的子进程数量。 |
+| **loop** | `None` | 一个兼容 asyncio 的事件循环。 如果没有指定,Sanic 会创建自己的事件循环。 |
+| **protocol** | `HttpProtocol` | asyncio.protocol 子类。 |
+| **access_log** | `True` | 启用请求访问日志(显著降低服务器速度)。 |
---:1
@@ -47,34 +47,21 @@ python server.py
### 子进程(Workers)
----:1
-
-在默认情况下,Sanic 在主进程中只占用一个 CPU 核心进行服务的监听。要想增加并发,只需在运行参数中指定 workers 的数量即可。
-
-:--:1
-
+在默认情况下,Sanic 在主进程中只占用一个 CPU 核心进行服务的监听。 要想增加并发,只需在运行参数中指定 workers 的数量即可。 :--:1
```python
app.run(host='0.0.0.0', port=1337, workers=4)
```
-
:---
-Sanic 会自动管理多个进程,并在它们之间进行负载均衡。我们建议将子进程数量设置的和您机器的 CPU 核心数量一样。
-
----:1
-
-获得最大 CPU 性能的最简单方法是使用 `fast` 参数。这将自动以系统最大的核心数量来创建工作线程。
-
-:--:1
+Sanic 会自动管理多个进程,并在它们之间进行负载均衡。 我们建议将子进程数量设置的和您机器的 CPU 核心数量一样。
+获得最大 CPU 性能的最简单方法是使用 `fast` 参数。 This will automatically run the maximum number of workers given the system constraints. :--:1
```python
app.run(host='0.0.0.0', port=1337, fast=True)
```
-
```python
$ sanic server:app --host=0.0.0.0 --port=1337 --fast
```
-
:---
在没有 `fast` 选项的旧版 Sanic 中, 在基于 Linux 的操作系统上,有一个通用的方式来检查 CPU 核心数量:
@@ -83,7 +70,7 @@ $ sanic server:app --host=0.0.0.0 --port=1337 --fast
$ nproc
```
-或者,我们可以使用 Python 来获取该值:
+Or, let Python do it:
```python
import multiprocessing
@@ -95,21 +82,16 @@ app.run(..., workers=workers)
#### Sanic 命令行界面(Sanic CLI)
----:1
-
Sanic 也提供一个简单的命令行界面,来帮助您通过命令行启动。
比如,如果您在 `server.py` 文件中初始化了一个 Sanic 应用,您可以使用右侧命令运行程序:
-
-:--:1
-
```bash
sanic server.app --host=0.0.0.0 --port=1337 --workers=4
```
:---
-您还可以使用 `sanic --help` 来查看所有选项。
+或者,我们可以使用 Python 来获取该值:
```text
$ sanic --help
@@ -186,83 +168,160 @@ Optional
--no-motd No show the startup display
-v, --verbosity Control logging noise, eg. -vv or --verbosity=2 [default 0]
--noisy-exceptions Output stack traces for all exceptions
- --no-noisy-exceptions No output stack traces for all exceptions
-```
+ --no-noisy-exceptions No output stack traces for all exceptions Example: path.to.server:app
+ If running a Simple Server, path to directory to serve. Example: ./
-#### 作为模块运行 (As a module)
+Optional
+========
+ General:
+ -h, --help show this help message and exit
+ --version show program's version number and exit
----:1
+ Application:
+ --factory Treat app as an application factory, i.e. a () -> callable
+ -s, --simple Run Sanic as a Simple Server, and serve the contents of a directory
+ (module arg should be a path)
+
+ Socket binding:
+ -H HOST, --host HOST Host address [default 127.0.0.1]
+ -p PORT, --port PORT Port to serve on [default 8000]
+ -u UNIX, --unix UNIX location of unix socket
-Sanic 也可以被当做模板直接调用。
+ TLS certificate:
+ --cert CERT Location of fullchain.pem, bundle.crt or equivalent
+ --key KEY Location of privkey.pem or equivalent .key file
+ --tls DIR TLS certificate folder with fullchain.pem and privkey.pem
+ May be specified multiple times to choose multiple certificates
+ --tls-strict-host Only allow clients that send an SNI matching server certs
-:--:1
+ Worker:
+ -w WORKERS, --workers WORKERS Number of worker processes [default 1]
+ --fast Set the number of workers to max allowed
+ --access-logs Display access logs
+ --no-access-logs No display access logs
+ Development:
+ --debug Run the server in debug mode
+ -d, --dev Currently is an alias for --debug. But starting in v22.3,
+ --debug will no longer automatically trigger auto_restart.
+ However, --dev will continue, effectively making it the
+ same as debug + auto_reload.
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+
+ Output:
+ --motd Show the startup display
+ --no-motd No show the startup display
+ -v, --verbosity Control logging noise, eg. -vv or --verbosity=2 [default 0]
+ --noisy-exceptions Output stack traces for all exceptions
+ --no-noisy-exceptions No output stack traces for all exceptions
+```
+
+#### 作为模块运行 (As a module)
+
+---:1 It can also be called directly as a module. :--:1
```bash
python -m sanic server.app --host=0.0.0.0 --port=1337 --workers=4
```
-
:---
-::: tip 小提示
-
-无论使用哪种方法(CLI 或模块),都再不应该在 Python 文件中调用 `app.run()`。如果您想调用该方法,请确认将其包装起来,使它只有在使用解释器运行文件时才会被执行。
+无论使用哪种方法(CLI 或模块),都再不应该在 Python 文件中调用 `app.run()`。 如果您想调用该方法,请确认将其包装起来,使它只有在使用解释器运行文件时才会被执行。
```python
if __name__ == '__main__':
app.run(host='0.0.0.0', port=1337, workers=4)
```
-
:::
-#### Sanic 简易服务器
-
----:1
-有时,您为了快速搭建一个本地环境,只需要代理一些静态文件。现在,只要指定一个特定的目录,Sanic 就能为您搭建一个简易的静态文件服务器。
-
-:--:1
+### Sanic 简易服务器
+---:1 Sometimes you just have a directory of static files that need to be served. This especially can be handy for quickly standing up a localhost server. 现在,只要指定一个特定的目录,Sanic 就能为您搭建一个简易的静态文件服务器。 :--:1
```bash
sanic ./path/to/dir --simple
```
+:---
+---:1 This could also be paired with auto-reloading. :--:1
+```bash
+sanic ./path/to/dir --simple --reload --reload-dir=./path/to/dir
+```
:---
----:1
-这也可以和自动重启功能一起使用。
+::: new NEW in v22.6
-:--:1
+### HTTP/3
-```bash
-sanic ./path/to/dir --simple --reload --reload-dir=./path/to/dir
+
+Sanic server offers HTTP/3 support using [aioquic](https://github.com/aiortc/aioquic). This **must** be installed to use HTTP/3:
+
+```
+pip install sanic aioquic
```
+```
+pip install sanic[http3]
+```
+
+::: tip 小提示
+
+---:1
+```
+$ sanic path.to.server:app --http=3
+```
+
+```
+$ sanic path.to.server:app -3
+```
+:--:1
+
+```python
+app.run(version=3)
+```
:---
-## ASGI
+To run both an HTTP/3 and HTTP/1.1 server simultaneously, you can use [application multi-serve](http://localhost:8080/en/guide/release-notes/v22.3.html#application-multi-serve) introduced in v22.3. This will automatically add an [Alt-Svc](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc) header to your HTTP/1.1 requests to let the client know that it is also available as HTTP/3.
-Sanic 同样兼容 ASGI。这意味着您可以使用您喜爱的 ASGI 服务器来运行 Sanic。现在有三大主流的 ASGI 服务器, [Daphne](http://github.com/django/daphne),[Uvicorn](https://www.uvicorn.org/),和 [Hypercorn](https://pgjones.gitlab.io/hypercorn/index.html) 。
-::: warning 警告
+---:1
+```
+$ sanic path.to.server:app --http=3 --http=1
+```
+
+```
+$ sanic path.to.server:app -3 -1
+```
+:--:1
+
+```python
+app.prepre(version=3)
+app.prepre(version=1)
+Sanic.serve()
+```
+:---
-Daphne 不支持 ASGI 中的 `lifespan` 协议,因此并不能用于 Sanic。更多详细信息请参考
-[Issue #264](https://github.com/django/daphne/issues/264)。
+Because HTTP/3 requires TLS, you cannot start a HTTP/3 server without a TLS certificate. You should [set it up yourself](http://localhost:8080/en/guide/how-to/tls.html) or use `mkcert` if in `DEBUG` mode. Currently, automatic TLS setup for HTTP/3 is not compatible with `trustme`. See [development](./development.md) for more details.
:::
-您需要参考他们的文档来找到运行 ASGI 应用的正确方式,这些启动命令大概看起来像这样:
+## ASGI
+
+Sanic 同样兼容 ASGI。 这意味着您可以使用您喜爱的 ASGI 服务器来运行 Sanic。 现在有三大主流的 ASGI 服务器, [Daphne](http://github.com/django/daphne),[Uvicorn](https://www.uvicorn.org/),和 [Hypercorn](https://pgjones.gitlab.io/hypercorn/index.html) 。
+
+Daphne 不支持 ASGI 中的 `lifespan` 协议,因此并不能用于 Sanic。 更多详细信息请参考 [Issue #264](https://github.com/django/daphne/issues/264)。 :::
+
+::: warning 警告
```
uvicorn myapp:app
hypercorn myapp:app
```
-当使用 ASGI 时,您需要关注以下几件事情:
-
-1. 当使用 Sanic 服务器,websocket 功能将使用 `websockets` 包来实现。在 ASGI 模式中,将不会使用该第三方包,因为 ASGI 服务器将会管理 websocket 链接。
+A couple things to note when using ASGI:
-2. [ASGI 生命周期协议](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) 中规定 ASGI 只支持两种服务器事件:启动和关闭。而 Sanic 则有四个事件:启动前、启动后、关闭前和关闭后。因此,在 ASGI 模式下,启动和关闭事件将连续运行,并不是根据服务器进程的实际状态来运行(因为此时是由 ASGI 服务器控制状态)。因此,最好使用 `after_server_start` 和 `before_server_stop` 。
+1. 当使用 Sanic 服务器,websocket 功能将使用 `websockets` 包来实现。 在 ASGI 模式中,将不会使用该第三方包,因为 ASGI 服务器将会管理 websocket 链接。
+2. [ASGI 生命周期协议](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) 中规定 ASGI 只支持两种服务器事件:启动和关闭。 而 Sanic 则有四个事件:启动前、启动后、关闭前和关闭后。 因此,在 ASGI 模式下,启动和关闭事件将连续运行,并不是根据服务器进程的实际状态来运行(因为此时是由 ASGI 服务器控制状态)。 因此,最好使用 `after_server_start` 和 `before_server_stop` 。
### Trio
@@ -272,50 +331,35 @@ Sanic 对使用 Trio 运行有着实验性的支持:
hypercorn -k trio myapp:app
```
+
## Gunicorn
-[Gunicorn](http://gunicorn.org/) ("Green Unicorn") 是一个基于 UNIX 操作系统的 WSGI HTTP 服务器。它是从 Ruby 的 Unicorn 项目中移植而来,采用的是 pre-fork worker 模型。
+[Gunicorn](http://gunicorn.org/) ("Green Unicorn") 是一个基于 UNIX 操作系统的 WSGI HTTP 服务器。 它是从 Ruby 的 Unicorn 项目中移植而来,采用的是 pre-fork worker 模型。
-为了使用 Gunicorn 来运行 Sanic 应用程序,您需要使用 Sanic 提供的 `sanic.worker.GunicornWorker` 类作为 Gunicorn worker-class 参数。
+当使用 ASGI 时,您需要关注以下几件事情:
```bash
gunicorn myapp:app --bind 0.0.0.0:1337 --worker-class sanic.worker.GunicornWorker
```
-如果您的应用有内存泄漏的困扰,您可以通过配置 Gunicorn 使子进程在处理了一定数量的请求后平滑重启。这种方法可以很方便得减少内存泄漏带来的影响。
+如果您的应用有内存泄漏的困扰,您可以通过配置 Gunicorn 使子进程在处理了一定数量的请求后平滑重启。 这种方法可以很方便得减少内存泄漏带来的影响。
查看 [Gunicorn 文档](http://docs.gunicorn.org/en/latest/settings.html#max-requests) 来获取更多信息。
-::: warning
-
-当通过 `gunicorn` 运行 Sanic 时,您将失去 `async/await` 带来的诸多性能优势。对于该种部署方式,请三思而后行。的确,Gunicorn 提供了很多配置选项,但它不是让 Sanic 全速运行的最佳坏境。
-
-:::
+当通过 `gunicorn` 运行 Sanic 时,您将失去 `async/await` 带来的诸多性能优势。 Weigh your considerations carefully before making this choice. 的确,Gunicorn 提供了很多配置选项,但它不是让 Sanic 全速运行的最佳坏境。 :::
## 性能方面的考虑 (Performance considerations)
----:1
-
-当部署在生产环境时,请确保 `debug` 模式处于关闭状态。
-
-:--:1
-
+当部署在生产环境时,请确保 `debug` 模式处于关闭状态。 :--:1
```python
app.run(..., debug=False)
```
-
:---
----:1
-
-如果您选择关闭了 `access_log` ,Sanic 将会全速运行。
-
-如果您的确需要请求访问日志,又想获得更好的性能,可以考虑使用 [Nginx](./nginx.md) 作为代理,让 Nginx 来处理您的访问日志。这种方式要比用 Python 处理快得多得多。
-
-:--:1
+::: warning
+如果您的确需要请求访问日志,又想获得更好的性能,可以考虑使用 [Nginx](./nginx.md) 作为代理,让 Nginx 来处理您的访问日志。 这种方式要比用 Python 处理快得多得多。 :--:1
```python
app.run(..., access_log=False)
```
-
:---
From 86885726b1f098af01fbd8f99728b3db048ff9f5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:22 +0300
Subject: [PATCH 128/776] New translations running.md (Portuguese, Brazilian)
---
src/pt/guide/deployment/running.md | 319 +++++++++++++++++++++++++++++
1 file changed, 319 insertions(+)
create mode 100644 src/pt/guide/deployment/running.md
diff --git a/src/pt/guide/deployment/running.md b/src/pt/guide/deployment/running.md
new file mode 100644
index 0000000000..51a6a5c2a0
--- /dev/null
+++ b/src/pt/guide/deployment/running.md
@@ -0,0 +1,319 @@
+# Running Sanic
+
+Sanic ships with its own internal web server. Under most circumstances, this is the preferred method for deployment. In addition, you can also deploy Sanic as an ASGI app bundled with an ASGI-able web server, or using gunicorn.
+
+## Sanic Server
+
+After defining an instance of `sanic.Sanic`, we can call the run method with the following keyword arguments:
+
+| Parameter | Default | Description |
+|:--------------:|:--------------:|:----------------------------------------------------------------------------------------- |
+| **host** | `"127.0.0.1"` | Address to host the server on. |
+| **port** | `8000` | Port to host the server on. |
+| **unix** | `None` | Unix socket name to host the server on (instead of TCP). |
+| **debug** | `False` | Enables debug output (slows server). |
+| **ssl** | `None` | SSLContext for SSL encryption of worker(s). |
+| **sock** | `None` | Socket for the server to accept connections from. |
+| **workers** | `1` | Number of worker processes to spawn. |
+| **loop** | `None` | An asyncio-compatible event loop. If none is specified, Sanic creates its own event loop. |
+| **protocol** | `HttpProtocol` | Subclass of asyncio.protocol. |
+| **access_log** | `True` | Enables log on handling requests (significantly slows server). |
+
+---:1
+
+In the above example, we decided to turn off the access log in order to increase performance.
+
+:--:1
+
+```python
+# server.py
+app = Sanic("My App")
+app.run(host='0.0.0.0', port=1337, access_log=False)
+```
+
+:---
+
+---:1
+
+Now, just execute the python script that has `app.run(...)`
+
+:--:1
+
+```bash
+python server.py
+```
+
+:---
+
+### Workers
+
+---:1 By default, Sanic listens in the main process using only one CPU core. To crank up the juice, just specify the number of workers in the run arguments. :--:1
+```python
+app.run(host='0.0.0.0', port=1337, workers=4)
+```
+:---
+
+Sanic will automatically spin up multiple processes and route traffic between them. We recommend as many workers as you have available processors.
+
+---:1 The easiest way to get the maximum CPU performance is to use the `fast` option. This will automatically run the maximum number of workers given the system constraints. :--:1
+```python
+app.run(host='0.0.0.0', port=1337, fast=True)
+```
+```python
+$ sanic server:app --host=0.0.0.0 --port=1337 --fast
+```
+:---
+
+In older versions of Sanic without the `fast` option, a common way to check this on Linux based operating systems:
+
+```
+$ nproc
+```
+
+Or, let Python do it:
+
+```python
+import multiprocessing
+workers = multiprocessing.cpu_count()
+app.run(..., workers=workers)
+```
+
+### Running via command
+
+#### Sanic CLI
+
+---:1 Sanic also has a simple CLI to launch via command line.
+
+For example, if you initialized Sanic as app in a file named `server.py`, you could run the server like so: :--:1
+```bash
+sanic server.app --host=0.0.0.0 --port=1337 --workers=4
+```
+
+:---
+
+Use `sanic --help` to see all the options.
+
+```text
+$ sanic --help
+usage: sanic [-h] [--version] [--factory] [-s] [-H HOST] [-p PORT] [-u UNIX] [--cert CERT] [--key KEY] [--tls DIR] [--tls-strict-host]
+ [-w WORKERS | --fast] [--access-logs | --no-access-logs] [--debug] [-d] [-r] [-R PATH] [--motd | --no-motd] [-v]
+ [--noisy-exceptions | --no-noisy-exceptions]
+ module
+
+ ▄███ █████ ██ ▄█▄ ██ █ █ ▄██████████
+ ██ █ █ █ ██ █ █ ██
+ ▀███████ ███▄ ▀ █ █ ██ ▄ █ ██
+ ██ █████████ █ ██ █ █ ▄▄
+ ████ ████████▀ █ █ █ ██ █ ▀██ ███████
+
+ To start running a Sanic application, provide a path to the module, where
+ app is a Sanic() instance:
+
+ $ sanic path.to.server:app
+
+ Or, a path to a callable that returns a Sanic() instance:
+
+ $ sanic path.to.factory:create_app --factory
+
+ Or, a path to a directory to run as a simple HTTP server:
+
+ $ sanic ./path/to/static --simple
+
+Required
+========
+ Positional:
+ module Path to your Sanic app. Example: path.to.server:app
+ If running a Simple Server, path to directory to serve. Example: ./
+
+Optional
+========
+ General:
+ -h, --help show this help message and exit
+ --version show program's version number and exit
+
+ Application:
+ --factory Treat app as an application factory, i.e. a () -> callable
+ -s, --simple Run Sanic as a Simple Server, and serve the contents of a directory
+ (module arg should be a path)
+
+ Socket binding:
+ -H HOST, --host HOST Host address [default 127.0.0.1]
+ -p PORT, --port PORT Port to serve on [default 8000]
+ -u UNIX, --unix UNIX location of unix socket
+
+ TLS certificate:
+ --cert CERT Location of fullchain.pem, bundle.crt or equivalent
+ --key KEY Location of privkey.pem or equivalent .key file
+ --tls DIR TLS certificate folder with fullchain.pem and privkey.pem
+ May be specified multiple times to choose multiple certificates
+ --tls-strict-host Only allow clients that send an SNI matching server certs
+
+ Worker:
+ -w WORKERS, --workers WORKERS Number of worker processes [default 1]
+ --fast Set the number of workers to max allowed
+ --access-logs Display access logs
+ --no-access-logs No display access logs
+
+ Development:
+ --debug Run the server in debug mode
+ -d, --dev Currently is an alias for --debug. But starting in v22.3,
+ --debug will no longer automatically trigger auto_restart.
+ However, --dev will continue, effectively making it the
+ same as debug + auto_reload.
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+
+ Output:
+ --motd Show the startup display
+ --no-motd No show the startup display
+ -v, --verbosity Control logging noise, eg. -vv or --verbosity=2 [default 0]
+ --noisy-exceptions Output stack traces for all exceptions
+ --no-noisy-exceptions No output stack traces for all exceptions
+```
+
+#### As a module
+
+---:1 It can also be called directly as a module. :--:1
+```bash
+python -m sanic server.app --host=0.0.0.0 --port=1337 --workers=4
+```
+:---
+
+::: tip FYI With either method (CLI or module), you shoud *not* invoke `app.run()` in your Python file. If you do, make sure you wrap it so that it only executes when directly run by the interpreter.
+
+```python
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=1337, workers=4)
+```
+:::
+
+
+### Sanic Simple Server
+
+---:1 Sometimes you just have a directory of static files that need to be served. This especially can be handy for quickly standing up a localhost server. Sanic ships with a Simple Server, where you only need to point it at a directory. :--:1
+```bash
+sanic ./path/to/dir --simple
+```
+:---
+
+---:1 This could also be paired with auto-reloading. :--:1
+```bash
+sanic ./path/to/dir --simple --reload --reload-dir=./path/to/dir
+```
+:---
+
+
+::: new NEW in v22.6
+
+### HTTP/3
+
+
+Sanic server offers HTTP/3 support using [aioquic](https://github.com/aiortc/aioquic). This **must** be installed to use HTTP/3:
+
+```
+pip install sanic aioquic
+```
+
+```
+pip install sanic[http3]
+```
+
+To start HTTP/3, you must explicitly request it when running your application.
+
+---:1
+```
+$ sanic path.to.server:app --http=3
+```
+
+```
+$ sanic path.to.server:app -3
+```
+:--:1
+
+```python
+app.run(version=3)
+```
+:---
+
+To run both an HTTP/3 and HTTP/1.1 server simultaneously, you can use [application multi-serve](http://localhost:8080/en/guide/release-notes/v22.3.html#application-multi-serve) introduced in v22.3. This will automatically add an [Alt-Svc](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc) header to your HTTP/1.1 requests to let the client know that it is also available as HTTP/3.
+
+
+---:1
+```
+$ sanic path.to.server:app --http=3 --http=1
+```
+
+```
+$ sanic path.to.server:app -3 -1
+```
+:--:1
+
+```python
+app.prepre(version=3)
+app.prepre(version=1)
+Sanic.serve()
+```
+:---
+
+Because HTTP/3 requires TLS, you cannot start a HTTP/3 server without a TLS certificate. You should [set it up yourself](http://localhost:8080/en/guide/how-to/tls.html) or use `mkcert` if in `DEBUG` mode. Currently, automatic TLS setup for HTTP/3 is not compatible with `trustme`. See [development](./development.md) for more details.
+
+:::
+
+## ASGI
+
+Sanic is also ASGI-compliant. This means you can use your preferred ASGI webserver to run Sanic. The three main implementations of ASGI are [Daphne](http://github.com/django/daphne), [Uvicorn](https://www.uvicorn.org/), and [Hypercorn](https://pgjones.gitlab.io/hypercorn/index.html).
+
+::: warning Daphne does not support the ASGI `lifespan` protocol, and therefore cannot be used to run Sanic. See [Issue #264](https://github.com/django/daphne/issues/264) for more details. :::
+
+Follow their documentation for the proper way to run them, but it should look something like:
+
+```
+uvicorn myapp:app
+hypercorn myapp:app
+```
+
+A couple things to note when using ASGI:
+
+1. When using the Sanic webserver, websockets will run using the `websockets` package. In ASGI mode, there is no need for this package since websockets are managed in the ASGI server.
+2. The ASGI lifespan protocol , supports only two server events: startup and shutdown. Sanic has four: before startup, after startup, before shutdown, and after shutdown. Therefore, in ASGI mode, the startup and shutdown events will run consecutively and not actually around the server process beginning and ending (since that is now controlled by the ASGI server). Therefore, it is best to use `after_server_start` and `before_server_stop`.
+
+### Trio
+
+Sanic has experimental support for running on Trio with:
+
+```
+hypercorn -k trio myapp:app
+```
+
+
+## Gunicorn
+
+[Gunicorn](http://gunicorn.org/) ("Green Unicorn") is a WSGI HTTP Server for UNIX based operating systems. It is a pre-fork worker model ported from Ruby’s Unicorn project.
+
+In order to run Sanic application with Gunicorn, you need to use the special `sanic.worker.GunicornWorker` for Gunicorn worker-class argument:
+
+```bash
+gunicorn myapp:app --bind 0.0.0.0:1337 --worker-class sanic.worker.GunicornWorker
+```
+
+If your application suffers from memory leaks, you can configure Gunicorn to gracefully restart a worker after it has processed a given number of requests. This can be a convenient way to help limit the effects of the memory leak.
+
+See the [Gunicorn Docs](http://docs.gunicorn.org/en/latest/settings.html#max-requests) for more information.
+
+::: warning When running Sanic via `gunicorn`, you are losing out on a lot of the performance benefits of `async`/`await`. Weigh your considerations carefully before making this choice. Gunicorn does provide a lot of configuration options, but it is not the best choice for getting Sanic to run at its fastest. :::
+
+## Performance considerations
+
+---:1 When running in production, make sure you turn off `debug`. :--:1
+```python
+app.run(..., debug=False)
+```
+:---
+
+---:1 Sanic will also perform fastest if you turn off `access_log`.
+
+If you still require access logs, but want to enjoy this performance boost, consider using [Nginx as a proxy](./nginx.md), and letting that handle your access logging. It will be much faster than anything Python can handle. :--:1
+```python
+app.run(..., access_log=False)
+```
+:---
From d2c2f24bddf8bfe40367849473c2403ba1c29aa7 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:23 +0300
Subject: [PATCH 129/776] New translations db.md (Korean)
---
src/ko/guide/how-to/db.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/db.md
diff --git a/src/ko/guide/how-to/db.md b/src/ko/guide/how-to/db.md
new file mode 100644
index 0000000000..60ca822eac
--- /dev/null
+++ b/src/ko/guide/how-to/db.md
@@ -0,0 +1 @@
+connecting to data sources
From 4175b8f129070a1dcf1193e10f13945cf8689e5d Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:24 +0300
Subject: [PATCH 130/776] New translations toc.md (Portuguese, Brazilian)
---
src/pt/guide/how-to/toc.md | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 src/pt/guide/how-to/toc.md
diff --git a/src/pt/guide/how-to/toc.md b/src/pt/guide/how-to/toc.md
new file mode 100644
index 0000000000..d10bda1de6
--- /dev/null
+++ b/src/pt/guide/how-to/toc.md
@@ -0,0 +1,21 @@
+# Table of Contents
+
+We have compiled fully working examples to answer common questions and user cases. For the most part, the examples are as minimal as possible, but should be complete and runnable solutions.
+
+| Page | How do I ... |
+|:------------------------------------- |:------------------------------------------------------------------- |
+| [Application mounting](./mounting.md) | ... mount my application at some path above the root? |
+| [Authentication](./authentication.md) | ... control authentication and authorization? |
+| [Autodiscovery](./autodiscovery.md) | ... autodiscover the components I am using to build my application? |
+| [CORS](./cors.md) | ... configure my application for CORS? |
+| CSRF | *Coming soon* |
+| Databases | *Coming soon* |
+| IPv6 | *Coming soon* |
+| Request ID Logging | *Coming soon* |
+| Request validation | *Coming soon* |
+| Serialization | *Coming soon* |
+| Server Sent Events | *Coming soon* |
+| [ORM](./orm) | ... use an ORM with Sanic? |
+| Task queues | *Coming soon* |
+| [TLS/SSL/HTTPS](./tls.md) | ... run Sanic via HTTPS? ... redirect HTTP to HTTPS? |
+| Websocket feeds | *Coming soon* |
From bcf062e2428a07a8d42ca87c4d40becb7a72a659 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:26 +0300
Subject: [PATCH 131/776] New translations task-queue.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/task-queue.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/task-queue.md
diff --git a/src/pt/guide/how-to/task-queue.md b/src/pt/guide/how-to/task-queue.md
new file mode 100644
index 0000000000..c5ee7c54a3
--- /dev/null
+++ b/src/pt/guide/how-to/task-queue.md
@@ -0,0 +1 @@
+task queue
From da7b5f013adb7a2c9a87bdca5608305d19896695 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:27 +0300
Subject: [PATCH 132/776] New translations tls.md (Japanese)
---
src/ja/guide/how-to/tls.md | 42 +++++++++++++++-----------------------
1 file changed, 17 insertions(+), 25 deletions(-)
diff --git a/src/ja/guide/how-to/tls.md b/src/ja/guide/how-to/tls.md
index 21b9a3acca..2f36179066 100644
--- a/src/ja/guide/how-to/tls.md
+++ b/src/ja/guide/how-to/tls.md
@@ -6,8 +6,7 @@ TLS証明書がない場合は、[このページの最後を参照](./tls.md#ge
## 単一ドメイン、単一証明書
----:1
-Sanicに証明書ファイルを自動的に読み込ませます。証明書ファイルは、指定されたフォルダーに `fullchain.pem` と `privkey.pem` という名前で格納する必要があります。
+---:1 Let Sanic automatically load your certificate files, which need to be named `fullchain.pem` and `privkey.pem` in the given folder:
:--:1
```sh
@@ -18,12 +17,10 @@ sudo sanic myserver:app -H :: -p 443 \
app.run("::", 443, ssl="/etc/letsencrypt/live/example.com/")
```
:---
-
----:1
-または、certとkeyのファイル名を別々に辞書として渡すことも可能です。
-さらに、鍵が暗号化されている場合は `password` を追加することができ、パスワード以外のすべてのフィールドは `request.conn_info.cert` に渡されます。
-:--:1
+---:1 または、certとkeyのファイル名を別々に辞書として渡すことも可能です。
+
+さらに、鍵が暗号化されている場合は `password` を追加することができ、パスワード以外のすべてのフィールドは `request.conn_info.cert` に渡されます。 :--:1 :--:1
```python
ssl = {
"cert": "/path/to/fullchain.pem",
@@ -34,9 +31,7 @@ app.run(host="0.0.0.0", port=8443, ssl=ssl)
```
:---
----:1
-また、どの暗号アルゴリズムが許可されるかなどの詳細を完全に制御したい場合は、[`ssl.SSLContext`](https://docs.python.org/3/library/ssl.html)を渡すこともできます。デフォルトでは、Sanicは安全なアルゴリズムのみを許可しており、非常に古いデバイスからのアクセスを制限する可能性があります。
-:--:1
+---:1 また、どの暗号アルゴリズムが許可されるかなどの詳細を完全に制御したい場合は、[`ssl.SSLContext`](https://docs.python.org/3/library/ssl.html)を渡すこともできます。 デフォルトでは、Sanicは安全なアルゴリズムのみを許可しており、非常に古いデバイスからのアクセスを制限する可能性があります。 :--:1 :--:1
```python
import ssl
@@ -50,16 +45,9 @@ app.run(host="0.0.0.0", port=8443, ssl=context)
## 複数のドメインで別々の証明書を使用
----:1
-複数の証明書のリストが提供されることがあり、その場合、Sanicはユーザーが接続しているホスト名に一致する証明書を選択する。これはTLSハンドシェイクの初期に発生するため、Sanicはまだクライアントにパケットを送信していません。
-
-クライアントがSNI(サーバー名表示)を送信しない場合、クライアントブラウザ上では名前の不一致によるTLSエラーで失敗する可能性が高いにもかかわらず、リストの最初の証明書が使用されることになります。このフォールバックを防ぎ、既知のホスト名を持たないクライアントを直ちに切断するには、リストの最初のエントリとして `None` を追加してください。`tls-strict-host` は同等のCLIオプションです。
-
-::: tip
-また、適切なDNS名ではなくIPアドレスに接続する人に対して、あなたの証明書、真のホスト名、サイトのコンテンツを明らかにしたくない場合は、単一の証明書の前に`None`を使用することができます。
-:::
+---:1 複数の証明書のリストが提供されることがあり、その場合、Sanicはユーザーが接続しているホスト名に一致する証明書を選択する。 これはTLSハンドシェイクの初期に発生するため、Sanicはまだクライアントにパケットを送信していません。
-:--:1
+クライアントがSNI(サーバー名表示)を送信しない場合、クライアントブラウザ上では名前の不一致によるTLSエラーで失敗する可能性が高いにもかかわらず、リストの最初の証明書が使用されることになります。 このフォールバックを防ぎ、既知のホスト名を持たないクライアントを直ちに切断するには、リストの最初のエントリとして `None` を追加してください。 `tls-strict-host` は同等のCLIオプションです。 ---:1
```python
ssl = ["certs/example.com/", "certs/bigcorp.test/"]
app.run(host="0.0.0.0", port=8443, ssl=ssl)
@@ -72,8 +60,10 @@ sanic myserver:app
```
:---
----:1
-リスト上で辞書を使用することができます。これにより、証明書がどのドメインに一致するかを指定することもできますが、証明書自体に存在する名前をここから制御することはできません。名前が指定されない場合、証明書自体の名前が使用されます。
+::: tip また、適切なDNS名ではなくIPアドレスに接続する人に対して、あなたの証明書、真のホスト名、サイトのコンテンツを明らかにしたくない場合は、単一の証明書の前に`None`を使用することができます。 :::
+:::
+
+---:1 リスト上で辞書を使用することができます。 これにより、証明書がどのドメインに一致するかを指定することもできますが、証明書自体に存在する名前をここから制御することはできません。 名前が指定されない場合、証明書自体の名前が使用されます。
メインドメイン **example.com** と **bigcorp.test** のサブドメインへの接続のみを許可する場合。
@@ -97,11 +87,12 @@ app.run(host="0.0.0.0", port=8443, ssl=ssl)
* `.cert` - 現在アクティブな証明書の証明書情報およびdictフィールド (dict)
* `.server_name` - クライアントが送信した SNI (文字列、空白の場合もある)
-すべての `conn_info` フィールドは、時間経過とともに多くのリクエストが発生する可能性のある接続ごとにあることに注意してください。サーバーの前でプロキシを使用している場合、同じパイプにあるこれらのリクエストは異なるユーザーからのものである可能性さえあります。
+すべての `conn_info` フィールドは、時間経過とともに多くのリクエストが発生する可能性のある接続ごとにあることに注意してください。 サーバーの前でプロキシを使用している場合、同じパイプにあるこれらのリクエストは異なるユーザーからのものである可能性さえあります。
## HTTP を HTTPS にリダイレクトし、証明書のリクエストは HTTP のままにする
通常の HTTPS サーバに加えて、リダイレクト用のサーバ `http_redir.py` を起動します。
+
```python
from sanic import Sanic, exceptions, response
@@ -118,7 +109,8 @@ def redirect_everything_else(request, exception):
return response.text("Bad Request. Please use HTTPS!", status=400)
```
-HTTPS サーバーとは別の systemd ユニットとしてセットアップするのがベストです。HTTPS サーバはまだ実行できませんが、証明書を要求する間は HTTP を実行する必要があるかもしれません。IPv4 と IPv6 で起動します。
+HTTPS サーバーとは別の systemd ユニットとしてセットアップするのがベストです。 HTTPS サーバはまだ実行できませんが、証明書を要求する間は HTTP を実行する必要があるかもしれません。 IPv4 と IPv6 で起動します。
+
```
sanic http_redir:app -H 0.0.0.0 -p 80
sanic http_redir:app -H :: -p 80
@@ -155,7 +147,7 @@ async def runner(app, app_server):
## ドメイン名用の証明書を取得する
-[Let's Encrypt](https://letsencrypt.org/)から無料で証明書を取得することができます。パッケージマネージャで[certbot](https://certbot.eff.org/)をインストールし、証明書を要求してください。
+[Let's Encrypt](https://letsencrypt.org/)から無料で証明書を取得することができます。 パッケージマネージャで[certbot](https://certbot.eff.org/)をインストールし、証明書を要求してください。
```sh
sudo certbot certonly --key-type ecdsa --preferred-chain "ISRG Root X1" -d example.com -d www.example.com
@@ -163,4 +155,4 @@ sudo certbot certonly --key-type ecdsa --preferred-chain "ISRG Root X1" -d examp
複数のドメイン名を `-d` 引数で追加することができ、すべて1つの証明書に保存され、ここでリストした **最初のドメイン** に従って `/etc/letsencrypt/live/example.com/` に保存されます。
-鍵の種類と優先するチェーンのオプションは、最小限のサイズの証明書ファイルを取得するために必要で、サーバーを*できるだけ速く*動作させるために不可欠なものです。Let's Encrypt が新しい EC チェーンをすべての主要なブラウザで信頼されるようになるまで、チェーンにはまだ 1 つの RSA 証明書が含まれます(おそらく 2023 年頃)。
+鍵の種類と優先するチェーンのオプションは、最小限のサイズの証明書ファイルを取得するために必要で、サーバーを*できるだけ速く*動作させるために不可欠なものです。 Let's Encrypt が新しい EC チェーンをすべての主要なブラウザで信頼されるようになるまで、チェーンにはまだ 1 つの RSA 証明書が含まれます(おそらく 2023 年頃)。
From 7732a49d2c5e2877f4f6d9005bacada4e55850cc Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:28 +0300
Subject: [PATCH 133/776] New translations tls.md (Korean)
---
src/ko/guide/how-to/tls.md | 158 +++++++++++++++++++++++++++++++++++++
1 file changed, 158 insertions(+)
create mode 100644 src/ko/guide/how-to/tls.md
diff --git a/src/ko/guide/how-to/tls.md b/src/ko/guide/how-to/tls.md
new file mode 100644
index 0000000000..5299134cb1
--- /dev/null
+++ b/src/ko/guide/how-to/tls.md
@@ -0,0 +1,158 @@
+# TLS/SSL/HTTPS
+
+> How do I run Sanic via HTTPS?
+
+If you do not have TLS certificates yet, [see the end of this page](./tls.md#get-certificates-for-your-domain-names).
+
+## Single domain and single certificate
+
+---:1 Let Sanic automatically load your certificate files, which need to be named `fullchain.pem` and `privkey.pem` in the given folder:
+
+:--:1
+```sh
+sudo sanic myserver:app -H :: -p 443 \
+ --tls /etc/letsencrypt/live/example.com/
+```
+```python
+app.run("::", 443, ssl="/etc/letsencrypt/live/example.com/")
+```
+:---
+
+---:1 Or, you can pass cert and key filenames separately as a dictionary:
+
+Additionally, `password` may be added if the key is encrypted, all fields except for the password are passed to `request.conn_info.cert`. :--:1
+```python
+ssl = {
+ "cert": "/path/to/fullchain.pem",
+ "key": "/path/to/privkey.pem",
+ "password": "for encrypted privkey file", # Optional
+}
+app.run(host="0.0.0.0", port=8443, ssl=ssl)
+```
+:---
+
+---:1 Alternatively, [`ssl.SSLContext`](https://docs.python.org/3/library/ssl.html) may be passed, if you need full control over details such as which crypto algorithms are permitted. By default Sanic only allows secure algorithms, which may restrict access from very old devices. :--:1
+```python
+import ssl
+
+context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
+context.load_cert_chain("certs/fullchain.pem", "certs/privkey.pem")
+
+app.run(host="0.0.0.0", port=8443, ssl=context)
+```
+:---
+
+
+## Multiple domains with separate certificates
+
+---:1 A list of multiple certificates may be provided, in which case Sanic chooses the one matching the hostname the user is connecting to. This occurs so early in the TLS handshake that Sanic has not sent any packets to the client yet.
+
+If the client sends no SNI (Server Name Indication), the first certificate on the list will be used even though on the client browser it will likely fail with a TLS error due to name mismatch. To prevent this fallback and to cause immediate disconnection of clients without a known hostname, add `None` as the first entry on the list. `--tls-strict-host` is the equivalent CLI option. :--:1
+```python
+ssl = ["certs/example.com/", "certs/bigcorp.test/"]
+app.run(host="0.0.0.0", port=8443, ssl=ssl)
+```
+```sh
+sanic myserver:app
+ --tls certs/example.com/
+ --tls certs/bigcorp.test/
+ --tls-strict-host
+```
+:---
+
+::: tip You may also use `None` in front of a single certificate if you do not wish to reveal your certificate, true hostname or site content to anyone connecting to the IP address instead of the proper DNS name. :::
+
+---:1 Dictionaries can be used on the list. This allows also specifying which domains a certificate matches to, although the names present on the certificate itself cannot be controlled from here. If names are not specified, the names from the certificate itself are used.
+
+To only allow connections to the main domain **example.com** and only to subdomains of **bigcorp.test**:
+
+:--:1
+```python
+ssl = [
+ None, # No fallback if names do not match!
+ {
+ "cert": "certs/example.com/fullchain.pem",
+ "key": "certs/example.com/privkey.pem",
+ "names": ["example.com", "*.bigcorp.test"],
+ }
+]
+app.run(host="0.0.0.0", port=8443, ssl=ssl)
+```
+:---
+
+## Accessing TLS information in handlers via `request.conn_info` fields
+
+* `.ssl` - is the connection secure (bool)
+* `.cert` - certificate info and dict fields of the currently active cert (dict)
+* `.server_name` - the SNI sent by the client (str, may be empty)
+
+Do note that all `conn_info` fields are per connection, where there may be many requests over time. If a proxy is used in front of your server, these requests on the same pipe may even come from different users.
+
+## Redirect HTTP to HTTPS, with certificate requests still over HTTP
+
+In addition to your normal server(s) running HTTPS, run another server for redirection, `http_redir.py`:
+
+```python
+from sanic import Sanic, exceptions, response
+
+app = Sanic("http_redir")
+
+# Serve ACME/certbot files without HTTPS, for certificate renewals
+app.static("/.well-known", "/var/www/.well-known", resource_type="dir")
+
+@app.exception(exceptions.NotFound, exceptions.MethodNotSupported)
+def redirect_everything_else(request, exception):
+ server, path = request.server_name, request.path
+ if server and path.startswith("/"):
+ return response.redirect(f"https://{server}{path}", status=308)
+ return response.text("Bad Request. Please use HTTPS!", status=400)
+```
+
+It is best to setup this as a systemd unit separate of your HTTPS servers. You may need to run HTTP while initially requesting your certificates, while you cannot run the HTTPS server yet. Start for IPv4 and IPv6:
+
+```
+sanic http_redir:app -H 0.0.0.0 -p 80
+sanic http_redir:app -H :: -p 80
+```
+
+Alternatively, it is possible to run the HTTP redirect application from the main application:
+
+```python
+# app == Your main application
+# redirect == Your http_redir application
+@app.before_server_start
+async def start(app, _):
+ app.ctx.redirect = await redirect.create_server(
+ port=80, return_asyncio_server=True
+ )
+ app.add_task(runner(redirect, app.ctx.redirect))
+
+
+@app.before_server_stop
+async def stop(app, _):
+ await app.ctx.redirect.close()
+
+
+async def runner(app, app_server):
+ app.is_running = True
+ try:
+ app.signalize()
+ app.finalize()
+ app.state.is_started = True
+ await app_server.serve_forever()
+ finally:
+ app.is_running = False
+ app.is_stopping = True
+```
+
+## Get certificates for your domain names
+
+You can get free certificates from [Let's Encrypt](https://letsencrypt.org/). Install [certbot](https://certbot.eff.org/) via your package manager, and request a certificate:
+
+```sh
+sudo certbot certonly --key-type ecdsa --preferred-chain "ISRG Root X1" -d example.com -d www.example.com
+```
+
+Multiple domain names may be added by further `-d` arguments, all stored into a single certificate which gets saved to `/etc/letsencrypt/live/example.com/` as per **the first domain** that you list here.
+
+The key type and preferred chain options are necessary for getting a minimal size certificate file, essential for making your server run as *fast* as possible. The chain will still contain one RSA certificate until when Let's Encrypt gets their new EC chain trusted in all major browsers, possibly around 2023.
From aaa6c95a09de93e9e597dcd4860b50fffcdef45b Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:29 +0300
Subject: [PATCH 134/776] New translations tls.md (Chinese Simplified)
---
src/zh/guide/how-to/tls.md | 76 ++++++++++----------------------------
1 file changed, 20 insertions(+), 56 deletions(-)
diff --git a/src/zh/guide/how-to/tls.md b/src/zh/guide/how-to/tls.md
index d5bce7611e..7164ece319 100644
--- a/src/zh/guide/how-to/tls.md
+++ b/src/zh/guide/how-to/tls.md
@@ -8,29 +8,19 @@
---:1
-如果您想让 Sanic 自动加载您的证书文件,您需要将证书文件在指定的文件夹中命名为 `fullchain.pem` 和 `privkey.pem`:
-
:--:1
-
```sh
sudo sanic myserver:app -H :: -p 443 \
--tls /etc/letsencrypt/live/example.com/
```
-
```python
app.run("::", 443, ssl="/etc/letsencrypt/live/example.com/")
```
-
:---
----:1
-
或者您可以将证书文件路径和秘钥文件路径作为字典的值传入到运行配置中:
-除此之外,如果您的秘钥文件被加密,您还可以选择传入 `password`,除了 `password` 之外的所有参数都将被传递给 `request.conn_info.cert`。
-
-:--:1
-
+除此之外,如果您的秘钥文件被加密,您还可以选择传入 `password`,除了 `password` 之外的所有参数都将被传递给 `request.conn_info.cert`。 :--:1
```python
ssl = {
"cert": "/path/to/fullchain.pem",
@@ -39,15 +29,9 @@ ssl = {
}
app.run(host="0.0.0.0", port=8443, ssl=ssl)
```
-
:---
----:1
-
-或者,如果您需要完全控制诸如允许哪些加密算法之类的细节,可以通过[`ssl` 模块](https://docs.python.org/3/library/ssl.html)。默认情况下,Sanic 只允许安全算法,这可能会限制来自非常旧的设备的访问。
-
-:--:1
-
+或者,如果您需要完全控制诸如允许哪些加密算法之类的细节,可以通过[`ssl` 模块](https://docs.python.org/3/library/ssl.html)。 默认情况下,Sanic 只允许安全算法,这可能会限制来自非常旧的设备的访问。 :--:1
```python
import ssl
@@ -60,53 +44,37 @@ context.load_cert_chain(
app.run(host="0.0.0.0", port=8443, ssl=context)
```
-
:---
-## 具有多个证书的域名(Multiple domains with separate certificates)
-
----:1
-有些时候,一个域名可能提供了多种证书,在这种情况下,Sanic 会主动选择和客户端相匹配的证书。该阶段处于 TLS 握手阶段,在该阶段中 Sanic 不会向客户端发送任何数据包。
-
-如果客户端没有发送 SNI(服务器名称指示),将使用证书列表中的第一个证书,即使在客户端浏览器上它可能会由于名称不匹配而失败,并出现 TLS 错误。为了防止这种回退并使没有已知主机名的客户端立即断开连接,请在列表中添加 `None` 作为第一个条目。
+## 具有多个证书的域名(Multiple domains with separate certificates)
-在 CLI 参数中,`-tls-strict-host` 是等效的选项。
-
-:--:1
+有些时候,一个域名可能提供了多种证书,在这种情况下,Sanic 会主动选择和客户端相匹配的证书。 该阶段处于 TLS 握手阶段,在该阶段中 Sanic 不会向客户端发送任何数据包。
+如果客户端没有发送 SNI(服务器名称指示),将使用证书列表中的第一个证书,即使在客户端浏览器上它可能会由于名称不匹配而失败,并出现 TLS 错误。 为了防止这种回退并使没有已知主机名的客户端立即断开连接,请在列表中添加 `None` 作为第一个条目。 在 CLI 参数中,`-tls-strict-host` 是等效的选项。 :--:1
```python
ssl = ["certs/example.com/", "certs/bigcorp.test/"]
app.run(host="0.0.0.0", port=8443, ssl=ssl)
```
-
```sh
sanic myserver:app
--tls certs/example.com/
--tls certs/bigcorp.test/
--tls-strict-host
```
-
:---
-::: tip 小提示
-
-如果您不希望将您的证书、真实主机名或网站内容透露给任何连接到该 IP 地址的人,而不是正确的 DNS 名称,您也可以在单个证书前面使用 `None`。
+如果您不希望将您的证书、真实主机名或网站内容透露给任何连接到该 IP 地址的人,而不是正确的 DNS 名称,您也可以在单个证书前面使用 `None`。 :::
-:::
+单子上可以用字典。 这也允许指定证书匹配的域,尽管不能从这里控制证书上的名称。 如果未指定名称,则使用证书本身的名称。
---:1
-单子上可以用字典。这也允许指定证书匹配的域,尽管不能从这里控制证书上的名称。如果未指定名称,则使用证书本身的名称。
-
-字典也可以的用于证书列表中,您可以通过 `names` 来指定证书需要使用的域。这并不能控制证书上对应的域,只是做了一层额外的控制。如果您未指定证书要使用的域,则将使用证书本身对应的域。
-
-只允许连接到主域 **example.com** 和 **bigcorp.test** 的子域示例:
-
:--:1
-
```python
ssl = [
+ None, # No fallback if names do not match!
+ ssl = [
None, # No fallback if names do not match!
{
"cert": "certs/example.com/fullchain.pem",
@@ -116,20 +84,19 @@ ssl = [
]
app.run(host="0.0.0.0", port=8443, ssl=ssl)
```
-
:---
## 通过 `request.conn_info` 访问 TLS 信息(Accessing TLS information in handlers via `request.conn_info` fields)
-- `.ssl` - 连接是否安全(布尔类型)
-- `.cert` - 当前使用的证书以及证书相关信息(字典类型)
-- `.server_name` - 客户端发送的 SNI 类型信息(字符类型,可能为空)
+* `.ssl` - 连接是否安全(布尔类型)
+* `.cert` - 当前使用的证书以及证书相关信息(字典类型)
+* `.server_name` - 客户端发送的 SNI 类型信息(字符类型,可能为空)
-请注意,所有 `conn_info` 字段都是针对每个连接的,其中可能会有许多请求。如果您在服务器前面使用了代理,那么这些请求虽然信息相同,但很有可能来自不同的用户。
+请注意,所有 `conn_info` 字段都是针对每个连接的,其中可能会有许多请求。 如果您在服务器前面使用了代理,那么这些请求虽然信息相同,但很有可能来自不同的用户。
## 将证书请求之外的 HTTP 重定向到 HTTPS(Redirect HTTP to HTTPS, with certificate requests still over HTTP)
-除了需要运行一个以 HTTPS 启动的应用程序之外,您还需要额外的启动一个额外的应用程序用于重定向:
+In addition to your normal server(s) running HTTPS, run another server for redirection, `http_redir.py`:
```python
from sanic import Sanic, exceptions, response
@@ -144,17 +111,17 @@ def redirect_everything_else(request, exception):
server, path = request.server_name, request.path
if server and path.startswith("/"):
return response.redirect(f"https://{server}{path}", status=308)
- return response.text("Bad Request. Please use HTTPS!", status=400)
+ return response.text("Bad Request. Please use HTTPS!", status=400) Please use HTTPS!", status=400)
```
-最好通过 systemd 将您的转发应用程序注册为独立于 HTTPS 应用程序的服务。在请求证书时,会将请求发送到到您的 HTTP 服务上,此时 HTTPS 服务并未工作。IPv4 和 IPv6 的启动方式如下:
+最好通过 systemd 将您的转发应用程序注册为独立于 HTTPS 应用程序的服务。 在请求证书时,会将请求发送到到您的 HTTP 服务上,此时 HTTPS 服务并未工作。 IPv4 和 IPv6 的启动方式如下:
```
sanic http_redir:app -H 0.0.0.0 -p 80
sanic http_redir:app -H :: -p 80
```
-当然,您也可以在 HTTPS 应用程序上运行 HTTP 重定向服务。
+::: tip 小提示
```python
# app == Your main application
@@ -186,15 +153,12 @@ async def runner(app, app_server):
## 为您的域名获取证书(Get certificates for your domain names)
-您可以通过 [Let's Encrypt](https://letsencrypt.org/) 来获取免费的证书。您可以通过包管理器来安装 [certbot](https://certbot.eff.org/) 来请求创建一个证书:
+您可以通过 [Let's Encrypt](https://letsencrypt.org/) 来获取免费的证书。 您可以通过包管理器来安装 [certbot](https://certbot.eff.org/) 来请求创建一个证书:
```sh
sudo certbot certonly --key-type ecdsa --preferred-chain "ISRG Root X1" -d example.com -d www.example.com
```
-您可以通过 `-d` 参数来指定多个域名,这些域名都将共用一个证书。证书的保存位置在 `/etc/letsencrypt/live/example.com/` 下,与您列出的第一个域名名称相匹配。
-The key type and preferred chain options are necessary for getting a minimal size certificate file, essential for making your server run as *fast* as possible. The chain will still contain one RSA certificate until when Let's Encrypt gets their new EC chain trusted in all major browsers, possibly around 2023.
-
-如果你想获取体积最小的证书文件,那么 `秘钥类型` 以及 `首选链` 这两个选项是很有必要的。这有助于让您的服务器更快地进行认证。该链中包含了一个 RSA 证书,直到所有的主流服务器都信任 Let's Encrypt 的新 EC 链,可能在 2023 年左右。
+:::
-密钥类型和首选链选项对于获取最小大小的证书文件是必需的,对于使您的服务器尽可能*快*地运行是必不可少的。该链仍将包含一个RSA证书,直到Let's Encrypt在所有主流浏览器中信任他们的新EC链,可能在2023年左右。
\ No newline at end of file
+密钥类型和首选链选项对于获取最小大小的证书文件是必需的,对于使您的服务器尽可能*快*地运行是必不可少的。 该链仍将包含一个RSA证书,直到Let's Encrypt在所有主流浏览器中信任他们的新EC链,可能在2023年左右。
From 93b5facd9d958d36fa5871f686afb08b2bb4b0eb Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:30 +0300
Subject: [PATCH 135/776] New translations tls.md (Portuguese, Brazilian)
---
src/pt/guide/how-to/tls.md | 158 +++++++++++++++++++++++++++++++++++++
1 file changed, 158 insertions(+)
create mode 100644 src/pt/guide/how-to/tls.md
diff --git a/src/pt/guide/how-to/tls.md b/src/pt/guide/how-to/tls.md
new file mode 100644
index 0000000000..5299134cb1
--- /dev/null
+++ b/src/pt/guide/how-to/tls.md
@@ -0,0 +1,158 @@
+# TLS/SSL/HTTPS
+
+> How do I run Sanic via HTTPS?
+
+If you do not have TLS certificates yet, [see the end of this page](./tls.md#get-certificates-for-your-domain-names).
+
+## Single domain and single certificate
+
+---:1 Let Sanic automatically load your certificate files, which need to be named `fullchain.pem` and `privkey.pem` in the given folder:
+
+:--:1
+```sh
+sudo sanic myserver:app -H :: -p 443 \
+ --tls /etc/letsencrypt/live/example.com/
+```
+```python
+app.run("::", 443, ssl="/etc/letsencrypt/live/example.com/")
+```
+:---
+
+---:1 Or, you can pass cert and key filenames separately as a dictionary:
+
+Additionally, `password` may be added if the key is encrypted, all fields except for the password are passed to `request.conn_info.cert`. :--:1
+```python
+ssl = {
+ "cert": "/path/to/fullchain.pem",
+ "key": "/path/to/privkey.pem",
+ "password": "for encrypted privkey file", # Optional
+}
+app.run(host="0.0.0.0", port=8443, ssl=ssl)
+```
+:---
+
+---:1 Alternatively, [`ssl.SSLContext`](https://docs.python.org/3/library/ssl.html) may be passed, if you need full control over details such as which crypto algorithms are permitted. By default Sanic only allows secure algorithms, which may restrict access from very old devices. :--:1
+```python
+import ssl
+
+context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
+context.load_cert_chain("certs/fullchain.pem", "certs/privkey.pem")
+
+app.run(host="0.0.0.0", port=8443, ssl=context)
+```
+:---
+
+
+## Multiple domains with separate certificates
+
+---:1 A list of multiple certificates may be provided, in which case Sanic chooses the one matching the hostname the user is connecting to. This occurs so early in the TLS handshake that Sanic has not sent any packets to the client yet.
+
+If the client sends no SNI (Server Name Indication), the first certificate on the list will be used even though on the client browser it will likely fail with a TLS error due to name mismatch. To prevent this fallback and to cause immediate disconnection of clients without a known hostname, add `None` as the first entry on the list. `--tls-strict-host` is the equivalent CLI option. :--:1
+```python
+ssl = ["certs/example.com/", "certs/bigcorp.test/"]
+app.run(host="0.0.0.0", port=8443, ssl=ssl)
+```
+```sh
+sanic myserver:app
+ --tls certs/example.com/
+ --tls certs/bigcorp.test/
+ --tls-strict-host
+```
+:---
+
+::: tip You may also use `None` in front of a single certificate if you do not wish to reveal your certificate, true hostname or site content to anyone connecting to the IP address instead of the proper DNS name. :::
+
+---:1 Dictionaries can be used on the list. This allows also specifying which domains a certificate matches to, although the names present on the certificate itself cannot be controlled from here. If names are not specified, the names from the certificate itself are used.
+
+To only allow connections to the main domain **example.com** and only to subdomains of **bigcorp.test**:
+
+:--:1
+```python
+ssl = [
+ None, # No fallback if names do not match!
+ {
+ "cert": "certs/example.com/fullchain.pem",
+ "key": "certs/example.com/privkey.pem",
+ "names": ["example.com", "*.bigcorp.test"],
+ }
+]
+app.run(host="0.0.0.0", port=8443, ssl=ssl)
+```
+:---
+
+## Accessing TLS information in handlers via `request.conn_info` fields
+
+* `.ssl` - is the connection secure (bool)
+* `.cert` - certificate info and dict fields of the currently active cert (dict)
+* `.server_name` - the SNI sent by the client (str, may be empty)
+
+Do note that all `conn_info` fields are per connection, where there may be many requests over time. If a proxy is used in front of your server, these requests on the same pipe may even come from different users.
+
+## Redirect HTTP to HTTPS, with certificate requests still over HTTP
+
+In addition to your normal server(s) running HTTPS, run another server for redirection, `http_redir.py`:
+
+```python
+from sanic import Sanic, exceptions, response
+
+app = Sanic("http_redir")
+
+# Serve ACME/certbot files without HTTPS, for certificate renewals
+app.static("/.well-known", "/var/www/.well-known", resource_type="dir")
+
+@app.exception(exceptions.NotFound, exceptions.MethodNotSupported)
+def redirect_everything_else(request, exception):
+ server, path = request.server_name, request.path
+ if server and path.startswith("/"):
+ return response.redirect(f"https://{server}{path}", status=308)
+ return response.text("Bad Request. Please use HTTPS!", status=400)
+```
+
+It is best to setup this as a systemd unit separate of your HTTPS servers. You may need to run HTTP while initially requesting your certificates, while you cannot run the HTTPS server yet. Start for IPv4 and IPv6:
+
+```
+sanic http_redir:app -H 0.0.0.0 -p 80
+sanic http_redir:app -H :: -p 80
+```
+
+Alternatively, it is possible to run the HTTP redirect application from the main application:
+
+```python
+# app == Your main application
+# redirect == Your http_redir application
+@app.before_server_start
+async def start(app, _):
+ app.ctx.redirect = await redirect.create_server(
+ port=80, return_asyncio_server=True
+ )
+ app.add_task(runner(redirect, app.ctx.redirect))
+
+
+@app.before_server_stop
+async def stop(app, _):
+ await app.ctx.redirect.close()
+
+
+async def runner(app, app_server):
+ app.is_running = True
+ try:
+ app.signalize()
+ app.finalize()
+ app.state.is_started = True
+ await app_server.serve_forever()
+ finally:
+ app.is_running = False
+ app.is_stopping = True
+```
+
+## Get certificates for your domain names
+
+You can get free certificates from [Let's Encrypt](https://letsencrypt.org/). Install [certbot](https://certbot.eff.org/) via your package manager, and request a certificate:
+
+```sh
+sudo certbot certonly --key-type ecdsa --preferred-chain "ISRG Root X1" -d example.com -d www.example.com
+```
+
+Multiple domain names may be added by further `-d` arguments, all stored into a single certificate which gets saved to `/etc/letsencrypt/live/example.com/` as per **the first domain** that you list here.
+
+The key type and preferred chain options are necessary for getting a minimal size certificate file, essential for making your server run as *fast* as possible. The chain will still contain one RSA certificate until when Let's Encrypt gets their new EC chain trusted in all major browsers, possibly around 2023.
From abc577a0ba8bd9e837d09a4fbf02c2e1523b5d42 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:31 +0300
Subject: [PATCH 136/776] New translations toc.md (Japanese)
---
src/ja/guide/how-to/toc.md | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/src/ja/guide/how-to/toc.md b/src/ja/guide/how-to/toc.md
index 0f6f129714..4184a4a141 100644
--- a/src/ja/guide/how-to/toc.md
+++ b/src/ja/guide/how-to/toc.md
@@ -1,21 +1,21 @@
# 目次
-よくある質問やユーザー・ケースに答えるために、十分に機能する例をまとめました。ほとんどの場合、例は最小限のものですが、完全で実行可能なソリューションである必要があります。
+よくある質問やユーザー・ケースに答えるために、十分に機能する例をまとめました。 ほとんどの場合、例は最小限のものですが、完全で実行可能なソリューションである必要があります。
-| Page | How do I ... |
-|:-----|:------------|
-| [Applicationのマウント](./mounting.md) | ... どうやってルートより上のパスにアプリケーションをマウントする? |
-| [Authentication](./authentication.md) | ... どうやって認証と許可を制御しますか? |
-| [Autodiscovery](./autodiscovery.md) | ... どうやってアプリケーションの構築に使用しているコンポーネントを自動検出しますか? |
-| [CORS](./cors.md) | ... どうやってCORS用にアプリケーションを構成しますか? |
-| CSRF | *Coming soon* |
-| Databases | *Coming soon* |
-| IPv6 | *Coming soon* |
-| Request ID Logging | *Coming soon* |
-| Request validation | *Coming soon* |
-| Serialization | *Coming soon* |
-| Server Sent Events | *Coming soon* |
-| [ORM](./orm) | ... どうやってSanicでORMを使う? |
-| Task queues | *Coming soon* |
-| [TLS/SSL/HTTPS](./tls.md) | ... どうやってHTTPS経由でSanicを実行する? ... どうやってHTTPをHTTPSにリダイレクトしますか? |
-| Websocket feeds | *Coming soon* |
+| Page | How do I ... |
+|:------------------------------------- |:---------------------------------------------------- |
+| [Applicationのマウント](./mounting.md) | ... どうやってルートより上のパスにアプリケーションをマウントする? |
+| [Authentication](./authentication.md) | ... どうやって認証と許可を制御しますか? |
+| [Autodiscovery](./autodiscovery.md) | ... どうやってアプリケーションの構築に使用しているコンポーネントを自動検出しますか? |
+| [CORS](./cors.md) | ... どうやってCORS用にアプリケーションを構成しますか? |
+| CSRF | *Coming soon* |
+| Databases | *Coming soon* |
+| IPv6 | *Coming soon* |
+| Request ID Logging | *Coming soon* |
+| Request validation | *Coming soon* |
+| Serialization | *Coming soon* |
+| Server Sent Events | *Coming soon* |
+| [ORM](./orm) | ... どうやってSanicでORMを使う? |
+| Task queues | *Coming soon* |
+| [TLS/SSL/HTTPS](./tls.md) | どうやってHTTPS経由でSanicを実行する? どうやってHTTPをHTTPSにリダイレクトしますか? |
+| Websocket feeds | *Coming soon* |
From 206c2a9fcd7dc8213eca57070f3527468c6902e3 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:32 +0300
Subject: [PATCH 137/776] New translations toc.md (Korean)
---
src/ko/guide/how-to/toc.md | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 src/ko/guide/how-to/toc.md
diff --git a/src/ko/guide/how-to/toc.md b/src/ko/guide/how-to/toc.md
new file mode 100644
index 0000000000..d10bda1de6
--- /dev/null
+++ b/src/ko/guide/how-to/toc.md
@@ -0,0 +1,21 @@
+# Table of Contents
+
+We have compiled fully working examples to answer common questions and user cases. For the most part, the examples are as minimal as possible, but should be complete and runnable solutions.
+
+| Page | How do I ... |
+|:------------------------------------- |:------------------------------------------------------------------- |
+| [Application mounting](./mounting.md) | ... mount my application at some path above the root? |
+| [Authentication](./authentication.md) | ... control authentication and authorization? |
+| [Autodiscovery](./autodiscovery.md) | ... autodiscover the components I am using to build my application? |
+| [CORS](./cors.md) | ... configure my application for CORS? |
+| CSRF | *Coming soon* |
+| Databases | *Coming soon* |
+| IPv6 | *Coming soon* |
+| Request ID Logging | *Coming soon* |
+| Request validation | *Coming soon* |
+| Serialization | *Coming soon* |
+| Server Sent Events | *Coming soon* |
+| [ORM](./orm) | ... use an ORM with Sanic? |
+| Task queues | *Coming soon* |
+| [TLS/SSL/HTTPS](./tls.md) | ... run Sanic via HTTPS? ... redirect HTTP to HTTPS? |
+| Websocket feeds | *Coming soon* |
From e6f97376d41a51f8103c41e6efba099fc3f7a966 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:33 +0300
Subject: [PATCH 138/776] New translations toc.md (Chinese Simplified)
---
src/zh/guide/how-to/toc.md | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/src/zh/guide/how-to/toc.md b/src/zh/guide/how-to/toc.md
index 29961b9604..eda9d28ba5 100644
--- a/src/zh/guide/how-to/toc.md
+++ b/src/zh/guide/how-to/toc.md
@@ -1,21 +1,21 @@
# 目录(Table of Contents)
-虽然我们已经编写了各种用户场景下的代码样例来回答常见的问题。但是在大多数情况下,这些例子都是尽可能的简单,所以同时应该有完整的可运行方案。
+虽然我们已经编写了各种用户场景下的代码样例来回答常见的问题。 但是在大多数情况下,这些例子都是尽可能的简单,所以同时应该有完整的可运行方案。
-| 内容 | 我该如何 ... |
-|:--------------------------------------|:-------------------------------------------------------|
-| [应用挂载](./mounting.md) | ... 将我的应用程序挂载在根目录下的某个路径? |
-| [认证](./authentication.md) | ... 控制认证和权限? |
-| [自动发现](./autodiscovery.md) | ... 自动发现我正在使用的组件来构建我的应用程序? |
-| [CORS](./cors.md) | ... 如何配置跨域资源共享 |
-| CSRF | *Coming soon* |
-| Databases | *Coming soon* |
-| IPv6 | *Coming soon* |
-| Request ID Logging | *Coming soon* |
-| Request validation | *Coming soon* |
-| Serialization | *Coming soon* |
-| Server Sent Events | *Coming soon* |
-| [ORM](./orm.md) | 在 Sanic 中使用 ORM ? |
-| Task queues | *Coming soon* |
-| [TLS/SSL/HTTPS](./tls.md) | ... 在 HTTPS 下运行 Sanic ?... 将 HTTP 重定向到 HTTPS ? |
-| Websocket feeds | *Coming soon* |
+| 内容 | 我该如何 ... |
+|:-------------------------- |:----------------------------------------------- |
+| [应用挂载](./mounting.md) | ... 将我的应用程序挂载在根目录下的某个路径? |
+| [认证](./authentication.md) | ... 控制认证和权限? |
+| [自动发现](./autodiscovery.md) | ... 自动发现我正在使用的组件来构建我的应用程序? |
+| [CORS](./cors.md) | ... 如何配置跨域资源共享 |
+| CSRF | *Coming soon* |
+| Databases | *Coming soon* |
+| IPv6 | *Coming soon* |
+| Request ID Logging | *Coming soon* |
+| Request validation | *Coming soon* |
+| Serialization | *Coming soon* |
+| Server Sent Events | *Coming soon* |
+| [ORM](./orm) | 在 Sanic 中使用 ORM ? |
+| Task queues | *Coming soon* |
+| [TLS/SSL/HTTPS](./tls.md) | ... 在 HTTPS 下运行 Sanic ? ... 将 HTTP 重定向到 HTTPS ? |
+| Websocket feeds | *Coming soon* |
From 06bf00d05d9ce7fb24b4111e34c0b54dfd57f779 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:36 +0300
Subject: [PATCH 139/776] New translations validation.md (Korean)
---
src/ko/guide/how-to/validation.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/validation.md
diff --git a/src/ko/guide/how-to/validation.md b/src/ko/guide/how-to/validation.md
new file mode 100644
index 0000000000..d45b2dea4c
--- /dev/null
+++ b/src/ko/guide/how-to/validation.md
@@ -0,0 +1 @@
+validation
From d2ee1ba3d738f00d3a82566bb973c97595b79702 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:37 +0300
Subject: [PATCH 140/776] New translations validation.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/validation.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/validation.md
diff --git a/src/pt/guide/how-to/validation.md b/src/pt/guide/how-to/validation.md
new file mode 100644
index 0000000000..d45b2dea4c
--- /dev/null
+++ b/src/pt/guide/how-to/validation.md
@@ -0,0 +1 @@
+validation
From 12a143fa46e95613ea1553dfec5a326067147896 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:39 +0300
Subject: [PATCH 141/776] New translations websocket-feed.md (Korean)
---
src/ko/guide/how-to/websocket-feed.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/websocket-feed.md
diff --git a/src/ko/guide/how-to/websocket-feed.md b/src/ko/guide/how-to/websocket-feed.md
new file mode 100644
index 0000000000..ae2abc2def
--- /dev/null
+++ b/src/ko/guide/how-to/websocket-feed.md
@@ -0,0 +1 @@
+websocket feed
From 304e008ee7adfce8ef2681677e544f59ad1e19ab Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:41 +0300
Subject: [PATCH 142/776] New translations websocket-feed.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/websocket-feed.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/websocket-feed.md
diff --git a/src/pt/guide/how-to/websocket-feed.md b/src/pt/guide/how-to/websocket-feed.md
new file mode 100644
index 0000000000..ae2abc2def
--- /dev/null
+++ b/src/pt/guide/how-to/websocket-feed.md
@@ -0,0 +1 @@
+websocket feed
From 69296e1aa43e2638706999f52c1bc826354e2dce Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:42 +0300
Subject: [PATCH 143/776] New translations v21.12.md (Japanese)
---
src/ja/guide/release-notes/v21.12.md | 105 +++++++++++----------------
1 file changed, 42 insertions(+), 63 deletions(-)
diff --git a/src/ja/guide/release-notes/v21.12.md b/src/ja/guide/release-notes/v21.12.md
index ec3691ce87..87fca39b96 100644
--- a/src/ja/guide/release-notes/v21.12.md
+++ b/src/ja/guide/release-notes/v21.12.md
@@ -4,17 +4,17 @@
## 概要
-このリリースは、バージョン21の[リリースサイクル](../../org/policies.md#release-schedule)の最終リリースとなります。バージョン21は今後長期サポートに入り、2023年12月までの2年間サポートされる予定です。
+このリリースは、バージョン21の[リリースサイクル](../../org/policies.md#release-schedule)の最終リリースとなります。 バージョン21は今後長期サポートに入り、2023年12月までの2年間サポートされる予定です。
## 知っておきたい
-詳しくは[Changelog](https://sanic.readthedocs.io/en/stable/sanic/changelog.html)をご覧ください。注目すべき新機能・不具合、アップグレード対象...
+詳しくは[Changelog](https://sanic.readthedocs.io/en/stable/sanic/changelog.html)をご覧ください。 注目すべき新機能・不具合、アップグレード対象...
### アプリケーション名とブループリント名の厳格化
-v21.6](./v21.6.md#stricter-application-and-blueprint-names-and-deprecation) では、アプリケーションとブループリントの名前は新しい制限に適合することが求められました。この変更は、起動時に強制されるようになりました。
+v21.6](./v21.6.md#stricter-application-and-blueprint-names-and-deprecation) では、アプリケーションとブループリントの名前は新しい制限に適合することが求められました。 この変更は、起動時に強制されるようになりました。
-以下の制約に従った名前で**なければいけません。**
+以下の制約に従った名前で**なければいけません。 **
1. 英数字(`a-zA-Z0-9`)のみ使用可能です。
2. ハイフン(`-`)またはアンダースコア(`_`)を含むことができます。
@@ -22,7 +22,7 @@ v21.6](./v21.6.md#stricter-application-and-blueprint-names-and-deprecation) で
### 厳格なアプリケーションとブループリントのプロパティ
-`Sanic` や `Blueprint` オブジェクトのプロパティを直接設定できる古い寛容さは、非推奨となり、今後は許可されなくなりました。必ず `ctx` オブジェクトを使用してください。
+`Sanic` や `Blueprint` オブジェクトのプロパティを直接設定できる古い寛容さは、非推奨となり、今後は許可されなくなりました。 必ず `ctx` オブジェクトを使用してください。
```python
app = Sanic("MyApp")
@@ -39,7 +39,7 @@ app.ctx.db = Database()
### ストリーミング応答のアップグレード (まだの場合)
-レスポンスメソッド `sanic.response.stream` は **非推奨** となり、v22.6 で削除される予定です。まだ旧式のストリーミングレスポンスを使用している場合は、アップグレードをお願いします。
+レスポンスメソッド `sanic.response.stream` は **非推奨** となり、v22.6 で削除される予定です。 まだ旧式のストリーミングレスポンスを使用している場合は、アップグレードをお願いします。
**旧 - 非推奨**
@@ -69,7 +69,7 @@ async def test(request: Request):
### CLIのオーバーホールとMOTD(本日のメッセージ)について
-SanicのCLIはかなり大規模なアップグレードを受けました。これは `app.run()` と同等にするために多くの新機能を追加しています。また、新しい MOTD 表示も含まれており、実行中の環境について素早く、一目でわかるハイライトを提供します。MOTDはTTYを意識しているので、サーバーのログではあまり冗長になりません。これは主にアプリケーション開発時の利便性を目的としています。
+SanicのCLIはかなり大規模なアップグレードを受けました。 これは `app.run()` と同等にするために多くの新機能を追加しています。 また、新しい MOTD 表示も含まれており、実行中の環境について素早く、一目でわかるハイライトを提供します。 MOTDはTTYを意識しているので、サーバーのログではあまり冗長になりません。 これは主にアプリケーション開発時の利便性を目的としています。
```
$ sanic --help
@@ -151,9 +151,9 @@ Optional
### サーバーの実行モードと `debug` に来る変更点
-現在、`DEV` と `PRODUCTION` の2つの実行モードがあります。デフォルトでは、Sanicサーバーは `PRODUCTION` モードで実行されます。これはデプロイメントを想定している。
+現在、`DEV` と `PRODUCTION` の2つの実行モードがあります。 デフォルトでは、Sanicサーバーは `PRODUCTION` モードで実行されます。 これはデプロイメントを想定している。
-現在、`DEV`モードは古いSanicのバージョンで `debug=True` が動作する方式と非常によく似ています。しかし、v22.3では しかし、v22.3では、`debug=True`は自動リロードを有効にしなくなりました**。デバッグと自動リロードを行いたい場合は、`DEV`モードを有効にする必要があります。
+現在、`DEV`モードは古いSanicのバージョンで `debug=True` が動作する方式と非常によく似ています。 However, in v22.3. `debug=True` will **no longer** enable auto-reload. デバッグと自動リロードを行いたい場合は、`DEV`モードを有効にする必要があります。
**開発**
@@ -179,12 +179,12 @@ v22.3から、`PRODUCTION`モードはデフォルトでアクセスログを有
変更点の概要は以下の通りです。
-| フラグ | モード | トレースバック | ログ | アクセスログ | 再読込 | 最大ワーカー |
-|---------|-------|------------|---------|-------------|--------|-------------|
-| --debug | DEBUG | はい | DEBUG | はい | ^1 | |
-| | PROD | いいえ | INFO ^2 | ^3 | | |
-| --dev | DEBUG | はい | DEBUG | はい | はい | |
-| --fast | | | | | | はい |
+| フラグ | モード | トレースバック | ログ | アクセスログ | 再読込 | 最大ワーカー |
+| ------- | ----- | ------- | ------- | ------ | --- | ------ |
+| --debug | DEBUG | はい | DEBUG | はい | ^1 | |
+| | PROD | いいえ | INFO ^2 | ^3 | | |
+| --dev | DEBUG | はい | DEBUG | はい | はい | |
+| --fast | | | | | | はい |
- ^1 `--debug` で自動リロードを非推奨とし、22.3 で削除する。
@@ -205,7 +205,7 @@ app.run(fast=True)
### ファーストクラスのSanic Extensionsサポート
-[Sanic Extensions](../../plugins/sanic-ext/getting-started.md) は、特に API 開発者のために意図された多くの追加機能を提供します。パッケージが環境にある限り、追加設定なしで、それが提供するすべての機能を簡単に実装できるようになりました。これらの機能は以下の通りです。
+[Sanic Extensions](../../plugins/sanic-ext/getting-started.md) は、特に API 開発者のために意図された多くの追加機能を提供します。 パッケージが環境にある限り、追加設定なしで、それが提供するすべての機能を簡単に実装できるようになりました。 これらの機能は以下の通りです。
- `HEAD`、`OPTIONS`、`TRACE` のエンドポイントの自動作成
- CORS保護
@@ -229,9 +229,9 @@ $ pip install sanic sanic-ext
:---
-その後、追加の設定は必要ありません。Sanic Extensionsはアプリケーションにアタッチされ、**これ以上の構成は必要なく**、すべての追加機能を提供します。
+その後、追加の設定は必要ありません。 Sanic Extensionsはアプリケーションにアタッチされ、**これ以上の構成は必要なく**、すべての追加機能を提供します。
-もし、動作方法を変更したり、追加の設定を提供したい場合は、`app.extend`を使用してSanic Extensionsを変更することができます。以下の例は同等です。`Config` オブジェクトは、IDE 開発に役立つ型アノテーションを提供するためのものです。
+もし、動作方法を変更したり、追加の設定を提供したい場合は、`app.extend`を使用してSanic Extensionsを変更することができます。 以下の例は同等です。 `Config` オブジェクトは、IDE 開発に役立つ型アノテーションを提供するためのものです。
---:1
```python
@@ -289,31 +289,26 @@ class TeapotError(SanicException):
raise TeapotError(extra={"name": "Adam"})
```
-新機能として、例外インスタンスに `extra` メタを渡すことができるようになりました。この `extra` 情報オブジェクトは、 `PRODUCTION` モードでは**抑制されます**が、 `DEVELOPMENT` モードでは表示されます。
+新機能として、例外インスタンスに `extra` メタを渡すことができるようになりました。 この `extra` 情報オブジェクトは、 `PRODUCTION` モードでは**抑制されます**が、 `DEVELOPMENT` モードでは表示されます。
----:1
-**PRODUCTION**
+---:1 **PRODUCTION**
-
-:--:1
-**DEVELOPMENT**
+ :--:1 **DEVELOPMENT**
-
-:---
+ :---
2.の話に戻ります: _エラーメッセージにコンテキストを追加する機能_
-これは、マイクロサービスや、エラーメッセージをJSON形式で返すつもりのAPIを作るときに特に有効です。この使用例では、クライアントに詳細を返すために、解析可能なエラーメッセージだけでなく、例外の周りに何らかのコンテキストを持たせたいと考えています。
+これは、マイクロサービスや、エラーメッセージをJSON形式で返すつもりのAPIを作るときに特に有効です。 この使用例では、クライアントに詳細を返すために、解析可能なエラーメッセージだけでなく、例外の周りに何らかのコンテキストを持たせたいと考えています。
```python
raise TeapotError(context={"foo": "bar"})
```
-これは、(利用可能であれば)常にエラーで**渡されるようにしたい**情報です。以下のような感じです。
+これは、(利用可能であれば)常にエラーで**渡されるようにしたい**情報です。 以下のような感じです。
----:1
-**PRODUCTION**
+---:1 **PRODUCTION**
```json
{
@@ -325,8 +320,7 @@ raise TeapotError(context={"foo": "bar"})
}
}
```
-:--:1
-**DEVELOPMENT**
+:--:1 **DEVELOPMENT**
```json
{
@@ -382,7 +376,7 @@ app.cancel_task("dummy_task")
### 定義におけるルートコンテキストのkwargs
-ルートが定義されるとき、`ctx_` というプレフィックスを持つキーワード引数をいくつでも追加することができます。これらの値は、ルートの `ctx` オブジェクトに注入されます。
+ルートが定義されるとき、`ctx_` というプレフィックスを持つキーワード引数をいくつでも追加することができます。 これらの値は、ルートの `ctx` オブジェクトに注入されます。
```python
@app.get("/1", ctx_label="something")
@@ -405,13 +399,13 @@ async def do_something(request):
### ブループリントはいつでも登録可能
-Sanicの以前のバージョンでは、ブループリントをアプリケーションにアタッチできるタイミングに厳密な順序がありました。もし、`app.blueprint(bp)`を、すべてのオブジェクトをBlueprintインスタンスにアタッチする*前に*実行すると、それらは見逃されることになります。
+Sanicの以前のバージョンでは、ブループリントをアプリケーションにアタッチできるタイミングに厳密な順序がありました。 もし、`app.blueprint(bp)`を、すべてのオブジェクトをBlueprintインスタンスにアタッチする*前に*実行すると、それらは見逃されることになります。
現在では、いつでもブループリントをアタッチすることができ、それにアタッチされたすべてのものがスタートアップ時に含まれます。
-# うるさい例外 (すべての例外をログに強制的に記録)
+### シグナルイベントを `Enum` で表す
-新しい設定値として `NOISY_EXCEPTIONS` があります。この値が `False` (デフォルト) の場合、Sanic はすべての `SanicException` の `quiet` プロパティを尊重します。つまり、`quiet=True` の例外はログ出力に表示されません。
+新しい設定値として `NOISY_EXCEPTIONS` があります。 この値が `False` (デフォルト) の場合、Sanic はすべての `SanicException` の `quiet` プロパティを尊重します。 つまり、`quiet=True` の例外はログ出力に表示されません。
しかし、 `NOISY_EXCEPTIONS=True` に設定すると、 `quiet` の値に関係なく、すべての例外がログに記録されるようになります。
@@ -421,7 +415,7 @@ Sanicの以前のバージョンでは、ブループリントをアプリケー
app.config.NOISY_EXCEPTIONS = True
```
-### シグナルイベントを `Enum` で表す
+### 環境変数のカスタム型キャスト
便宜上、すべてのビルトインシグナル値を持つ `Enum` が存在します。
@@ -433,15 +427,15 @@ async def connection_opened(conn_info):
...
```
-### 環境変数のカスタム型キャスト
+### `uvloop` を設定値で無効にする
-デフォルトでは、Sanic は環境変数を `config` インスタンスに適用する際に、 `int`, `float`, または `bool` 値に変換します。これを独自のコンバータで拡張することができる。
+デフォルトでは、Sanic は環境変数を `config` インスタンスに適用する際に、 `int`, `float`, または `bool` 値に変換します。 これを独自のコンバータで拡張することができる。
```python
app = Sanic(..., config=Config(converters=[UUID]))
```
-### `uvloop` を設定値で無効にする
+### 複数のTLS証明書でSanicサーバーを実行する
設定値によって `uvloop` の使用を制御することができます。
@@ -450,7 +444,7 @@ app = Sanic(..., config=Config(converters=[UUID]))
app.config.USE_UVLOOP = False
```
-### 複数のTLS証明書でSanicサーバーを実行する
+### 近日公開予定: SanicでPythonのWeb開発
Sanicは、複数のTLS証明書を使用して実行することができます。
@@ -465,43 +459,28 @@ app.run(
## ニュース
-### 近日公開予定: SanicでPythonのWeb開発
+### ドキュメントのダークモード
コア開発者の一人である[@ahopkins](https://github.com/ahopkins)によるSanicに関する本が近日発売予定です。
詳しくは[sanicbook.com](https://sanicbook.com)でご覧ください。
-> ウェブアプリケーションのパフォーマンスとスケーラビリティを向上させるために、Sanicを使った作業の実践的な知識を身につけましょう。その一方で、アプリを大幅にオーバーエンジニアリングすることなく、変化するビジネスニーズに合わせてカスタマイズする方法を学び、開発スキルをレベルアップします。
+> ウェブアプリケーションのパフォーマンスとスケーラビリティを向上させるために、Sanicを使った作業の実践的な知識を身につけましょう。 その一方で、アプリを大幅にオーバーエンジニアリングすることなく、変化するビジネスニーズに合わせてカスタマイズする方法を学び、開発スキルをレベルアップします。
-書籍の収益の一部はSanic Community Organizationに入り、Sanicの開発・運営資金として活用されます。つまり、この本を買うことも、Sanicを支援する方法のひとつなのです。
+書籍の収益の一部はSanic Community Organizationに入り、Sanicの開発・運営資金として活用されます。 つまり、この本を買うことも、Sanicを支援する方法のひとつなのです。
-### ドキュメントのダークモード
+### Dark mode for the docs
-まだお気づきでないようですが、このSanicのウェブサイトはネイティブのダークモードでご利用いただけるようになりました。ページの右上にあるテーマを切り替えることができます。
+まだお気づきでないようですが、このSanicのウェブサイトはネイティブのダークモードでご利用いただけるようになりました。 ページの右上にあるテーマを切り替えることができます。
## 謝礼
今回のリリースに参加された皆さん、ありがとうございました。 :clap:
-[@adarsharegmi](https://github.com/adarsharegmi)
-[@ahopkins](https://github.com/ahopkins)
-[@ashleysommer](https://github.com/ashleysommer)
-[@ChihweiLHBird](https://github.com/ChihweiLHBird)
-[@cnicodeme](https://github.com/cnicodeme)
-[@kianmeng](https://github.com/kianmeng)
-[@meysam81](https://github.com/meysam81)
-[@nuxion](https://github.com/nuxion)
-[@prryplatypus](https://github.com/prryplatypus)
-[@realDragonium](https://github.com/realDragonium)
-[@SaidBySolo](https://github.com/SaidBySolo)
-[@sjsadowski](https://github.com/sjsadowski)
-[@Tronic](https://github.com/tronic)
-[@Varriount](https://github.com/Varriount)
-[@vltr](https://github.com/vltr)
-[@whos4n3](https://github.com/whos4n3)
+[@adarsharegmi](https://github.com/adarsharegmi) [@ahopkins](https://github.com/ahopkins) [@ashleysommer](https://github.com/ashleysommer) [@ChihweiLHBird](https://github.com/ChihweiLHBird) [@cnicodeme](https://github.com/cnicodeme) [@kianmeng](https://github.com/kianmeng) [@meysam81](https://github.com/meysam81) [@nuxion](https://github.com/nuxion) [@prryplatypus](https://github.com/prryplatypus) [@realDragonium](https://github.com/realDragonium) [@SaidBySolo](https://github.com/SaidBySolo) [@sjsadowski](https://github.com/sjsadowski) [@Tronic](https://github.com/tronic) [@Varriount](https://github.com/Varriount) [@vltr](https://github.com/vltr) [@whos4n3](https://github.com/whos4n3)
そして、ドキュメントの同期と中国語への翻訳を維持してくれた[@miss85246](https://github.com/miss85246) と [@ZinkLu](https://github.com/ZinkLu) には、多大なる感謝を捧げます。
---
-もし、このプロジェクトを楽しんでいただけるなら、ぜひ貢献をご検討ください。もちろんコードの貢献は大歓迎ですが、どんな形の貢献も大歓迎です。ドキュメントを書いたり、使用例を紹介したり、会話に参加してあなたの声を伝えたり、もし可能であれば、[金銭的な貢献](https://opencollective.com/sanic-org/)も検討してみてください。
+もし、このプロジェクトを楽しんでいただけるなら、ぜひ貢献をご検討ください。 もちろんコードの貢献は大歓迎ですが、どんな形の貢献も大歓迎です。 ドキュメントを書いたり、使用例を紹介したり、会話に参加してあなたの声を伝えたり、もし可能であれば、[金銭的な貢献](https://opencollective.com/sanic-org/)も検討してみてください。
From e2338cf28fd5205967b2e6b3f559033c0feb9401 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:43 +0300
Subject: [PATCH 144/776] New translations v21.12.md (Korean)
---
src/ko/guide/release-notes/v21.12.md | 486 +++++++++++++++++++++++++++
1 file changed, 486 insertions(+)
create mode 100644 src/ko/guide/release-notes/v21.12.md
diff --git a/src/ko/guide/release-notes/v21.12.md b/src/ko/guide/release-notes/v21.12.md
new file mode 100644
index 0000000000..d2a443b404
--- /dev/null
+++ b/src/ko/guide/release-notes/v21.12.md
@@ -0,0 +1,486 @@
+# Version 21.12 (LTS)
+
+[[toc]]
+
+## Introduction
+
+This is the final release of the version 21 [release cycle](../../org/policies.md#release-schedule). Version 21 will now enter long-term support and will be supported for two years until December 2023.
+
+## What to know
+
+More details in the [Changelog](https://sanic.readthedocs.io/en/stable/sanic/changelog.html). Notable new or breaking features, and what to upgrade...
+
+### Strict application and blueprint names
+
+In [v21.6](./v21.6.md#stricter-application-and-blueprint-names-and-deprecation) application and blueprint names were required to conform to a new set of restrictions. That change is now being enforced at startup time.
+
+Names **must**:
+
+1. Only use alphanumeric characters (`a-zA-Z0-9`)
+2. May contain a hyphen (`-`) or an underscore (`_`)
+3. Must begin with a letter or underscore (`a-zA-Z_`)
+
+### Strict application and blueprint properties
+
+The old leniency to allow directly setting properties of a `Sanic` or `Blueprint` object was deprecated and no longer allowed. You must use the `ctx` object.
+
+```python
+app = Sanic("MyApp")
+app.ctx.db = Database()
+```
+
+### Removals
+
+The following deprecated features no longer exist:
+
+- `sanic.exceptions.abort`
+- `sanic.views.CompositionView`
+- `sanic.response.StreamingHTTPResponse`
+
+### Upgrade your streaming responses (if not already)
+
+The `sanic.response.stream` response method has been **deprecated** and will be removed in v22.6. If you are sill using an old school streaming response, please upgrade it.
+
+**OLD - Deprecated**
+
+```python
+async def sample_streaming_fn(response):
+ await response.write("foo,")
+ await response.write("bar")
+
+@app.route("/")
+async def test(request: Request):
+ return stream(sample_streaming_fn, content_type="text/csv")
+```
+
+**Current**
+
+```python
+async def sample_streaming_fn(response):
+ await response.write("foo,")
+ await response.write("bar")
+
+@app.route("/")
+async def test(request: Request):
+ response = await request.respond(content_type="text/csv")
+ await response.send("foo,")
+ await response.send("bar")
+```
+
+### CLI overhaul and MOTD (Message of the Day)
+
+The Sanic CLI has received a fairly extensive upgrade. It adds a bunch of new features to make it on par with `app.run()`. It also includes a new MOTD display to provide quick, at-a-glance highlights about your running environment. The MOTD is TTY-aware, and therefore will be less verbose in server logs. It is mainly intended as a convenience during application development.
+
+```
+$ sanic --help
+usage: sanic [-h] [--version] [--factory] [-s] [-H HOST] [-p PORT] [-u UNIX] [--cert CERT] [--key KEY] [--tls DIR] [--tls-strict-host]
+ [-w WORKERS | --fast] [--access-logs | --no-access-logs] [--debug] [-d] [-r] [-R PATH] [--motd | --no-motd] [-v]
+ [--noisy-exceptions | --no-noisy-exceptions]
+ module
+
+ ▄███ █████ ██ ▄█▄ ██ █ █ ▄██████████
+ ██ █ █ █ ██ █ █ ██
+ ▀███████ ███▄ ▀ █ █ ██ ▄ █ ██
+ ██ █████████ █ ██ █ █ ▄▄
+ ████ ████████▀ █ █ █ ██ █ ▀██ ███████
+
+ To start running a Sanic application, provide a path to the module, where
+ app is a Sanic() instance:
+
+ $ sanic path.to.server:app
+
+ Or, a path to a callable that returns a Sanic() instance:
+
+ $ sanic path.to.factory:create_app --factory
+
+ Or, a path to a directory to run as a simple HTTP server:
+
+ $ sanic ./path/to/static --simple
+
+Required
+========
+ Positional:
+ module Path to your Sanic app. Example: path.to.server:app
+ If running a Simple Server, path to directory to serve. Example: ./
+
+Optional
+========
+ General:
+ -h, --help show this help message and exit
+ --version show program's version number and exit
+
+ Application:
+ --factory Treat app as an application factory, i.e. a () -> callable
+ -s, --simple Run Sanic as a Simple Server, and serve the contents of a directory
+ (module arg should be a path)
+
+ Socket binding:
+ -H HOST, --host HOST Host address [default 127.0.0.1]
+ -p PORT, --port PORT Port to serve on [default 8000]
+ -u UNIX, --unix UNIX location of unix socket
+
+ TLS certificate:
+ --cert CERT Location of fullchain.pem, bundle.crt or equivalent
+ --key KEY Location of privkey.pem or equivalent .key file
+ --tls DIR TLS certificate folder with fullchain.pem and privkey.pem
+ May be specified multiple times to choose multiple certificates
+ --tls-strict-host Only allow clients that send an SNI matching server certs
+
+ Worker:
+ -w WORKERS, --workers WORKERS Number of worker processes [default 1]
+ --fast Set the number of workers to max allowed
+ --access-logs Display access logs
+ --no-access-logs No display access logs
+
+ Development:
+ --debug Run the server in debug mode
+ -d, --dev Currently is an alias for --debug. But starting in v22.3,
+ --debug will no longer automatically trigger auto_restart.
+ However, --dev will continue, effectively making it the
+ same as debug + auto_reload.
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+
+ Output:
+ --motd Show the startup display
+ --no-motd No show the startup display
+ -v, --verbosity Control logging noise, eg. -vv or --verbosity=2 [default 0]
+ --noisy-exceptions Output stack traces for all exceptions
+ --no-noisy-exceptions No output stack traces for all exceptions
+```
+
+### Server running modes and changes coming to `debug`
+
+There are now two running modes: `DEV` and `PRODUCTION`. By default, Sanic server will run under `PRODUCTION` mode. This is intended for deployments.
+
+Currently, `DEV` mode will operate very similarly to how `debug=True` does in older Sanic versions. However, in v22.3. `debug=True` will **no longer** enable auto-reload. If you would like to have debugging and auto-reload, you should enable `DEV` mode.
+
+**DEVELOPMENT**
+
+```
+$ sanic server:app --dev
+```
+
+```python
+app.run(debug=True, auto_reload=True)
+```
+
+**PRODUCTION**
+
+```
+$ sanic server:app
+```
+
+```python
+app.run()
+```
+
+Beginning in v22.3, `PRODUCTION` mode will no longer enable access logs by default.
+
+A summary of the changes are as follows:
+
+| Flag | Mode | Tracebacks | Logging | Access logs | Reload | Max workers |
+| ------- | ----- | ---------- | ------- | ----------- | ------ | ----------- |
+| --debug | DEBUG | yes | DEBUG | yes | ^1 | |
+| | PROD | no | INFO ^2 | ^3 | | |
+| --dev | DEBUG | yes | DEBUG | yes | yes | |
+| --fast | | | | | | yes |
+
+
+- ^1 `--debug` to deprecate auto-reloading and remove in 22.3
+- ^2 After 22.3 this moves to WARNING
+- ^3 After 22.3: no
+
+### Max allowed workers
+
+You can easily spin up the maximum number of allowed workers using `--fast`.
+
+```
+$ sanic server:app --fast
+```
+
+```python
+app.run(fast=True)
+```
+
+### First-class Sanic Extensions support
+
+[Sanic Extensions](../../plugins/sanic-ext/getting-started.md) provides a number of additional features specifically intended for API developers. You can now easily implement all of the functionality it has to offer without additional setup as long as the package is in the environment. These features include:
+
+- Auto create `HEAD`, `OPTIONS`, and `TRACE` endpoints
+- CORS protection
+- Predefined, endpoint-specific response serializers
+- Dependency injection into route handlers
+- OpenAPI documentation with Redoc and/or Swagger
+- Request query arguments and body input validation
+
+The preferred method is to install it along with Sanic, but you can also install the packages on their own.
+
+---:1
+```
+$ pip install sanic[ext]
+```
+
+:--:1
+
+```
+$ pip install sanic sanic-ext
+```
+
+:---
+
+After that, no additional configuration is required. Sanic Extensions will be attached to your application and provide all of the additional functionality with **no further configuration**.
+
+If you want to change how it works, or provide additional configuration, you can change Sanic extensions using `app.extend`. The following examples are equivalent. The `Config` object is to provide helpful type annotations for IDE development.
+
+---:1
+```python
+# This is optional, not required
+app = Sanic("MyApp")
+app.extend(config={"oas_url_prefix": "/apidocs"})
+```
+:--:
+```python
+# This is optional, not required
+app = Sanic("MyApp")
+app.config.OAS_URL_PREFIX = "/apidocs"
+```
+:---
+
+---:1
+```python
+# This is optional, not required
+from sanic_ext import Config
+
+app = Sanic("MyApp")
+app.extend(config=Config(oas_url_prefix="/apidocs"))
+```
+:--:
+
+:---
+
+### Contextual exceptions
+
+In [v21.9](./v21.9.md#default-exception-messages) we added default messages to exceptions that simplify the ability to consistently raise exceptions throughout your application.
+
+```python
+class TeapotError(SanicException):
+ status_code = 418
+ message = "Sorry, I cannot brew coffee"
+
+raise TeapotError
+```
+
+But this lacked two things:
+
+1. A dynamic and predictable message format
+2. The ability to add additional context to an error message (more on this in a moment)
+
+The current release allows any Sanic exception to have additional information to when raised to provide context when writing an error message:
+
+```python
+class TeapotError(SanicException):
+ status_code = 418
+
+ @property
+ def message(self):
+ return f"Sorry {self.extra['name']}, I cannot make you coffee"
+
+raise TeapotError(extra={"name": "Adam"})
+```
+
+The new feature allows the passing of `extra` meta to the exception instance. This `extra` info object **will be suppressed** when in `PRODUCTION` mode, but displayed in `DEVELOPMENT` mode.
+
+---:1 **PRODUCTION**
+
+ :--:1 **DEVELOPMENT**
+
+ :---
+
+Getting back to item 2 from above: _The ability to add additional context to an error message_
+
+This is particularly useful when creating microservices or an API that you intend to pass error messages back in JSON format. In this use case, we want to have some context around the exception beyond just a parseable error message to return details to the client.
+
+
+```python
+raise TeapotError(context={"foo": "bar"})
+```
+
+This is information **that we want** to always be passed in the error (when it is available). Here is what it should look like:
+
+---:1 **PRODUCTION**
+
+```json
+{
+ "description": "I'm a teapot",
+ "status": 418,
+ "message": "Sorry Adam, I cannot make you coffee",
+ "context": {
+ "foo": "bar"
+ }
+}
+```
+:--:1 **DEVELOPMENT**
+
+```json
+{
+ "description": "I'm a teapot",
+ "status": 418,
+ "message": "Sorry Adam, I cannot make you coffee",
+ "context": {
+ "foo": "bar"
+ },
+ "extra": {
+ "name": "Adam",
+ "more": "lines",
+ "complex": {
+ "one": "two"
+ }
+ },
+ "path": "/",
+ "args": {},
+ "exceptions": [
+ {
+ "type": "TeapotError",
+ "exception": "Sorry Adam, I cannot make you coffee",
+ "frames": [
+ {
+ "file": "handle_request",
+ "line": 83,
+ "name": "handle_request",
+ "src": ""
+ },
+ {
+ "file": "/tmp/p.py",
+ "line": 17,
+ "name": "handler",
+ "src": "raise TeapotError("
+ }
+ ]
+ }
+ ]
+}
+```
+:---
+
+### Background task management
+
+When using the `app.add_task` method to create a background task, there now is the option to pass an optional `name` keyword argument that allows it to be fetched, or cancelled.
+
+```python
+app.add_task(dummy, name="dummy_task")
+task = app.get_task("dummy_task")
+
+app.cancel_task("dummy_task")
+```
+
+### Route context kwargs in definitions
+
+When a route is defined, you can add any number of keyword arguments with a `ctx_` prefix. These values will be injected into the route `ctx` object.
+
+```python
+@app.get("/1", ctx_label="something")
+async def handler1(request):
+ ...
+
+@app.get("/2", ctx_label="something")
+async def handler2(request):
+ ...
+
+@app.get("/99")
+async def handler99(request):
+ ...
+
+@app.on_request
+async def do_something(request):
+ if request.route.ctx.label == "something":
+ ...
+```
+
+### Blueprints can be registered at any time
+
+In previous versions of Sanic, there was a strict ordering of when a Blueprint could be attached to an application. If you ran `app.blueprint(bp)` *before* attaching all objects to the Blueprint instance, they would be missed.
+
+Now, you can attach a Blueprint at anytime and everything attached to it will be included at startup.
+
+### Noisy exceptions (force all exceptions to logs)
+
+There is a new `NOISY_EXCEPTIONS` config value. When it is `False` (which is the default), Sanic will respect the `quiet` property of any `SanicException`. This means that an exception with `quiet=True` will not be displayed to the log output.
+
+However, when setting `NOISY_EXCEPTIONS=True`, all exceptions will be logged regardless of the `quiet` value.
+
+This can be helpful when debugging.
+
+```python
+app.config.NOISY_EXCEPTIONS = True
+```
+
+### Signal events as `Enum`
+
+There is an `Enum` with all of the built-in signal values for convenience.
+
+```python
+from sanic.signals import Event
+
+@app.signal(Event.HTTP_LIFECYCLE_BEGIN)
+async def connection_opened(conn_info):
+ ...
+```
+
+### Custom type casting of environment variables
+
+By default, Sanic will convert an `int`, `float`, or a `bool` value when applying environment variables to the `config` instance. You can extend this with your own converter:
+
+```python
+app = Sanic(..., config=Config(converters=[UUID]))
+```
+
+### Disable `uvloop` by configuration value
+
+The usage of `uvloop` can be controlled by configuration value:
+
+
+```python
+app.config.USE_UVLOOP = False
+```
+
+### Run Sanic server with multiple TLS certificates
+
+Sanic can be run with multiple TLS certificates:
+
+```python
+app.run(
+ ssl=[
+ "/etc/letsencrypt/live/example.com/",
+ "/etc/letsencrypt/live/mysite.example/",
+ ]
+)
+```
+
+## News
+
+### Coming Soon: Python Web Development with Sanic
+
+A book about Sanic is coming soon by one of the core developers, [@ahopkins](https://github.com/ahopkins).
+
+Learn more at [sanicbook.com](https://sanicbook.com).
+
+> Get equipped with the practical knowledge of working with Sanic to increase the performance and scalability of your web applications. While doing that, we will level-up your development skills as you learn to customize your application to meet the changing business needs without having to significantly over-engineer the app.
+
+A portion of book proceeds goes into the Sanic Community Organization to help fund the development and operation of Sanic. So, buying the book is another way you can support Sanic.
+
+### Dark mode for the docs
+
+If you have not already noticed, this Sanic website is now available in a native dark mode. You can toggle the theme at the top right of the page.
+
+## Thank you
+
+Thank you to everyone that participated in this release: :clap:
+
+[@adarsharegmi](https://github.com/adarsharegmi) [@ahopkins](https://github.com/ahopkins) [@ashleysommer](https://github.com/ashleysommer) [@ChihweiLHBird](https://github.com/ChihweiLHBird) [@cnicodeme](https://github.com/cnicodeme) [@kianmeng](https://github.com/kianmeng) [@meysam81](https://github.com/meysam81) [@nuxion](https://github.com/nuxion) [@prryplatypus](https://github.com/prryplatypus) [@realDragonium](https://github.com/realDragonium) [@SaidBySolo](https://github.com/SaidBySolo) [@sjsadowski](https://github.com/sjsadowski) [@Tronic](https://github.com/tronic) [@Varriount](https://github.com/Varriount) [@vltr](https://github.com/vltr) [@whos4n3](https://github.com/whos4n3)
+
+And, a special thank you to [@miss85246](https://github.com/miss85246) and [@ZinkLu](https://github.com/ZinkLu) for their tremendous work keeping the documentation synced and translated into Chinese.
+
+---
+
+If you enjoy the project, please consider contributing. Of course we love code contributions, but we also love contributions in any form. Consider writing some documentation, showing off use cases, joining conversations and making your voice known, and if you are able: [financial contributions](https://opencollective.com/sanic-org/).
From d13d006b6b2bfd4388d6024a661ccfdf609b563e Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:45 +0300
Subject: [PATCH 145/776] New translations v21.12.md (Chinese Simplified)
---
src/zh/guide/release-notes/v21.12.md | 192 ++++++++++++++++-----------
1 file changed, 112 insertions(+), 80 deletions(-)
diff --git a/src/zh/guide/release-notes/v21.12.md b/src/zh/guide/release-notes/v21.12.md
index af5fd79513..ed509f9db8 100644
--- a/src/zh/guide/release-notes/v21.12.md
+++ b/src/zh/guide/release-notes/v21.12.md
@@ -4,15 +4,15 @@
## 介绍(Introduction)
-该版本为 21 版本 [发布周期](../../org/policies.md#release-schedule) 中的最后一个发行版本,目前 21 版本将进入长期维护状态,直至 2023 年 12 月。
+该版本为 21 版本 [发布周期](../../org/policies.md#release-schedule) 中的最后一个发行版本,目前 21 版本将进入长期维护状态,直至 2023 年 12 月。 Version 21 will now enter long-term support and will be supported for two years until December 2023.
## 更新内容(What to know)
-更多详情请见 [更新记录](https://sanic.readthedocs.io/en/stable/sanic/changelog.html)。值得注意的新功能或突破性功能,以及要升级的内容...
+更多详情请见 [更新记录](https://sanic.readthedocs.io/en/stable/sanic/changelog.html)。 值得注意的新功能或突破性功能,以及要升级的内容...
### 更严格的应用程序和蓝图命名检查(Strict application and blueprint names)
-在 [v21.6](./v21.6.md#stricter-application-and-blueprint-names-and-deprecation) 中,应用程序或蓝图的名称需要符合新的命名规范,现在该规范将在应用启动时进行强制检查。
+在 [v21.6](./v21.6.md#stricter-application-and-blueprint-names-and-deprecation) 中,应用程序或蓝图的名称需要符合新的命名规范,现在该规范将在应用启动时进行强制检查。 That change is now being enforced at startup time.
名称 **必须** 符合以下规则:
@@ -22,7 +22,7 @@
### 更严格的应用程序和蓝图属性检查(Strict application and blueprint properties)
-在以前的版本中,您可以直接将属性挂载到 `Sanic` 或者 `Blueprint` 上,现在您必须使用 `ctx` 来进行属性设置。
+The old leniency to allow directly setting properties of a `Sanic` or `Blueprint` object was deprecated and no longer allowed. You must use the `ctx` object.
```python
app = Sanic("MyApp")
@@ -39,7 +39,7 @@ app.ctx.db = Database()
### 升级您的流式响应 (如果您尚未准备好弃用)
-`sanic.response.stream` 响应方法已被 **弃用** 并将在 v22.6 版本中删除。如果您仍在使用旧的流式响应,请将其升级。
+`sanic.response.stream` 响应方法已被 **弃用** 并将在 v22.6 版本中删除。 如果您仍在使用旧的流式响应,请将其升级。
**旧用法 - 已弃用**
@@ -69,7 +69,7 @@ async def test(request: Request):
### CLI 样式更新及每日消息(MOTD)
-Sanic CLI 获得了升级,它增加了非常多的新功能,使其能够与 `app.run` 一较高下。它还包含了一个全新的 MOTD 显示功能。让您快速的对当前环境配置有一个了解。MOTD 和 TTY 是互相感知的,因此它在您的日志中并不会有更详细的记录,主要目的是为了方便应用程序的开发。
+Sanic CLI 获得了升级,它增加了非常多的新功能,使其能够与 `app.run` 一较高下。 It adds a bunch of new features to make it on par with `app.run()`. 它还包含了一个全新的 MOTD 显示功能。 让您快速的对当前环境配置有一个了解。 The MOTD is TTY-aware, and therefore will be less verbose in server logs. It is mainly intended as a convenience during application development.
```
$ sanic --help
@@ -141,6 +141,52 @@ Optional
-r, --reload, --auto-reload Watch source directory for file changes and reload on changes
-R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+ Output:
+ --motd Show the startup display
+ --no-motd No show the startup display
+ -v, --verbosity Control logging noise, eg. -vv or --verbosity=2 [default 0]
+ --noisy-exceptions Output stack traces for all exceptions
+ --no-noisy-exceptions No output stack traces for all exceptions Example: path.to.server:app
+ If running a Simple Server, path to directory to serve. Example: ./
+
+Optional
+========
+ General:
+ -h, --help show this help message and exit
+ --version show program's version number and exit
+
+ Application:
+ --factory Treat app as an application factory, i.e. a () -> callable
+ -s, --simple Run Sanic as a Simple Server, and serve the contents of a directory
+ (module arg should be a path)
+
+ Socket binding:
+ -H HOST, --host HOST Host address [default 127.0.0.1]
+ -p PORT, --port PORT Port to serve on [default 8000]
+ -u UNIX, --unix UNIX location of unix socket
+
+ TLS certificate:
+ --cert CERT Location of fullchain.pem, bundle.crt or equivalent
+ --key KEY Location of privkey.pem or equivalent .key file
+ --tls DIR TLS certificate folder with fullchain.pem and privkey.pem
+ May be specified multiple times to choose multiple certificates
+ --tls-strict-host Only allow clients that send an SNI matching server certs
+
+ Worker:
+ -w WORKERS, --workers WORKERS Number of worker processes [default 1]
+ --fast Set the number of workers to max allowed
+ --access-logs Display access logs
+ --no-access-logs No display access logs
+
+ Development:
+ --debug Run the server in debug mode
+ -d, --dev Currently is an alias for --debug. But starting in v22.3,
+ --debug will no longer automatically trigger auto_restart.
+ However, --dev will continue, effectively making it the
+ same as debug + auto_reload.
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+
Output:
--motd Show the startup display
--no-motd No show the startup display
@@ -151,9 +197,9 @@ Optional
### 服务运行模式和 `debug` 的更改
-目前拥有的两个运行模式是:开发(`DEV`) 和 生产(`PRODUCTION`) Sanic 服务在生产模式下运行,这是为部署而设计的。
+There are now two running modes: `DEV` and `PRODUCTION`. By default, Sanic server will run under `PRODUCTION` mode. This is intended for deployments.
-目前,`DEV` 模式的运行方式与旧版本 Sanic 中的 `debug=True` 非常相似。但是,在 v22.3 中,`debug=True` 将 **不再** 启用自动重载功能。如果您想要调试和自动重载,您应该启用 开发(`dev`) 模式。
+目前,`DEV` 模式的运行方式与旧版本 Sanic 中的 `debug=True` 非常相似。 However, in v22.3. 但是,在 v22.3 中,`debug=True` 将 **不再** 启用自动重载功能。 如果您想要调试和自动重载,您应该启用 开发(`dev`) 模式。
**开发模式**
@@ -179,12 +225,13 @@ app.run()
变化摘要如下:
-| 标志 | 模式 | 错误追溯 | 日志 | 访问日志 | 自动重载 | 最大 works |
-| ------- | ----- | -------- | ------- | -------- | -------- | ---------- |
-| --debug | DEBUG | yes | DEBUG | yes | ^1 | |
-| | PROD | no | INFO ^2 | ^3 | | |
-| --dev | DEBUG | yes | DEBUG | yes | yes | |
-| --fast | | | | | | yes |
+| 标志 | 模式 | 错误追溯 | 日志 | 访问日志 | 自动重载 | 最大 works |
+| ------- | ----- | ---- | ------- | ---- | ---- | -------- |
+| --debug | DEBUG | yes | DEBUG | yes | ^1 | |
+| | PROD | no | INFO ^2 | ^3 | | |
+| --dev | DEBUG | yes | DEBUG | yes | yes | |
+| --fast | | | | | | yes |
+
- ^1 `--debug` 参数将在 v22.3 版本中移除自动重载功能
- ^2 在 v22.3 版本后将日志级别变更为 WARNING
@@ -204,7 +251,7 @@ app.run(fast=True)
### 一流的 Sanic 拓展支持(First-class Sanic Extensions support)
-[Sanic 拓展](../../plugins/sanic-ext/getting-started.md) 提供了许多专门针对 API 开发者的拓展功能,现在只要您在 python 环境中安装了 Sanic 拓展 就能够轻松地使用其所有功能,无需进行额外的设置,这些功能包括:
+[Sanic 拓展](../../plugins/sanic-ext/getting-started.md) 提供了许多专门针对 API 开发者的拓展功能,现在只要您在 python 环境中安装了 Sanic 拓展 就能够轻松地使用其所有功能,无需进行额外的设置,这些功能包括: You can now easily implement all of the functionality it has to offer without additional setup as long as the package is in the environment. These features include:
- 能够自动创建 `HEAD`, `OPTIONS`,和 `TRACE` 响应程序
- 具有跨域保护
@@ -213,9 +260,9 @@ app.run(fast=True)
- 完美适配 Redoc 和 Swagger
- 能够对请求参数和请求体进行验证
-最好的安装方式就是在安装 Sanic 的同时一并安装 Sanic 拓展,当然,您也可以独立安装:
----:1
+最好的安装方式就是在安装 Sanic 的同时一并安装 Sanic 拓展,当然,您也可以独立安装: ---:1
+---:1
```
$ pip install sanic[ext]
```
@@ -228,30 +275,25 @@ $ pip install sanic sanic-ext
:---
-之后,**不需要额外的配置**。Sanic 拓展将自动附加到您的应用程序,并提供所有拓展功能。
+之后,**不需要额外的配置**。 Sanic 拓展将自动附加到您的应用程序,并提供所有拓展功能。
-如果你想改变其工作方式,或者提供额外的配置,你可以使用 `app.extend` 来改变 Sanic 拓展。`Config` 对象是为 ide 开发提供有用的类型注释。
+如果你想改变其工作方式,或者提供额外的配置,你可以使用 `app.extend` 来改变 Sanic 拓展。 The following examples are equivalent. `Config` 对象是为 ide 开发提供有用的类型注释。
---:1
-
```python
# This is optional, not required
app = Sanic("MyApp")
app.extend(config={"oas_url_prefix": "/apidocs"})
```
-
:--:
-
```python
# This is optional, not required
app = Sanic("MyApp")
app.config.OAS_URL_PREFIX = "/apidocs"
```
-
:---
---:1
-
```python
# This is optional, not required
from sanic_ext import Config
@@ -259,14 +301,13 @@ from sanic_ext import Config
app = Sanic("MyApp")
app.extend(config=Config(oas_url_prefix="/apidocs"))
```
-
:--:
:---
### 上下文异常(Contextual exceptions)
-在[v21.9](./v21.9.md#default-exception-messages) 版本中,我们向异常添加了默认消息,简化了在整个应用程序中一致引发异常的能力。
+但这样会忽视两个非常重要的问题:
```python
class TeapotError(SanicException):
@@ -276,12 +317,12 @@ class TeapotError(SanicException):
raise TeapotError
```
-但这样会忽视两个非常重要的问题:
+当前版本允许任何 Sanic 异常在引发时具有附加信息,以便在编写错误消息时提供上下文:
1. 如何设置动态且可预测的消息格式
2. 如何向错误消息中添加额外上下文内容
-当前版本允许任何 Sanic 异常在引发时具有附加信息,以便在编写错误消息时提供上下文:
+新特性允许您向异常传递额外的信息,在生产模式下,该信息将不会被输出,但是在开发模式下它将进行显示。
```python
class TeapotError(SanicException):
@@ -294,33 +335,26 @@ class TeapotError(SanicException):
raise TeapotError(extra={"name": "Adam"})
```
-新特性允许您向异常传递额外的信息,在生产模式下,该信息将不会被输出,但是在开发模式下它将进行显示。
+The new feature allows the passing of `extra` meta to the exception instance. This `extra` info object **will be suppressed** when in `PRODUCTION` mode, but displayed in `DEVELOPMENT` mode.
----:1
-**生产模式**
-
-
-
-:--:1
-
-**开发模式**
+---:1 **生产模式**
-
+ ---:1 **生产模式**
-:---
+ :---
回到我们刚才提到的第二个问题:如何向错误消息中添加额外上下文内容
-这在创建微服务或 API 时特别有用,因为您希望以 JSON 格式传回错误消息。在这个用例中,我们希望有一些关于异常的上下文,而不仅仅是一个可解析的错误消息,以便向客户端返回详细信息。
+这在创建微服务或 API 时特别有用,因为您希望以 JSON 格式传回错误消息。 在这个用例中,我们希望有一些关于异常的上下文,而不仅仅是一个可解析的错误消息,以便向客户端返回详细信息。
+
```python
raise TeapotError(context={"foo": "bar"})
```
-这是我们希望 **始终在错误中传递的信息**(如果可用)。它应该是这样的:
+这是我们希望 **始终在错误中传递的信息**(如果可用)。 它应该是这样的:
----:1
-**生产模式**
+---:1 **PRODUCTION**
```json
{
@@ -332,9 +366,7 @@ raise TeapotError(context={"foo": "bar"})
}
}
```
-
-:--:1
-**开发模式**
+:--:1 **DEVELOPMENT**
```json
{
@@ -375,12 +407,11 @@ raise TeapotError(context={"foo": "bar"})
]
}
```
-
:---
### 后台任务管理(Background task management)
-当使用 `app.add_task` 方法创建后台任务时,可以额外的设置一个 `name` 参数,方便后续获取或取消任务。
+:--:1 **开发模式**
```python
app.add_task(dummy, name="dummy_task")
@@ -391,7 +422,7 @@ app.cancel_task("dummy_task")
### 定义路由中的上下文参数(Route context kwargs in definitions)
-定义路由时,您可以添加任意数量的带有' ctx\_ '前缀的关键字参数。这些值将被注入到路由“ctx”对象中。
+定义路由时,您可以添加任意数量的带有' ctx\_ '前缀的关键字参数。 这些值将被注入到路由“ctx”对象中。
```python
@app.get("/1", ctx_label="something")
@@ -406,6 +437,19 @@ async def handler2(request):
async def handler99(request):
...
+@app.on_request
+async def do_something(request):
+ if request.route.ctx.label == "something":
+ ...
+
+@app.get("/2", ctx_label="something")
+async def handler2(request):
+ ...
+
+@app.get("/99")
+async def handler99(request):
+ ...
+
@app.on_request
async def do_something(request):
if request.route.ctx.label == "something":
@@ -414,15 +458,15 @@ async def do_something(request):
### 蓝图可以在任意时刻注册
-在以前的 Sanic 版本中,蓝图的注册顺序有着严格的限制,如果您在响应函数注册到蓝图之前将蓝图注册到应用程序中,这些对象将会丢失。
+In previous versions of Sanic, there was a strict ordering of when a Blueprint could be attached to an application. If you ran `app.blueprint(bp)` *before* attaching all objects to the Blueprint instance, they would be missed.
-现在,您可以随时注册一个蓝图,所有被注册到蓝图上的响应函数都将在启动时被包含。
+Now, you can attach a Blueprint at anytime and everything attached to it will be included at startup.
### 通知异常 (将所有的异常输出到日志中)
-新增了一个 `NOISY_EXCEPTIONS` 配置项,该配置项默认为 False。 Sanic 支持任何静默异常,这意味着如果您在捕获异常后设置了 `quiet=False` 参数,该异常将不会在日志中输出。
+新增了一个 `NOISY_EXCEPTIONS` 配置项,该配置项默认为 False。 Sanic 支持任何静默异常,这意味着如果您在捕获异常后设置了 `quiet=False` 参数,该异常将不会在日志中输出。 This means that an exception with `quiet=True` will not be displayed to the log output.
-但是当您设置了 `NOISY_EXCEPTIONS` 为 True 时,无论 `quiet` 如何进行设置,都将被记录。
+现在,您可以随时注册一个蓝图,所有被注册到蓝图上的响应函数都将在启动时被包含。
这在调试时极为有用。
@@ -432,7 +476,7 @@ app.config.NOISY_EXCEPTIONS = True
### 可枚举的信号事件
-为了方便,我们内置了一个能够枚举所有信号的事件
+但是当您设置了 `NOISY_EXCEPTIONS` 为 True 时,无论 `quiet` 如何进行设置,都将被记录。
```python
from sanic.signals import Event
@@ -444,7 +488,7 @@ async def connection_opened(conn_info):
### 自定义环境变量的类型转换
-默认情况下,在环境变量中加载 config 配置的时候,Sanic 将主动转换配置为可能的类型,您可以通过配置转换器来进行控制:
+By default, Sanic will convert an `int`, `float`, or a `bool` value when applying environment variables to the `config` instance. You can extend this with your own converter:
```python
app = Sanic(..., config=Config(converters=[UUID]))
@@ -452,7 +496,8 @@ app = Sanic(..., config=Config(converters=[UUID]))
### 通过配置项禁用 `uvloop`
-现在 `uvloop` 的使用可由配置值进行控制:
+为了方便,我们内置了一个能够枚举所有信号的事件
+
```python
app.config.USE_UVLOOP = False
@@ -460,7 +505,7 @@ app.config.USE_UVLOOP = False
### 使用多个 TLS 证书运行 Sanic 服务
-现在 Sanic 支持使用多个不同的 TLS 证书运行:
+默认情况下,在环境变量中加载 config 配置的时候,Sanic 将主动转换配置为可能的类型,您可以通过配置转换器来进行控制:
```python
app.run(
@@ -475,39 +520,26 @@ app.run(
### 即将发布:《Sanic web 开发》
-由 Sanic 核心开发人员 [@ahopkins](https://github.com/ahopkins) 主笔的新书即将发布,访问 [sanicbook.com](https://sanicbook.com) 了解更多信息。
+现在 `uvloop` 的使用可由配置值进行控制:
+
+现在 Sanic 支持使用多个不同的 TLS 证书运行:
-> 掌握使用 Sanic 的实用知识,以提高 web 应用程序的性能和可伸缩性。除此之外,我们将提高您的开发技能,让您学会定制您的应用程序,以满足不断变化的业务需求,而不必对应用程序进行重大的过度设计。
+> 掌握使用 Sanic 的实用知识,以提高 web 应用程序的性能和可伸缩性。 除此之外,我们将提高您的开发技能,让您学会定制您的应用程序,以满足不断变化的业务需求,而不必对应用程序进行重大的过度设计。
-该书的收入将按照一定的比例捐赠给 SCO ,用于 Sanic 的进一步发展。因此购买此书是你支持 Sanic 发展的另一种方式。
+该书的收入将按照一定的比例捐赠给 SCO ,用于 Sanic 的进一步发展。 因此购买此书是你支持 Sanic 发展的另一种方式。
### 文档的深色模式(Dark mode for the docs)
-如果您还没有注意到,该网站现在支持原生在深色模式和浅色模式之间进行切换,您可以通过页面的右上角来进行手动切换。
+If you have not already noticed, this Sanic website is now available in a native dark mode. You can toggle the theme at the top right of the page.
## 鸣谢(Thank you)
-感谢每一位参与本次发布的人::clap:
-
-[@adarsharegmi](https://github.com/adarsharegmi)
-[@ahopkins](https://github.com/ahopkins)
-[@ashleysommer](https://github.com/ashleysommer)
-[@ChihweiLHBird](https://github.com/ChihweiLHBird)
-[@cnicodeme](https://github.com/cnicodeme)
-[@kianmeng](https://github.com/kianmeng)
-[@meysam81](https://github.com/meysam81)
-[@nuxion](https://github.com/nuxion)
-[@prryplatypus](https://github.com/prryplatypus)
-[@realDragonium](https://github.com/realDragonium)
-[@SaidBySolo](https://github.com/SaidBySolo)
-[@sjsadowski](https://github.com/sjsadowski)
-[@Tronic](https://github.com/tronic)
-[@Varriount](https://github.com/Varriount)
-[@vltr](https://github.com/vltr)
-[@whos4n3](https://github.com/whos4n3)
+如果您还没有注意到,该网站现在支持原生在深色模式和浅色模式之间进行切换,您可以通过页面的右上角来进行手动切换。
+
+[@adarsharegmi](https://github.com/adarsharegmi) [@ahopkins](https://github.com/ahopkins) [@ashleysommer](https://github.com/ashleysommer) [@ChihweiLHBird](https://github.com/ChihweiLHBird) [@cnicodeme](https://github.com/cnicodeme) [@kianmeng](https://github.com/kianmeng) [@meysam81](https://github.com/meysam81) [@nuxion](https://github.com/nuxion) [@prryplatypus](https://github.com/prryplatypus) [@realDragonium](https://github.com/realDragonium) [@SaidBySolo](https://github.com/SaidBySolo) [@sjsadowski](https://github.com/sjsadowski) [@Tronic](https://github.com/tronic) [@Varriount](https://github.com/Varriount) [@vltr](https://github.com/vltr) [@whos4n3](https://github.com/whos4n3)
并且,特别感谢 [@ConnorZhang](https://github.com/miss85246) 和 [@ZinkLu](https://github.com/ZinkLu),他们在同步翻译最新中文文档上付出了巨大精力。
---
-如果您喜欢本项目,请考虑参与建设本项目。我们欢迎您提交代码,也欢迎您以任何其他方式来参与本项目的建设。比如撰写文档,分享使用心得,参与社区讨论,当然,如果经济允许,您也可以考虑[经济资助](https://opencollective.com/sanic-org/)。
+如果您喜欢本项目,请考虑参与建设本项目。 我们欢迎您提交代码,也欢迎您以任何其他方式来参与本项目的建设。 比如撰写文档,分享使用心得,参与社区讨论,当然,如果经济允许,您也可以考虑[经济资助](https://opencollective.com/sanic-org/)。
From ce31d0117f3a14b1389d24bd99708244b643b509 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:45 +0300
Subject: [PATCH 146/776] New translations task-queue.md (Korean)
---
src/ko/guide/how-to/task-queue.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/task-queue.md
diff --git a/src/ko/guide/how-to/task-queue.md b/src/ko/guide/how-to/task-queue.md
new file mode 100644
index 0000000000..c5ee7c54a3
--- /dev/null
+++ b/src/ko/guide/how-to/task-queue.md
@@ -0,0 +1 @@
+task queue
From 4267c2558ed13275fa096bc8210e0bf524dd71f1 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:47 +0300
Subject: [PATCH 147/776] New translations static-redirects.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/static-redirects.md | 110 ++++++++++++++++++++++++
1 file changed, 110 insertions(+)
create mode 100644 src/pt/guide/how-to/static-redirects.md
diff --git a/src/pt/guide/how-to/static-redirects.md b/src/pt/guide/how-to/static-redirects.md
new file mode 100644
index 0000000000..5566050c74
--- /dev/null
+++ b/src/pt/guide/how-to/static-redirects.md
@@ -0,0 +1,110 @@
+# "Static" Redirects
+
+> How do I configure static redirects?
+
+:::: tabs
+::: tab app.py
+```python
+### SETUP ###
+import typing
+import sanic, sanic.response
+
+# Create the Sanic app
+app = sanic.Sanic(__name__)
+
+# This dictionary represents your "static"
+# redirects. For example, these values
+# could be pulled from a configuration file.
+REDIRECTS = {
+ '/':'/hello_world', # Redirect '/' to '/hello_world'
+ '/hello_world':'/hello_world.html' # Redirect '/hello_world' to 'hello_world.html'
+}
+
+# This function will return another function
+# that will return the configured value
+# regardless of the arguments passed to it.
+def get_static_function(value:typing.Any) -> typing.Callable[..., typing.Any]:
+ return lambda *_, **__: value
+
+### ROUTING ###
+# Iterate through the redirects
+for src, dest in REDIRECTS.items():
+ # Create the redirect response object
+ response:sanic.HTTPResponse = sanic.response.redirect(dest)
+
+ # Create the handler function. Typically,
+ # only a sanic.Request object is passed
+ # to the function. This object will be
+ # ignored.
+ handler = get_static_function(response)
+
+ # Route the src path to the handler
+ app.route(src)(handler)
+
+# Route some file and client resources
+app.static('/files/', 'files')
+app.static('/', 'client')
+
+### RUN ###
+if __name__ == '__main__':
+ app.run(
+ '127.0.0.1',
+ 10000
+ )
+```
+:::
+
+::: tab client/hello_world.html
+```html
+
+
+
+
+
+
+ Hello World
+
+
+
+
+ Hello world!
+
+
+
+```
+:::
+
+::: tab client/hello_world.css
+```css
+#hello_world {
+ width: 1000px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 100px;
+
+ padding: 100px;
+ color: aqua;
+ text-align: center;
+ font-size: 100px;
+ font-family: monospace;
+
+ background-color: rgba(0, 0, 0, 0.75);
+
+ border-radius: 10px;
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.75);
+}
+
+body {
+ background-image: url("/files/lake.jpg");
+ background-repeat: no-repeat;
+ background-size: cover;
+}
+```
+:::
+
+::: tab files/lake.jpg  :::
+::::
+
+Also, checkout some resources from the community:
+
+- [Static Routing Example](https://github.com/Perzan/sanic-static-routing-example)
From 7f22f9a92fd5137008a03a05c8c15478e69c18bb Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:47 +0300
Subject: [PATCH 148/776] New translations db.md (Portuguese, Brazilian)
---
src/pt/guide/how-to/db.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/db.md
diff --git a/src/pt/guide/how-to/db.md b/src/pt/guide/how-to/db.md
new file mode 100644
index 0000000000..60ca822eac
--- /dev/null
+++ b/src/pt/guide/how-to/db.md
@@ -0,0 +1 @@
+connecting to data sources
From 9908ffe1b836b00df373ae8740438d47683510a3 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:48 +0300
Subject: [PATCH 149/776] New translations orm.md (Chinese Simplified)
---
src/zh/guide/how-to/orm.md | 65 ++++++++++++--------------------------
1 file changed, 20 insertions(+), 45 deletions(-)
diff --git a/src/zh/guide/how-to/orm.md b/src/zh/guide/how-to/orm.md
index d5e2383134..9a2034faa9 100644
--- a/src/zh/guide/how-to/orm.md
+++ b/src/zh/guide/how-to/orm.md
@@ -4,31 +4,28 @@
Sanic 可以与所有的 ORM 工具一起使用,但是非异步的 ORM 框架将会拖累 Sanic 的性能。 目前已经支持异步的 orm 有很多, 比较好用的有:
-[SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html) [tortoise-orm](https://github.com/tortoise/tortoise-orm)
+At present, there are many ORMs that support asynchronicity. Two of the more common libraries are:
-只知道有这些工具但不会用?不用担心,接下来我们以 mysql 为例, 手把手教您使用两种 orm
+- [SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html)
+- [pip install tortoise-orm](https://github.com/tortoise/tortoise-orm)
+
+Integration in to your Sanic application is fairly simple:
## SQLAlchemy
-是的,您没有听错,在 [SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html) 版本中,添加了对 asyncio
-的原生支持,至此,Sanic 终于可以和 ORM 界的老前辈愉快的玩耍了。
+是的,您没有听错,在 [SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html) 版本中,添加了对 asyncio 的原生支持,至此,Sanic 终于可以和 ORM 界的老前辈愉快的玩耍了。 Be aware that this functionality is still considered *beta* by the SQLAlchemy project.
+
---:1
### 安装依赖
-首先,我们需要安装依赖,在以前的时候,我们安装的依赖是 `sqlalchemy` 和 `pymysql` 但是现在我们需要的是 `sqlalchemy` 和 `aiomysql`
+First, we need to install the required dependencies. 首先,我们需要安装依赖,在以前的时候,我们安装的依赖是 `sqlalchemy` 和 `pymysql` 但是现在我们需要的是 `sqlalchemy` 和 `aiomysql`
:--:1
```shell
-pip install sqlalchemy, aiomysql
-```
-
-或者
-
-```shell
-pip install sqlalchemy, asyncpg
+pip install sqlalchemy, aiomysql
```
:---
@@ -77,9 +74,8 @@ class Car(BaseModel):
### 创建 Sanic app 与异步数据库引擎。
-这里我们使用 mysql 作为数据库,您也可以选择 PostgreSQL / SQLite,注意要将驱动从 `aiomysql` 换为 `asyncpg` / `aiosqlite`
+这里我们使用 mysql 作为数据库,您也可以选择 PostgreSQL / SQLite,注意要将驱动从 `aiomysql` 换为 `asyncpg` / `aiosqlite` Pay attention to changing the driver from `aiomysql` to `asyncpg`/`aiosqlite`. :--:1
-:--:1
```python
# ./server.py
@@ -97,11 +93,11 @@ bind = create_async_engine("mysql+aiomysql://root:root@localhost/test", echo=Tru
### 注册中间件
-在这里,请求中间件为我们创建了一个可用的 `AsyncSession` 对象并且将其绑定至 `request.ctx` 中,而 `_base_model_session_ctx` 也会在这是被赋予可用的值,如果您需要在其他地方使用
-session 对象(而非从 `request.ctx` 中取值),该全局变量或许能帮助您(它是线程安全的)。
+在这里,请求中间件为我们创建了一个可用的 `AsyncSession` 对象并且将其绑定至 `request.ctx` 中,而 `_base_model_session_ctx` 也会在这是被赋予可用的值,如果您需要在其他地方使用 session 对象(而非从 `request.ctx` 中取值),该全局变量或许能帮助您(它是线程安全的)。
响应中间件会将创建的 `AsyncSession` 关闭,并重置 `_base_model_session_ctx` 的值,进而释放资源。
+
:--:1
```python
@@ -172,12 +168,8 @@ async def get_user(request, pk):
:---
----:1
-
### 发送请求
-:--:1
-
```sh
curl --location --request POST 'http://127.0.0.1:8000/user'
{"name":"foo","cars":[{"brand":"Tesla"}]}
@@ -188,7 +180,6 @@ curl --location --request GET 'http://127.0.0.1:8000/user/1'
{"name":"foo","cars":[{"brand":"Tesla"}]}
```
-:---
## Tortoise-ORM
@@ -201,7 +192,7 @@ tortoise-orm 的依赖非常简单,您只需要安装它即可。
:--:1
```shell
-pip install tortoise-orm
+pip install sqlalchemy, asyncpg
```
:---
@@ -229,6 +220,7 @@ class Users(Model):
:---
+
---:1
### 创建 Sanic app 与异步数据库引擎
@@ -245,6 +237,7 @@ from tortoise.contrib.sanic import register_tortoise
app = Sanic(__name__)
+
register_tortoise(
app, db_url="mysql://root:root@localhost/test", modules={"models": ["models"]}, generate_schemas=True
)
@@ -257,8 +250,6 @@ register_tortoise(
### 注册路由
-直接按照 Django ORM 的操作方式进行操作就可以了
-
:--:1
```python
@@ -266,33 +257,19 @@ register_tortoise(
# ./main.py
from models import Users
-from sanic import Sanic, response
-
-
-@app.route("/user")
-async def list_all(request):
- users = await Users.all()
- return response.json({"users": [str(user) for user in users]})
-
-
-@app.route("/user/")
-async def get_user(request, pk):
- user = await Users.query(pk=pk)
- return response.json({"user": str(user)})
+from tortoise.contrib.sanic import register_tortoise
+app = Sanic(__name__)
-if __name__ == "__main__":
- app.run(port=5000)
+register_tortoise(
+ app, db_url="mysql://root:root@localhost/test", modules={"models": ["models"]}, generate_schemas=True
+)
```
:---
----:1
-
### 启动服务并发送请求:
-:--:1
-
```sh
curl --location --request POST 'http://127.0.0.1:8000/user'
{"users":["I am foo", "I am bar"]}
@@ -302,5 +279,3 @@ curl --location --request POST 'http://127.0.0.1:8000/user'
curl --location --request GET 'http://127.0.0.1:8000/user/1'
{"user": "I am foo"}
```
-
-:---
\ No newline at end of file
From 591d377bfedd37920fa34f8ea16b20471506d65e Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:50 +0300
Subject: [PATCH 150/776] New translations decorators.md (Korean)
---
src/ko/guide/how-to/decorators.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/decorators.md
diff --git a/src/ko/guide/how-to/decorators.md b/src/ko/guide/how-to/decorators.md
new file mode 100644
index 0000000000..9ef318134e
--- /dev/null
+++ b/src/ko/guide/how-to/decorators.md
@@ -0,0 +1 @@
+decorators
From 9242cf756950da6c99ee2a0c9937ccc83a40de47 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:52 +0300
Subject: [PATCH 151/776] New translations decorators.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/decorators.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/decorators.md
diff --git a/src/pt/guide/how-to/decorators.md b/src/pt/guide/how-to/decorators.md
new file mode 100644
index 0000000000..9ef318134e
--- /dev/null
+++ b/src/pt/guide/how-to/decorators.md
@@ -0,0 +1 @@
+decorators
From 0fd31e9581214be0c7e62e70080695a4d8b1a3b1 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:53 +0300
Subject: [PATCH 152/776] New translations mounting.md (Korean)
---
src/ko/guide/how-to/mounting.md | 52 +++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
create mode 100644 src/ko/guide/how-to/mounting.md
diff --git a/src/ko/guide/how-to/mounting.md b/src/ko/guide/how-to/mounting.md
new file mode 100644
index 0000000000..918c422cdb
--- /dev/null
+++ b/src/ko/guide/how-to/mounting.md
@@ -0,0 +1,52 @@
+# Application Mounting
+
+> How do I mount my application at some path above the root?
+
+```python
+# server.py
+from sanic import Sanic, text
+
+app = Sanic("app")
+app.config.SERVER_NAME = "example.com/api"
+
+
+@app.route("/foo")
+def handler(request):
+ url = app.url_for("handler", _external=True)
+ return text(f"URL: {url}")
+```
+
+```yaml
+# docker-compose.yml
+version: "3.7"
+services:
+ app:
+ image: nginx:alpine
+ ports:
+ - 80:80
+ volumes:
+ - type: bind
+ source: ./conf
+ target: /etc/nginx/conf.d/default.conf
+```
+
+```nginx
+# conf
+server {
+ listen 80;
+
+ # Computed data service
+ location /api/ {
+ proxy_pass http://:9999/;
+ proxy_set_header Host example.com;
+ }
+}
+```
+```bash
+$ docker-compose up -d
+$ sanic server.app --port=9999 --host=0.0.0.0
+```
+```bash
+$ curl localhost/api/foo
+URL: http://example.com/api/foo
+```
From 57d30ad6260f48d834e06159a54c6d3a28df6a6e Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:54 +0300
Subject: [PATCH 153/776] New translations mounting.md (Chinese Simplified)
---
src/zh/guide/how-to/mounting.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/zh/guide/how-to/mounting.md b/src/zh/guide/how-to/mounting.md
index 53ef3e6215..5faf22df45 100644
--- a/src/zh/guide/how-to/mounting.md
+++ b/src/zh/guide/how-to/mounting.md
@@ -42,12 +42,10 @@ server {
}
}
```
-
```bash
$ docker-compose up -d
$ sanic server.app --port=9999 --host=0.0.0.0
```
-
```bash
$ curl localhost/api/foo
URL: http://example.com/api/foo
From 07b5b99fb060e36eb06f0ff988fd711d19416527 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:55 +0300
Subject: [PATCH 154/776] New translations mounting.md (Portuguese, Brazilian)
---
src/pt/guide/how-to/mounting.md | 52 +++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
create mode 100644 src/pt/guide/how-to/mounting.md
diff --git a/src/pt/guide/how-to/mounting.md b/src/pt/guide/how-to/mounting.md
new file mode 100644
index 0000000000..918c422cdb
--- /dev/null
+++ b/src/pt/guide/how-to/mounting.md
@@ -0,0 +1,52 @@
+# Application Mounting
+
+> How do I mount my application at some path above the root?
+
+```python
+# server.py
+from sanic import Sanic, text
+
+app = Sanic("app")
+app.config.SERVER_NAME = "example.com/api"
+
+
+@app.route("/foo")
+def handler(request):
+ url = app.url_for("handler", _external=True)
+ return text(f"URL: {url}")
+```
+
+```yaml
+# docker-compose.yml
+version: "3.7"
+services:
+ app:
+ image: nginx:alpine
+ ports:
+ - 80:80
+ volumes:
+ - type: bind
+ source: ./conf
+ target: /etc/nginx/conf.d/default.conf
+```
+
+```nginx
+# conf
+server {
+ listen 80;
+
+ # Computed data service
+ location /api/ {
+ proxy_pass http://:9999/;
+ proxy_set_header Host example.com;
+ }
+}
+```
+```bash
+$ docker-compose up -d
+$ sanic server.app --port=9999 --host=0.0.0.0
+```
+```bash
+$ curl localhost/api/foo
+URL: http://example.com/api/foo
+```
From d271abfae0742a4a9e1f8395fbb44ddb7577b11d Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:56 +0300
Subject: [PATCH 155/776] New translations orm.md (Japanese)
---
src/ja/guide/how-to/orm.md | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/ja/guide/how-to/orm.md b/src/ja/guide/how-to/orm.md
index 00ea7e576e..3bf20574d1 100644
--- a/src/ja/guide/how-to/orm.md
+++ b/src/ja/guide/how-to/orm.md
@@ -2,10 +2,9 @@
> SQLAlchemyをSanicと共に使用する方法?
-すべてのORMツールはSanicで動作しますが、非同期ORMツールはSanicのパフォーマンスに影響します。
-これをサポートするormパッケージがいくつかあります。
+すべてのORMツールはSanicで動作しますが、非同期ORMツールはSanicのパフォーマンスに影響します。 これをサポートするormパッケージがいくつかあります。 There are some orm packages who support
-現在、非同期性をサポートするORMはたくさんあります。一般的なライブラリには、次の2つがあります。
+現在、非同期性をサポートするORMはたくさんあります。 一般的なライブラリには、次の2つがあります。
- [SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html)
- [tortoise-orm](https://github.com/tortoise/tortoise-orm)
@@ -14,14 +13,14 @@
## SQLAlchemy
-[SQLAlchemy 1.4関数](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html)が`asyncio`のネイティブサポートを追加したので、SanicはついにSQLAlchemyでうまく動作するようになりました。SQLAlchemyプロジェクトでは、この機能はまだ*ベータ*と見なされていることに注意してください。
+[SQLAlchemy 1.4関数](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html)が`asyncio`のネイティブサポートを追加したので、SanicはついにSQLAlchemyでうまく動作するようになりました。 SQLAlchemyプロジェクトでは、この機能はまだ*ベータ*と見なされていることに注意してください。
---:1
### 依存関係
-まず、必要な依存関係をインストールする必要があります。以前は、インストールされる依存関係は`sqlalchemy'と`pymysql'でしたが、現在は`sqlalchemy'と`aiomysql'が必要です。
+まず、必要な依存関係をインストールする必要があります。 以前は、インストールされる依存関係は`sqlalchemy'と`pymysql'でしたが、現在は`sqlalchemy'と`aiomysql'が必要です。
:--:1
@@ -76,8 +75,7 @@ class Car(BaseModel):
### Sanicアプリケーションと非同期エンジンの作成
-ここではデータベースとしてmysqlを使用しますが、PostgreSQL/SQLiteを選択することもできます。ドライバを`aiomysql`から`asyncpg`/`aiosqlite`に変更することに注意してください。
-:--:1
+ここではデータベースとしてmysqlを使用しますが、PostgreSQL/SQLiteを選択することもできます。 ドライバを`aiomysql`から`asyncpg`/`aiosqlite`に変更することに注意してください。 :--:1 :--:1
```python
From 2853244a763f8d92146eb12162fab25ad8fac6df Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:57 +0300
Subject: [PATCH 156/776] New translations orm.md (Korean)
---
src/ko/guide/how-to/orm.md | 290 +++++++++++++++++++++++++++++++++++++
1 file changed, 290 insertions(+)
create mode 100644 src/ko/guide/how-to/orm.md
diff --git a/src/ko/guide/how-to/orm.md b/src/ko/guide/how-to/orm.md
new file mode 100644
index 0000000000..86a877d3ab
--- /dev/null
+++ b/src/ko/guide/how-to/orm.md
@@ -0,0 +1,290 @@
+# ORM
+
+> How do I use SQLAlchemy with Sanic ?
+
+All ORM tools can work with Sanic, but non-async ORM tool have a impact on Sanic performance. There are some orm packages who support
+
+At present, there are many ORMs that support asynchronicity. Two of the more common libraries are:
+
+- [SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html)
+- [tortoise-orm](https://github.com/tortoise/tortoise-orm)
+
+Integration in to your Sanic application is fairly simple:
+
+## SQLAlchemy
+
+Because [SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html) has added native support for `asyncio`, Sanic can finally work well with SQLAlchemy. Be aware that this functionality is still considered *beta* by the SQLAlchemy project.
+
+
+---:1
+
+### Dependencies
+
+First, we need to install the required dependencies. In the past, the dependencies installed were `sqlalchemy` and `pymysql`, but now `sqlalchemy` and `aiomysql` are needed.
+
+:--:1
+
+```shell
+pip install -U sqlalchemy
+pip install -U aiomysql
+```
+
+:---
+
+---:1
+
+### Define ORM Model
+
+ORM model creation remains the same.
+
+:--:1
+
+```python
+# ./models.py
+from sqlalchemy import INTEGER, Column, ForeignKey, String
+from sqlalchemy.orm import declarative_base, relationship
+
+Base = declarative_base()
+
+
+class BaseModel(Base):
+ __abstract__ = True
+ id = Column(INTEGER(), primary_key=True)
+
+
+class Person(BaseModel):
+ __tablename__ = "person"
+ name = Column(String())
+ cars = relationship("Car")
+
+ def to_dict(self):
+ return {"name": self.name, "cars": [{"brand": car.brand} for car in self.cars]}
+
+
+class Car(BaseModel):
+ __tablename__ = "car"
+
+ brand = Column(String())
+ user_id = Column(ForeignKey("person.id"))
+ user = relationship("Person", back_populates="cars")
+```
+
+:---
+
+---:1
+
+### Create Sanic App and Async Engine
+
+Here we use mysql as the database, and you can also choose PostgreSQL/SQLite. Pay attention to changing the driver from `aiomysql` to `asyncpg`/`aiosqlite`. :--:1
+
+
+```python
+# ./server.py
+from sanic import Sanic
+from sqlalchemy.ext.asyncio import create_async_engine
+
+app = Sanic("my_app")
+
+bind = create_async_engine("mysql+aiomysql://root:root@localhost/test", echo=True)
+```
+
+:---
+
+---:1
+
+### Register Middlewares
+
+The request middleware creates an usable `AsyncSession` object and set it to `request.ctx` and `_base_model_session_ctx`.
+
+Thread-safe variable `_base_model_session_ctx` helps you to use the session object instead of fetching it from `request.ctx`.
+
+
+:--:1
+
+```python
+# ./server.py
+from contextvars import ContextVar
+
+from sqlalchemy.ext.asyncio import AsyncSession
+from sqlalchemy.orm import sessionmaker
+
+_base_model_session_ctx = ContextVar("session")
+
+@app.middleware("request")
+async def inject_session(request):
+ request.ctx.session = sessionmaker(bind, AsyncSession, expire_on_commit=False)()
+ request.ctx.session_ctx_token = _base_model_session_ctx.set(request.ctx.session)
+
+
+@app.middleware("response")
+async def close_session(request, response):
+ if hasattr(request.ctx, "session_ctx_token"):
+ _base_model_session_ctx.reset(request.ctx.session_ctx_token)
+ await request.ctx.session.close()
+```
+
+:---
+
+---:1
+
+### Register Routes
+
+According to sqlalchemy official docs, `session.query` will be legacy in 2.0, and the 2.0 way to query an ORM object is using `select`.
+
+:--:1
+
+```python
+# ./server.py
+from sqlalchemy import select
+from sqlalchemy.orm import selectinload
+from sanic.response import json
+
+from models import Car, Person
+
+
+@app.post("/user")
+async def create_user(request):
+ session = request.ctx.session
+ async with session.begin():
+ car = Car(brand="Tesla")
+ person = Person(name="foo", cars=[car])
+ session.add_all([person])
+ return json(person.to_dict())
+
+
+@app.get("/user/")
+async def get_user(request, pk):
+ session = request.ctx.session
+ async with session.begin():
+ stmt = select(Person).where(Person.id == pk).options(selectinload(Person.cars))
+ result = await session.execute(stmt)
+ person = result.scalar()
+
+ if not person:
+ return json({})
+
+ return json(person.to_dict())
+```
+
+:---
+
+### Send Requests
+
+```sh
+curl --location --request POST 'http://127.0.0.1:8000/user'
+{"name":"foo","cars":[{"brand":"Tesla"}]}
+```
+
+```sh
+curl --location --request GET 'http://127.0.0.1:8000/user/1'
+{"name":"foo","cars":[{"brand":"Tesla"}]}
+```
+
+
+## Tortoise-ORM
+
+---:1
+
+### Dependencies
+
+tortoise-orm's dependency is very simple, you just need install tortoise-orm.
+
+:--:1
+
+```shell
+pip install -U tortoise-orm
+```
+
+:---
+
+---:1
+
+### Define ORM Model
+
+If you are familiar with Django, you should find this part very familiar.
+
+:--:1
+
+```python
+# ./models.py
+from tortoise import Model, fields
+
+
+class Users(Model):
+ id = fields.IntField(pk=True)
+ name = fields.CharField(50)
+
+ def __str__(self):
+ return f"I am {self.name}"
+```
+
+:---
+
+
+---:1
+
+### Create Sanic App and Async Engine
+
+Tortoise-orm provides a set of registration interface, which is convenient for users, and you can use it to create database connection easily.
+
+:--:1
+
+```python
+# ./main.py
+
+from models import Users
+from tortoise.contrib.sanic import register_tortoise
+
+app = Sanic(__name__)
+
+
+register_tortoise(
+ app, db_url="mysql://root:root@localhost/test", modules={"models": ["models"]}, generate_schemas=True
+)
+
+```
+
+:---
+
+---:1
+
+### Register Routes
+
+:--:1
+
+```python
+
+# ./main.py
+
+from models import Users
+from sanic import Sanic, response
+
+
+@app.route("/user")
+async def list_all(request):
+ users = await Users.all()
+ return response.json({"users": [str(user) for user in users]})
+
+
+@app.route("/user/")
+async def get_user(request, pk):
+ user = await Users.query(pk=pk)
+ return response.json({"user": str(user)})
+
+if __name__ == "__main__":
+ app.run(port=5000)
+```
+
+:---
+
+### Send Requests
+
+```sh
+curl --location --request POST 'http://127.0.0.1:8000/user'
+{"users":["I am foo", "I am bar"]}
+```
+
+```sh
+curl --location --request GET 'http://127.0.0.1:8000/user/1'
+{"user": "I am foo"}
+```
From 62328015803b9308a2fac7ee736c3d4a17546718 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:58 +0300
Subject: [PATCH 157/776] New translations orm.md (Portuguese, Brazilian)
---
src/pt/guide/how-to/orm.md | 290 +++++++++++++++++++++++++++++++++++++
1 file changed, 290 insertions(+)
create mode 100644 src/pt/guide/how-to/orm.md
diff --git a/src/pt/guide/how-to/orm.md b/src/pt/guide/how-to/orm.md
new file mode 100644
index 0000000000..86a877d3ab
--- /dev/null
+++ b/src/pt/guide/how-to/orm.md
@@ -0,0 +1,290 @@
+# ORM
+
+> How do I use SQLAlchemy with Sanic ?
+
+All ORM tools can work with Sanic, but non-async ORM tool have a impact on Sanic performance. There are some orm packages who support
+
+At present, there are many ORMs that support asynchronicity. Two of the more common libraries are:
+
+- [SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html)
+- [tortoise-orm](https://github.com/tortoise/tortoise-orm)
+
+Integration in to your Sanic application is fairly simple:
+
+## SQLAlchemy
+
+Because [SQLAlchemy 1.4](https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html) has added native support for `asyncio`, Sanic can finally work well with SQLAlchemy. Be aware that this functionality is still considered *beta* by the SQLAlchemy project.
+
+
+---:1
+
+### Dependencies
+
+First, we need to install the required dependencies. In the past, the dependencies installed were `sqlalchemy` and `pymysql`, but now `sqlalchemy` and `aiomysql` are needed.
+
+:--:1
+
+```shell
+pip install -U sqlalchemy
+pip install -U aiomysql
+```
+
+:---
+
+---:1
+
+### Define ORM Model
+
+ORM model creation remains the same.
+
+:--:1
+
+```python
+# ./models.py
+from sqlalchemy import INTEGER, Column, ForeignKey, String
+from sqlalchemy.orm import declarative_base, relationship
+
+Base = declarative_base()
+
+
+class BaseModel(Base):
+ __abstract__ = True
+ id = Column(INTEGER(), primary_key=True)
+
+
+class Person(BaseModel):
+ __tablename__ = "person"
+ name = Column(String())
+ cars = relationship("Car")
+
+ def to_dict(self):
+ return {"name": self.name, "cars": [{"brand": car.brand} for car in self.cars]}
+
+
+class Car(BaseModel):
+ __tablename__ = "car"
+
+ brand = Column(String())
+ user_id = Column(ForeignKey("person.id"))
+ user = relationship("Person", back_populates="cars")
+```
+
+:---
+
+---:1
+
+### Create Sanic App and Async Engine
+
+Here we use mysql as the database, and you can also choose PostgreSQL/SQLite. Pay attention to changing the driver from `aiomysql` to `asyncpg`/`aiosqlite`. :--:1
+
+
+```python
+# ./server.py
+from sanic import Sanic
+from sqlalchemy.ext.asyncio import create_async_engine
+
+app = Sanic("my_app")
+
+bind = create_async_engine("mysql+aiomysql://root:root@localhost/test", echo=True)
+```
+
+:---
+
+---:1
+
+### Register Middlewares
+
+The request middleware creates an usable `AsyncSession` object and set it to `request.ctx` and `_base_model_session_ctx`.
+
+Thread-safe variable `_base_model_session_ctx` helps you to use the session object instead of fetching it from `request.ctx`.
+
+
+:--:1
+
+```python
+# ./server.py
+from contextvars import ContextVar
+
+from sqlalchemy.ext.asyncio import AsyncSession
+from sqlalchemy.orm import sessionmaker
+
+_base_model_session_ctx = ContextVar("session")
+
+@app.middleware("request")
+async def inject_session(request):
+ request.ctx.session = sessionmaker(bind, AsyncSession, expire_on_commit=False)()
+ request.ctx.session_ctx_token = _base_model_session_ctx.set(request.ctx.session)
+
+
+@app.middleware("response")
+async def close_session(request, response):
+ if hasattr(request.ctx, "session_ctx_token"):
+ _base_model_session_ctx.reset(request.ctx.session_ctx_token)
+ await request.ctx.session.close()
+```
+
+:---
+
+---:1
+
+### Register Routes
+
+According to sqlalchemy official docs, `session.query` will be legacy in 2.0, and the 2.0 way to query an ORM object is using `select`.
+
+:--:1
+
+```python
+# ./server.py
+from sqlalchemy import select
+from sqlalchemy.orm import selectinload
+from sanic.response import json
+
+from models import Car, Person
+
+
+@app.post("/user")
+async def create_user(request):
+ session = request.ctx.session
+ async with session.begin():
+ car = Car(brand="Tesla")
+ person = Person(name="foo", cars=[car])
+ session.add_all([person])
+ return json(person.to_dict())
+
+
+@app.get("/user/")
+async def get_user(request, pk):
+ session = request.ctx.session
+ async with session.begin():
+ stmt = select(Person).where(Person.id == pk).options(selectinload(Person.cars))
+ result = await session.execute(stmt)
+ person = result.scalar()
+
+ if not person:
+ return json({})
+
+ return json(person.to_dict())
+```
+
+:---
+
+### Send Requests
+
+```sh
+curl --location --request POST 'http://127.0.0.1:8000/user'
+{"name":"foo","cars":[{"brand":"Tesla"}]}
+```
+
+```sh
+curl --location --request GET 'http://127.0.0.1:8000/user/1'
+{"name":"foo","cars":[{"brand":"Tesla"}]}
+```
+
+
+## Tortoise-ORM
+
+---:1
+
+### Dependencies
+
+tortoise-orm's dependency is very simple, you just need install tortoise-orm.
+
+:--:1
+
+```shell
+pip install -U tortoise-orm
+```
+
+:---
+
+---:1
+
+### Define ORM Model
+
+If you are familiar with Django, you should find this part very familiar.
+
+:--:1
+
+```python
+# ./models.py
+from tortoise import Model, fields
+
+
+class Users(Model):
+ id = fields.IntField(pk=True)
+ name = fields.CharField(50)
+
+ def __str__(self):
+ return f"I am {self.name}"
+```
+
+:---
+
+
+---:1
+
+### Create Sanic App and Async Engine
+
+Tortoise-orm provides a set of registration interface, which is convenient for users, and you can use it to create database connection easily.
+
+:--:1
+
+```python
+# ./main.py
+
+from models import Users
+from tortoise.contrib.sanic import register_tortoise
+
+app = Sanic(__name__)
+
+
+register_tortoise(
+ app, db_url="mysql://root:root@localhost/test", modules={"models": ["models"]}, generate_schemas=True
+)
+
+```
+
+:---
+
+---:1
+
+### Register Routes
+
+:--:1
+
+```python
+
+# ./main.py
+
+from models import Users
+from sanic import Sanic, response
+
+
+@app.route("/user")
+async def list_all(request):
+ users = await Users.all()
+ return response.json({"users": [str(user) for user in users]})
+
+
+@app.route("/user/")
+async def get_user(request, pk):
+ user = await Users.query(pk=pk)
+ return response.json({"user": str(user)})
+
+if __name__ == "__main__":
+ app.run(port=5000)
+```
+
+:---
+
+### Send Requests
+
+```sh
+curl --location --request POST 'http://127.0.0.1:8000/user'
+{"users":["I am foo", "I am bar"]}
+```
+
+```sh
+curl --location --request GET 'http://127.0.0.1:8000/user/1'
+{"user": "I am foo"}
+```
From 9bc446af43f572fbd0c04064e84b730ea58dfa28 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:45:59 +0300
Subject: [PATCH 158/776] New translations static-redirects.md (Chinese
Simplified)
---
src/zh/guide/how-to/static-redirects.md | 110 ++++++++++++++++++++++++
1 file changed, 110 insertions(+)
create mode 100644 src/zh/guide/how-to/static-redirects.md
diff --git a/src/zh/guide/how-to/static-redirects.md b/src/zh/guide/how-to/static-redirects.md
new file mode 100644
index 0000000000..5566050c74
--- /dev/null
+++ b/src/zh/guide/how-to/static-redirects.md
@@ -0,0 +1,110 @@
+# "Static" Redirects
+
+> How do I configure static redirects?
+
+:::: tabs
+::: tab app.py
+```python
+### SETUP ###
+import typing
+import sanic, sanic.response
+
+# Create the Sanic app
+app = sanic.Sanic(__name__)
+
+# This dictionary represents your "static"
+# redirects. For example, these values
+# could be pulled from a configuration file.
+REDIRECTS = {
+ '/':'/hello_world', # Redirect '/' to '/hello_world'
+ '/hello_world':'/hello_world.html' # Redirect '/hello_world' to 'hello_world.html'
+}
+
+# This function will return another function
+# that will return the configured value
+# regardless of the arguments passed to it.
+def get_static_function(value:typing.Any) -> typing.Callable[..., typing.Any]:
+ return lambda *_, **__: value
+
+### ROUTING ###
+# Iterate through the redirects
+for src, dest in REDIRECTS.items():
+ # Create the redirect response object
+ response:sanic.HTTPResponse = sanic.response.redirect(dest)
+
+ # Create the handler function. Typically,
+ # only a sanic.Request object is passed
+ # to the function. This object will be
+ # ignored.
+ handler = get_static_function(response)
+
+ # Route the src path to the handler
+ app.route(src)(handler)
+
+# Route some file and client resources
+app.static('/files/', 'files')
+app.static('/', 'client')
+
+### RUN ###
+if __name__ == '__main__':
+ app.run(
+ '127.0.0.1',
+ 10000
+ )
+```
+:::
+
+::: tab client/hello_world.html
+```html
+
+
+
+
+
+
+ Hello World
+
+
+
+
+ Hello world!
+
+
+
+```
+:::
+
+::: tab client/hello_world.css
+```css
+#hello_world {
+ width: 1000px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 100px;
+
+ padding: 100px;
+ color: aqua;
+ text-align: center;
+ font-size: 100px;
+ font-family: monospace;
+
+ background-color: rgba(0, 0, 0, 0.75);
+
+ border-radius: 10px;
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.75);
+}
+
+body {
+ background-image: url("/files/lake.jpg");
+ background-repeat: no-repeat;
+ background-size: cover;
+}
+```
+:::
+
+::: tab files/lake.jpg  :::
+::::
+
+Also, checkout some resources from the community:
+
+- [Static Routing Example](https://github.com/Perzan/sanic-static-routing-example)
From 3279d61c2834e58b8f84130e62437d3a6f3edb49 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:01 +0300
Subject: [PATCH 159/776] New translations serialization.md (Korean)
---
src/ko/guide/how-to/serialization.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/serialization.md
diff --git a/src/ko/guide/how-to/serialization.md b/src/ko/guide/how-to/serialization.md
new file mode 100644
index 0000000000..0dfc62d35b
--- /dev/null
+++ b/src/ko/guide/how-to/serialization.md
@@ -0,0 +1 @@
+# Serialization
From 60b3610bcfd23b69948750d4049284720d2b0cf2 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:03 +0300
Subject: [PATCH 160/776] New translations serialization.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/serialization.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/serialization.md
diff --git a/src/pt/guide/how-to/serialization.md b/src/pt/guide/how-to/serialization.md
new file mode 100644
index 0000000000..0dfc62d35b
--- /dev/null
+++ b/src/pt/guide/how-to/serialization.md
@@ -0,0 +1 @@
+# Serialization
From 762b8c5461b0364b369167739289f2c90e1edadb Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:04 +0300
Subject: [PATCH 161/776] New translations server-sent-events.md (Korean)
---
src/ko/guide/how-to/server-sent-events.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/guide/how-to/server-sent-events.md
diff --git a/src/ko/guide/how-to/server-sent-events.md b/src/ko/guide/how-to/server-sent-events.md
new file mode 100644
index 0000000000..7daf86745e
--- /dev/null
+++ b/src/ko/guide/how-to/server-sent-events.md
@@ -0,0 +1 @@
+sse
From 054c5d05a19b5d34083e2938531ec2957729c70b Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:06 +0300
Subject: [PATCH 162/776] New translations server-sent-events.md (Portuguese,
Brazilian)
---
src/pt/guide/how-to/server-sent-events.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/guide/how-to/server-sent-events.md
diff --git a/src/pt/guide/how-to/server-sent-events.md b/src/pt/guide/how-to/server-sent-events.md
new file mode 100644
index 0000000000..7daf86745e
--- /dev/null
+++ b/src/pt/guide/how-to/server-sent-events.md
@@ -0,0 +1 @@
+sse
From 969c1ec24d3c05311a74ffb3dc80d1f602b46406 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:07 +0300
Subject: [PATCH 163/776] New translations static-redirects.md (Japanese)
---
src/ja/guide/how-to/static-redirects.md | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/src/ja/guide/how-to/static-redirects.md b/src/ja/guide/how-to/static-redirects.md
index deffd6d200..713abc5032 100644
--- a/src/ja/guide/how-to/static-redirects.md
+++ b/src/ja/guide/how-to/static-redirects.md
@@ -22,8 +22,7 @@ REDIRECTS = {
# This function will return another function
# that will return the configured value
-# regardless of the arguments passed to it.
-def get_static_function(value:typing.Any) -> typing.Callable[..., typing.Any]:
+# regardless of the arguments passed to it. def get_static_function(value:typing.Any) -> typing.Callable[..., typing.Any]:
return lambda *_, **__: value
### ROUTING ###
@@ -102,9 +101,7 @@ body {
```
:::
-::: tab files/lake.jpg
-
-:::
+::: tab files/lake.jpg  :::
::::
また、コミュニティからいくつかのリソースをチェックアウトします。
From f79754c5db5e3204573bdb70c124b66e770ec823 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:08 +0300
Subject: [PATCH 164/776] New translations static-redirects.md (Korean)
---
src/ko/guide/how-to/static-redirects.md | 110 ++++++++++++++++++++++++
1 file changed, 110 insertions(+)
create mode 100644 src/ko/guide/how-to/static-redirects.md
diff --git a/src/ko/guide/how-to/static-redirects.md b/src/ko/guide/how-to/static-redirects.md
new file mode 100644
index 0000000000..5566050c74
--- /dev/null
+++ b/src/ko/guide/how-to/static-redirects.md
@@ -0,0 +1,110 @@
+# "Static" Redirects
+
+> How do I configure static redirects?
+
+:::: tabs
+::: tab app.py
+```python
+### SETUP ###
+import typing
+import sanic, sanic.response
+
+# Create the Sanic app
+app = sanic.Sanic(__name__)
+
+# This dictionary represents your "static"
+# redirects. For example, these values
+# could be pulled from a configuration file.
+REDIRECTS = {
+ '/':'/hello_world', # Redirect '/' to '/hello_world'
+ '/hello_world':'/hello_world.html' # Redirect '/hello_world' to 'hello_world.html'
+}
+
+# This function will return another function
+# that will return the configured value
+# regardless of the arguments passed to it.
+def get_static_function(value:typing.Any) -> typing.Callable[..., typing.Any]:
+ return lambda *_, **__: value
+
+### ROUTING ###
+# Iterate through the redirects
+for src, dest in REDIRECTS.items():
+ # Create the redirect response object
+ response:sanic.HTTPResponse = sanic.response.redirect(dest)
+
+ # Create the handler function. Typically,
+ # only a sanic.Request object is passed
+ # to the function. This object will be
+ # ignored.
+ handler = get_static_function(response)
+
+ # Route the src path to the handler
+ app.route(src)(handler)
+
+# Route some file and client resources
+app.static('/files/', 'files')
+app.static('/', 'client')
+
+### RUN ###
+if __name__ == '__main__':
+ app.run(
+ '127.0.0.1',
+ 10000
+ )
+```
+:::
+
+::: tab client/hello_world.html
+```html
+
+
+
+
+
+
+ Hello World
+
+
+
+
+ Hello world!
+
+
+
+```
+:::
+
+::: tab client/hello_world.css
+```css
+#hello_world {
+ width: 1000px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 100px;
+
+ padding: 100px;
+ color: aqua;
+ text-align: center;
+ font-size: 100px;
+ font-family: monospace;
+
+ background-color: rgba(0, 0, 0, 0.75);
+
+ border-radius: 10px;
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.75);
+}
+
+body {
+ background-image: url("/files/lake.jpg");
+ background-repeat: no-repeat;
+ background-size: cover;
+}
+```
+:::
+
+::: tab files/lake.jpg  :::
+::::
+
+Also, checkout some resources from the community:
+
+- [Static Routing Example](https://github.com/Perzan/sanic-static-routing-example)
From 7a9c3c9611dc4f185f566ca84d6ea9077571d9f5 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:09 +0300
Subject: [PATCH 165/776] New translations v21.12.md (Portuguese, Brazilian)
---
src/pt/guide/release-notes/v21.12.md | 486 +++++++++++++++++++++++++++
1 file changed, 486 insertions(+)
create mode 100644 src/pt/guide/release-notes/v21.12.md
diff --git a/src/pt/guide/release-notes/v21.12.md b/src/pt/guide/release-notes/v21.12.md
new file mode 100644
index 0000000000..d2a443b404
--- /dev/null
+++ b/src/pt/guide/release-notes/v21.12.md
@@ -0,0 +1,486 @@
+# Version 21.12 (LTS)
+
+[[toc]]
+
+## Introduction
+
+This is the final release of the version 21 [release cycle](../../org/policies.md#release-schedule). Version 21 will now enter long-term support and will be supported for two years until December 2023.
+
+## What to know
+
+More details in the [Changelog](https://sanic.readthedocs.io/en/stable/sanic/changelog.html). Notable new or breaking features, and what to upgrade...
+
+### Strict application and blueprint names
+
+In [v21.6](./v21.6.md#stricter-application-and-blueprint-names-and-deprecation) application and blueprint names were required to conform to a new set of restrictions. That change is now being enforced at startup time.
+
+Names **must**:
+
+1. Only use alphanumeric characters (`a-zA-Z0-9`)
+2. May contain a hyphen (`-`) or an underscore (`_`)
+3. Must begin with a letter or underscore (`a-zA-Z_`)
+
+### Strict application and blueprint properties
+
+The old leniency to allow directly setting properties of a `Sanic` or `Blueprint` object was deprecated and no longer allowed. You must use the `ctx` object.
+
+```python
+app = Sanic("MyApp")
+app.ctx.db = Database()
+```
+
+### Removals
+
+The following deprecated features no longer exist:
+
+- `sanic.exceptions.abort`
+- `sanic.views.CompositionView`
+- `sanic.response.StreamingHTTPResponse`
+
+### Upgrade your streaming responses (if not already)
+
+The `sanic.response.stream` response method has been **deprecated** and will be removed in v22.6. If you are sill using an old school streaming response, please upgrade it.
+
+**OLD - Deprecated**
+
+```python
+async def sample_streaming_fn(response):
+ await response.write("foo,")
+ await response.write("bar")
+
+@app.route("/")
+async def test(request: Request):
+ return stream(sample_streaming_fn, content_type="text/csv")
+```
+
+**Current**
+
+```python
+async def sample_streaming_fn(response):
+ await response.write("foo,")
+ await response.write("bar")
+
+@app.route("/")
+async def test(request: Request):
+ response = await request.respond(content_type="text/csv")
+ await response.send("foo,")
+ await response.send("bar")
+```
+
+### CLI overhaul and MOTD (Message of the Day)
+
+The Sanic CLI has received a fairly extensive upgrade. It adds a bunch of new features to make it on par with `app.run()`. It also includes a new MOTD display to provide quick, at-a-glance highlights about your running environment. The MOTD is TTY-aware, and therefore will be less verbose in server logs. It is mainly intended as a convenience during application development.
+
+```
+$ sanic --help
+usage: sanic [-h] [--version] [--factory] [-s] [-H HOST] [-p PORT] [-u UNIX] [--cert CERT] [--key KEY] [--tls DIR] [--tls-strict-host]
+ [-w WORKERS | --fast] [--access-logs | --no-access-logs] [--debug] [-d] [-r] [-R PATH] [--motd | --no-motd] [-v]
+ [--noisy-exceptions | --no-noisy-exceptions]
+ module
+
+ ▄███ █████ ██ ▄█▄ ██ █ █ ▄██████████
+ ██ █ █ █ ██ █ █ ██
+ ▀███████ ███▄ ▀ █ █ ██ ▄ █ ██
+ ██ █████████ █ ██ █ █ ▄▄
+ ████ ████████▀ █ █ █ ██ █ ▀██ ███████
+
+ To start running a Sanic application, provide a path to the module, where
+ app is a Sanic() instance:
+
+ $ sanic path.to.server:app
+
+ Or, a path to a callable that returns a Sanic() instance:
+
+ $ sanic path.to.factory:create_app --factory
+
+ Or, a path to a directory to run as a simple HTTP server:
+
+ $ sanic ./path/to/static --simple
+
+Required
+========
+ Positional:
+ module Path to your Sanic app. Example: path.to.server:app
+ If running a Simple Server, path to directory to serve. Example: ./
+
+Optional
+========
+ General:
+ -h, --help show this help message and exit
+ --version show program's version number and exit
+
+ Application:
+ --factory Treat app as an application factory, i.e. a () -> callable
+ -s, --simple Run Sanic as a Simple Server, and serve the contents of a directory
+ (module arg should be a path)
+
+ Socket binding:
+ -H HOST, --host HOST Host address [default 127.0.0.1]
+ -p PORT, --port PORT Port to serve on [default 8000]
+ -u UNIX, --unix UNIX location of unix socket
+
+ TLS certificate:
+ --cert CERT Location of fullchain.pem, bundle.crt or equivalent
+ --key KEY Location of privkey.pem or equivalent .key file
+ --tls DIR TLS certificate folder with fullchain.pem and privkey.pem
+ May be specified multiple times to choose multiple certificates
+ --tls-strict-host Only allow clients that send an SNI matching server certs
+
+ Worker:
+ -w WORKERS, --workers WORKERS Number of worker processes [default 1]
+ --fast Set the number of workers to max allowed
+ --access-logs Display access logs
+ --no-access-logs No display access logs
+
+ Development:
+ --debug Run the server in debug mode
+ -d, --dev Currently is an alias for --debug. But starting in v22.3,
+ --debug will no longer automatically trigger auto_restart.
+ However, --dev will continue, effectively making it the
+ same as debug + auto_reload.
+ -r, --reload, --auto-reload Watch source directory for file changes and reload on changes
+ -R PATH, --reload-dir PATH Extra directories to watch and reload on changes
+
+ Output:
+ --motd Show the startup display
+ --no-motd No show the startup display
+ -v, --verbosity Control logging noise, eg. -vv or --verbosity=2 [default 0]
+ --noisy-exceptions Output stack traces for all exceptions
+ --no-noisy-exceptions No output stack traces for all exceptions
+```
+
+### Server running modes and changes coming to `debug`
+
+There are now two running modes: `DEV` and `PRODUCTION`. By default, Sanic server will run under `PRODUCTION` mode. This is intended for deployments.
+
+Currently, `DEV` mode will operate very similarly to how `debug=True` does in older Sanic versions. However, in v22.3. `debug=True` will **no longer** enable auto-reload. If you would like to have debugging and auto-reload, you should enable `DEV` mode.
+
+**DEVELOPMENT**
+
+```
+$ sanic server:app --dev
+```
+
+```python
+app.run(debug=True, auto_reload=True)
+```
+
+**PRODUCTION**
+
+```
+$ sanic server:app
+```
+
+```python
+app.run()
+```
+
+Beginning in v22.3, `PRODUCTION` mode will no longer enable access logs by default.
+
+A summary of the changes are as follows:
+
+| Flag | Mode | Tracebacks | Logging | Access logs | Reload | Max workers |
+| ------- | ----- | ---------- | ------- | ----------- | ------ | ----------- |
+| --debug | DEBUG | yes | DEBUG | yes | ^1 | |
+| | PROD | no | INFO ^2 | ^3 | | |
+| --dev | DEBUG | yes | DEBUG | yes | yes | |
+| --fast | | | | | | yes |
+
+
+- ^1 `--debug` to deprecate auto-reloading and remove in 22.3
+- ^2 After 22.3 this moves to WARNING
+- ^3 After 22.3: no
+
+### Max allowed workers
+
+You can easily spin up the maximum number of allowed workers using `--fast`.
+
+```
+$ sanic server:app --fast
+```
+
+```python
+app.run(fast=True)
+```
+
+### First-class Sanic Extensions support
+
+[Sanic Extensions](../../plugins/sanic-ext/getting-started.md) provides a number of additional features specifically intended for API developers. You can now easily implement all of the functionality it has to offer without additional setup as long as the package is in the environment. These features include:
+
+- Auto create `HEAD`, `OPTIONS`, and `TRACE` endpoints
+- CORS protection
+- Predefined, endpoint-specific response serializers
+- Dependency injection into route handlers
+- OpenAPI documentation with Redoc and/or Swagger
+- Request query arguments and body input validation
+
+The preferred method is to install it along with Sanic, but you can also install the packages on their own.
+
+---:1
+```
+$ pip install sanic[ext]
+```
+
+:--:1
+
+```
+$ pip install sanic sanic-ext
+```
+
+:---
+
+After that, no additional configuration is required. Sanic Extensions will be attached to your application and provide all of the additional functionality with **no further configuration**.
+
+If you want to change how it works, or provide additional configuration, you can change Sanic extensions using `app.extend`. The following examples are equivalent. The `Config` object is to provide helpful type annotations for IDE development.
+
+---:1
+```python
+# This is optional, not required
+app = Sanic("MyApp")
+app.extend(config={"oas_url_prefix": "/apidocs"})
+```
+:--:
+```python
+# This is optional, not required
+app = Sanic("MyApp")
+app.config.OAS_URL_PREFIX = "/apidocs"
+```
+:---
+
+---:1
+```python
+# This is optional, not required
+from sanic_ext import Config
+
+app = Sanic("MyApp")
+app.extend(config=Config(oas_url_prefix="/apidocs"))
+```
+:--:
+
+:---
+
+### Contextual exceptions
+
+In [v21.9](./v21.9.md#default-exception-messages) we added default messages to exceptions that simplify the ability to consistently raise exceptions throughout your application.
+
+```python
+class TeapotError(SanicException):
+ status_code = 418
+ message = "Sorry, I cannot brew coffee"
+
+raise TeapotError
+```
+
+But this lacked two things:
+
+1. A dynamic and predictable message format
+2. The ability to add additional context to an error message (more on this in a moment)
+
+The current release allows any Sanic exception to have additional information to when raised to provide context when writing an error message:
+
+```python
+class TeapotError(SanicException):
+ status_code = 418
+
+ @property
+ def message(self):
+ return f"Sorry {self.extra['name']}, I cannot make you coffee"
+
+raise TeapotError(extra={"name": "Adam"})
+```
+
+The new feature allows the passing of `extra` meta to the exception instance. This `extra` info object **will be suppressed** when in `PRODUCTION` mode, but displayed in `DEVELOPMENT` mode.
+
+---:1 **PRODUCTION**
+
+ :--:1 **DEVELOPMENT**
+
+ :---
+
+Getting back to item 2 from above: _The ability to add additional context to an error message_
+
+This is particularly useful when creating microservices or an API that you intend to pass error messages back in JSON format. In this use case, we want to have some context around the exception beyond just a parseable error message to return details to the client.
+
+
+```python
+raise TeapotError(context={"foo": "bar"})
+```
+
+This is information **that we want** to always be passed in the error (when it is available). Here is what it should look like:
+
+---:1 **PRODUCTION**
+
+```json
+{
+ "description": "I'm a teapot",
+ "status": 418,
+ "message": "Sorry Adam, I cannot make you coffee",
+ "context": {
+ "foo": "bar"
+ }
+}
+```
+:--:1 **DEVELOPMENT**
+
+```json
+{
+ "description": "I'm a teapot",
+ "status": 418,
+ "message": "Sorry Adam, I cannot make you coffee",
+ "context": {
+ "foo": "bar"
+ },
+ "extra": {
+ "name": "Adam",
+ "more": "lines",
+ "complex": {
+ "one": "two"
+ }
+ },
+ "path": "/",
+ "args": {},
+ "exceptions": [
+ {
+ "type": "TeapotError",
+ "exception": "Sorry Adam, I cannot make you coffee",
+ "frames": [
+ {
+ "file": "handle_request",
+ "line": 83,
+ "name": "handle_request",
+ "src": ""
+ },
+ {
+ "file": "/tmp/p.py",
+ "line": 17,
+ "name": "handler",
+ "src": "raise TeapotError("
+ }
+ ]
+ }
+ ]
+}
+```
+:---
+
+### Background task management
+
+When using the `app.add_task` method to create a background task, there now is the option to pass an optional `name` keyword argument that allows it to be fetched, or cancelled.
+
+```python
+app.add_task(dummy, name="dummy_task")
+task = app.get_task("dummy_task")
+
+app.cancel_task("dummy_task")
+```
+
+### Route context kwargs in definitions
+
+When a route is defined, you can add any number of keyword arguments with a `ctx_` prefix. These values will be injected into the route `ctx` object.
+
+```python
+@app.get("/1", ctx_label="something")
+async def handler1(request):
+ ...
+
+@app.get("/2", ctx_label="something")
+async def handler2(request):
+ ...
+
+@app.get("/99")
+async def handler99(request):
+ ...
+
+@app.on_request
+async def do_something(request):
+ if request.route.ctx.label == "something":
+ ...
+```
+
+### Blueprints can be registered at any time
+
+In previous versions of Sanic, there was a strict ordering of when a Blueprint could be attached to an application. If you ran `app.blueprint(bp)` *before* attaching all objects to the Blueprint instance, they would be missed.
+
+Now, you can attach a Blueprint at anytime and everything attached to it will be included at startup.
+
+### Noisy exceptions (force all exceptions to logs)
+
+There is a new `NOISY_EXCEPTIONS` config value. When it is `False` (which is the default), Sanic will respect the `quiet` property of any `SanicException`. This means that an exception with `quiet=True` will not be displayed to the log output.
+
+However, when setting `NOISY_EXCEPTIONS=True`, all exceptions will be logged regardless of the `quiet` value.
+
+This can be helpful when debugging.
+
+```python
+app.config.NOISY_EXCEPTIONS = True
+```
+
+### Signal events as `Enum`
+
+There is an `Enum` with all of the built-in signal values for convenience.
+
+```python
+from sanic.signals import Event
+
+@app.signal(Event.HTTP_LIFECYCLE_BEGIN)
+async def connection_opened(conn_info):
+ ...
+```
+
+### Custom type casting of environment variables
+
+By default, Sanic will convert an `int`, `float`, or a `bool` value when applying environment variables to the `config` instance. You can extend this with your own converter:
+
+```python
+app = Sanic(..., config=Config(converters=[UUID]))
+```
+
+### Disable `uvloop` by configuration value
+
+The usage of `uvloop` can be controlled by configuration value:
+
+
+```python
+app.config.USE_UVLOOP = False
+```
+
+### Run Sanic server with multiple TLS certificates
+
+Sanic can be run with multiple TLS certificates:
+
+```python
+app.run(
+ ssl=[
+ "/etc/letsencrypt/live/example.com/",
+ "/etc/letsencrypt/live/mysite.example/",
+ ]
+)
+```
+
+## News
+
+### Coming Soon: Python Web Development with Sanic
+
+A book about Sanic is coming soon by one of the core developers, [@ahopkins](https://github.com/ahopkins).
+
+Learn more at [sanicbook.com](https://sanicbook.com).
+
+> Get equipped with the practical knowledge of working with Sanic to increase the performance and scalability of your web applications. While doing that, we will level-up your development skills as you learn to customize your application to meet the changing business needs without having to significantly over-engineer the app.
+
+A portion of book proceeds goes into the Sanic Community Organization to help fund the development and operation of Sanic. So, buying the book is another way you can support Sanic.
+
+### Dark mode for the docs
+
+If you have not already noticed, this Sanic website is now available in a native dark mode. You can toggle the theme at the top right of the page.
+
+## Thank you
+
+Thank you to everyone that participated in this release: :clap:
+
+[@adarsharegmi](https://github.com/adarsharegmi) [@ahopkins](https://github.com/ahopkins) [@ashleysommer](https://github.com/ashleysommer) [@ChihweiLHBird](https://github.com/ChihweiLHBird) [@cnicodeme](https://github.com/cnicodeme) [@kianmeng](https://github.com/kianmeng) [@meysam81](https://github.com/meysam81) [@nuxion](https://github.com/nuxion) [@prryplatypus](https://github.com/prryplatypus) [@realDragonium](https://github.com/realDragonium) [@SaidBySolo](https://github.com/SaidBySolo) [@sjsadowski](https://github.com/sjsadowski) [@Tronic](https://github.com/tronic) [@Varriount](https://github.com/Varriount) [@vltr](https://github.com/vltr) [@whos4n3](https://github.com/whos4n3)
+
+And, a special thank you to [@miss85246](https://github.com/miss85246) and [@ZinkLu](https://github.com/ZinkLu) for their tremendous work keeping the documentation synced and translated into Chinese.
+
+---
+
+If you enjoy the project, please consider contributing. Of course we love code contributions, but we also love contributions in any form. Consider writing some documentation, showing off use cases, joining conversations and making your voice known, and if you are able: [financial contributions](https://opencollective.com/sanic-org/).
From 445b11d13b090e7cd7ea5493bfedb0f2f07069b1 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:10 +0300
Subject: [PATCH 166/776] New translations v21.3.md (Japanese)
---
src/ja/guide/release-notes/v21.3.md | 57 ++++++++++++++---------------
1 file changed, 28 insertions(+), 29 deletions(-)
diff --git a/src/ja/guide/release-notes/v21.3.md b/src/ja/guide/release-notes/v21.3.md
index 176c973f3e..41e85f2b93 100644
--- a/src/ja/guide/release-notes/v21.3.md
+++ b/src/ja/guide/release-notes/v21.3.md
@@ -6,17 +6,16 @@
Sanicが速くなりました。
-まあ、すでに速かったんですけどね。しかし、v21リリースの最初のイテレーションで、いくつかの主要なマイルストーンを取り入れ、目に見える改善を行いました。これらは、何年も前から温めていたアイデアを、ようやくリリースバージョンに取り入れたものです。
+まあ、すでに速かったんですけどね。 しかし、v21リリースの最初のイテレーションで、いくつかの主要なマイルストーンを取り入れ、目に見える改善を行いました。 これらは、何年も前から温めていたアイデアを、ようやくリリースバージョンに取り入れたものです。
-::: warning Breaking changes
-バージョン21.3では、多くの新機能が導入されています。しかし、いくつかの破壊的な変更も含まれています。このため、これらの変更は前回のLTSの後に導入されました。もし、削除されたものに依存している場合は、アップグレードできるようになるまで v20.12LTS を使い続ける必要があります。
+::: warning Breaking changes バージョン21.3では、多くの新機能が導入されています。 しかし、いくつかの破壊的な変更も含まれています。 このため、これらの変更は前回のLTSの後に導入されました。 もし、削除されたものに依存している場合は、アップグレードできるようになるまで v20.12LTS を使い続ける必要があります。
```bash
pip install "sanic>=20.12,<20.13"
pip freeze > requirements.txt
```
-ほとんどの典型的なインストールでは、問題なくアップグレードできるはずです。
+ほとんどの典型的なインストールでは、問題なくアップグレードできるはずです。 :::
:::
## 知っておきたいこと
@@ -25,21 +24,21 @@ pip freeze > requirements.txt
### Python 3.7以上必須
-このバージョンでPython 3.6のサポートが終了します。バージョン 20.12LTS は 2022 年 12 月の EOL まで、バージョン 19.12LTS は 2021 年 12 月の EOL まで Python 3.6 のサポートを継続します。
+このバージョンでPython 3.6のサポートが終了します。 バージョン 20.12LTS は 2022 年 12 月の EOL まで、バージョン 19.12LTS は 2021 年 12 月の EOL まで Python 3.6 のサポートを継続します。
[LTSポリシー](../project/policies.md#long-term-support-v-interim-releases)についてもっと読む。
### 一級市民としてのストリーミング
-最も大きな速度向上は、リクエストとレスポンスのサイクルを1つのフローに統一したことです。以前は、通常のサイクルとストリーミングサイクルの間に違いがありました。これは、互換性のためにAPIは同じままですが、フードの下で簡素化されました。正味の利点は、**すべての** リクエストが新しい利点を見ることができるようになったことです。
+最も大きな速度向上は、リクエストとレスポンスのサイクルを1つのフローに統一したことです。 以前は、通常のサイクルとストリーミングサイクルの間に違いがありました。 これは、互換性のためにAPIは同じままですが、フードの下で簡素化されました。 正味の利点は、**すべての** リクエストが新しい利点を見ることができるようになったことです。
[ストリーミングの変更](../advanced/streaming.md#response-streaming)についてもっと読む。
### ルーターの見直し
-古いSanicのルーターは正規表現をベースにしていました。さらに、それは実行時に修正するのが難しく、いくつかのパフォーマンスの問題をもたらした多くの癖に悩まされていました。この変更は何年もかけて行われ、現在では [起動時にルータをコンパイルされたツリーに変換する](https://community.sanicframework.org/t/a-fast-new-router/649/41)ようになっています。今年中のさらなる改良にご期待ください。
+古いSanicのルーターは正規表現をベースにしていました。 さらに、それは実行時に修正するのが難しく、いくつかのパフォーマンスの問題をもたらした多くの癖に悩まされていました。 この変更は何年もかけて行われ、現在では [起動時にルータをコンパイルされたツリーに変換する](https://community.sanicframework.org/t/a-fast-new-router/649/41)ようになっています。 今年中のさらなる改良にご期待ください。
-外向きのAPIは後方互換性を保っています。しかし、特にルーター内部の何かにアクセスしていた場合、いくつかの変更に気づくことが多いでしょう。例えば
+外向きのAPIは後方互換性を保っています。 しかし、特にルーター内部の何かにアクセスしていた場合、いくつかの変更に気づくことが多いでしょう。 例えば
1. `Router.get()` に新しい戻り値が追加されました。
2. `Route`は、`namedtuple`ではなく、ちゃんとしたクラスオブジェクトになりました。
@@ -47,13 +46,13 @@ pip freeze > requirements.txt
4. ルートにマッチする新しいパターン `` が追加されました。
5. 少なくとも1つのルートが定義されていないと、アプリケーションを起動することはできません。
-ルーターは独自のリポジトリに置かれるようになりました。[sanic-org/sanic-router](https://github.com/sanic-org/sanic-router) また、独自の [standalone package on PyPI](https://pypi.org/project/sanic-routing/) に配置されています。
+[sanic-org/sanic-router](https://github.com/sanic-org/sanic-router) また、独自の [standalone package on PyPI](https://pypi.org/project/sanic-routing/) に配置されています。
### シグナルAPI ⭐️
-_BETA機能: APIはv21.6で完成予定です_。
+__BETA機能: APIはv21.6で完成予定です_。*
-新しいルーターの副次的な利点は、それが[新しいシグナルAPI](https://github.com/sanic-org/sanic/issues/1630)をも動かす二重の役割を果たすことです。この機能は現在公開されており、おそらく公開されるAPIは最終的に変更されることはないでしょう。
+新しいルーターの副次的な利点は、それが[新しいシグナルAPI](https://github.com/sanic-org/sanic/issues/1630)をも動かす二重の役割を果たすことです。 この機能は現在公開されており、おそらく公開されるAPIは最終的に変更されることはないでしょう。
この機能の核となる考えは以下の通りです。
@@ -63,7 +62,7 @@ _BETA機能: APIはv21.6で完成予定です_。
このAPIでは、3つの新しいメソッドを導入しています。
-- `@app.signal(...)` - シグナルハンドラを定義するためのメソッドです。これは、ルートに非常によく似た外観と動作をします。シグナルがディスパッチされるたびに、このハンドラが実行されます。
+- `@app.signal(...)` - シグナルハンドラを定義するためのメソッドです。 これは、ルートに非常によく似た外観と動作をします。 シグナルがディスパッチされるたびに、このハンドラが実行されます。
- `app.event(...)` - イベントが発生するまで実行を一時停止するために、アプリケーションの任意の場所で使用できる待ち受けです。
- `app.dispatch(...)` - イベントをトリガーして、シグナルハンドラを実行させます。
@@ -90,13 +89,13 @@ async def trigger(request):
### ルートネーミング
-以前は、ルートは`route.name`と`route.endpoint`の両方で参照されていました。似たようなものですが、両者は若干異なっていました。現在では、すべてのルートは**一貫した**名前空間と参照方法を持つようになりました。
+以前は、ルートは`route.name`と`route.endpoint`の両方で参照されていました。 似たようなものですが、両者は若干異なっていました。 現在では、すべてのルートは**一貫した**名前空間と参照方法を持つようになりました。
```
.[オプショナル:<ブループリント名>.]<ハンドラ名>
```
-この新しい「名前」は、`route.name`というプロパティに割り当てられます。私たちは`route.endpoint`を非推奨としており、v21.9でこのプロパティを削除する予定です。それまでは、`route.name`のエイリアスになります。
+この新しい「名前」は、`route.name`というプロパティに割り当てられます。 私たちは`route.endpoint`を非推奨としており、v21.9でこのプロパティを削除する予定です。 それまでは、`route.name`のエイリアスになります。
また、静的ルート、websocketルート、blueprintルートなどに使用されていたネーミングプレフィックスが削除されました。
@@ -118,7 +117,7 @@ IDEのオートコンプリートを支援する新しいデコレーターを
### ルート内の引用符の解除
-非アスキー文字を使用するルートがある場合、Sanicはあなたのためにテキストを`unquote`しないでしょう。ルート定義にそうするように特別に指示する必要があります。
+非アスキー文字を使用するルートがある場合、Sanicはあなたのためにテキストを`unquote`しないでしょう。 ルート定義にそうするように特別に指示する必要があります。
```python
@app.route("/overload/", methods=["GET"], unquote=True)
@@ -133,7 +132,7 @@ assert response.text == "OK2 您好"
### `Request.match_info` を変更する。
-これまで `match_info` はマッチしたパスパラメータのデータを提供してきました。ミドルウェアなどで、これを変更できるようになりました。
+これまで `match_info` はマッチしたパスパラメータのデータを提供してきました。 ミドルウェアなどで、これを変更できるようになりました。
```python
@app.on_request
@@ -156,7 +155,7 @@ routesの引数`version`に以下のタイプが指定できるようになり
```
### ボディを使った安全なメソッド処理
-`GET`、`HEAD`、`OPTIONS`、`DELETE` のルートハンドラは、渡された HTTP のボディをデコードしません。これをオーバーライドすることができます。
+`GET`、`HEAD`、`OPTIONS`、`DELETE` のルートハンドラは、渡された HTTP のボディをデコードしません。 これをオーバーライドすることができます。
```python
@app.delete(..., ignore_body=False)
@@ -164,7 +163,7 @@ routesの引数`version`に以下のタイプが指定できるようになり
### アプリケーション、ブループリント、ブループリント・グループのパリティ
-`Sanic` クラスと `Blueprint` クラスは共通のベースを使用しています。以前は、多くの機能が重複していたため、両者の間で若干異なる実装になっていました。現在は、どちらも同じベースクラスを継承しているため、開発者やプラグインはより一貫した API を使用できるようになりました。
+`Sanic` クラスと `Blueprint` クラスは共通のベースを使用しています。 以前は、多くの機能が重複していたため、両者の間で若干異なる実装になっていました。 現在は、どちらも同じベースクラスを継承しているため、開発者やプラグインはより一貫した API を使用できるようになりました。
また、Blueprint Groups は `version` や `strict_slashes` キーワード引数のような一般的な URL 拡張をサポートするようになりました。
@@ -174,13 +173,13 @@ routesの引数`version`に以下のタイプが指定できるようになり
### `testing` ライブラリを削除
-Sanicの内部テストクライアントは削除されました。現在は独自のリポジトリに置かれています。[sanic-org/sanic-testing](https://github.com/sanic-org/sanic-testing) にあり、また、独自の [standalone package on PyPI](https://pypi.org/project/sanic-testing/) にもあります。
+Sanicの内部テストクライアントは削除されました。 現在は独自のリポジトリに置かれています。 [sanic-org/sanic-testing](https://github.com/sanic-org/sanic-testing) にあり、また、独自の [standalone package on PyPI](https://pypi.org/project/sanic-testing/) にもあります。
-`sanic-testing` がインストールされていれば、これまで通り `Sanic()` アプリケーションインスタンスで利用することができます。そのため、 ** 唯一の** 変更点は、テストスイートの要件に `sanic-testing` を追加することです。
+`sanic-testing` がインストールされていれば、これまで通り `Sanic()` アプリケーションインスタンスで利用することができます。 そのため、 ** 唯一の** 変更点は、テストスイートの要件に `sanic-testing` を追加することです。
### アプリケーションと接続レベルのコンテキスト (`ctx`) オブジェクト
-バージョン19.9で`request.ctx`APIを[追加](https://github.com/sanic-org/sanic/pull/1666/files)しました。この便利な構造により、 (例えばミドルウェアの) リクエストオブジェクトにプロパティやデータをアタッチし、 アプリケーション内の他の場所でその情報を再利用することが簡単にできるようになりました。
+バージョン19.9で`request.ctx`APIを[追加](https://github.com/sanic-org/sanic/pull/1666/files)しました。 この便利な構造により、 (例えばミドルウェアの) リクエストオブジェクトにプロパティやデータをアタッチし、 アプリケーション内の他の場所でその情報を再利用することが簡単にできるようになりました。
同様に、このコンセプトは2つの場所で拡張されています。
@@ -189,7 +188,7 @@ Sanicの内部テストクライアントは削除されました。現在は独
#### アプリケーションコンテキスト
-一般的なユースケースは、アプリのインスタンスにプロパティをアタッチすることです。一貫性を保つため、そして Sanic プロパティとの名前の衝突の問題を避けるために、`ctx` オブジェクトは現在 `Sanic` インスタンスに存在します。
+一般的なユースケースは、アプリのインスタンスにプロパティをアタッチすることです。 一貫性を保つため、そして Sanic プロパティとの名前の衝突の問題を避けるために、`ctx` オブジェクトは現在 `Sanic` インスタンスに存在します。
```python
@app.before_server_startup
@@ -203,7 +202,7 @@ async def startup_db(app, _):
#### 接続コンテキスト
-クライアントがキープアライブヘッダを送信すると、Sanicはトランスポートソケットを[一定期間オープンしたままにしようとします](../deployment/configuration.md#keep-alive-timeout)。クライアントがキープアライブヘッダを送信すると、Sanicはトランスポートソケットを一定期間オープンしたままにしようとします。そのトランスポートオブジェクトは今、`ctx`オブジェクトを利用できるようになりました。これは事実上、1つのクライアントからの複数のリクエスト(トランスポートレイヤーが再利用されている)が状態を共有することができることを意味します。
+クライアントがキープアライブヘッダを送信すると、Sanicはトランスポートソケットを[一定期間オープンしたままにしようとします](../deployment/configuration.md#keep-alive-timeout)。 そのトランスポートオブジェクトは今、`ctx`オブジェクトを利用できるようになりました。 これは事実上、1つのクライアントからの複数のリクエスト(トランスポートレイヤーが再利用されている)が状態を共有することができることを意味します。
```python
@app.on_request
@@ -226,22 +225,22 @@ request.conn_info.ctx.foo=3
::: warning
接続レベルのコンテキストは実験的な機能であり、v21.6で最終的に有効化される予定です。
-:::
+::: :::
## ニュース
### 新しいフロントページ 🎉
-ドキュメントを2つに分けました。コードベース内部のdocstringsは、これまで通りReadTheDocsにshinxのdocをビルドしていきます。しかし、それはAPIドキュメントに限定されるでしょう。新しいフロントページには、"Sanicユーザーガイド"が置かれます。
+ドキュメントを2つに分けました。 コードベース内部のdocstringsは、これまで通りReadTheDocsにshinxのdocをビルドしていきます。 しかし、それはAPIドキュメントに限定されるでしょう。 新しいフロントページには、"Sanicユーザーガイド"が置かれます。
-新しいサイトはVuepressで動作します。寄付を歓迎します。また、ドキュメントの翻訳のお手伝いも募集しています。
+新しいサイトはVuepressで動作します。 寄付を歓迎します。 また、ドキュメントの翻訳のお手伝いも募集しています。
この一環として、RTDのドキュメントもリフレッシュし、APIドキュメントのみに変更しました。
### チャットは Discord に移動
-Gitterチャットルームは廃止に一歩近づきました。その代わりに、私たちは[Discordサーバ](https://discord.gg/FARQzAEMAA)を開設しました。
+Gitterチャットルームは廃止に一歩近づきました。 その代わりに、私たちは[Discordサーバ](https://discord.gg/FARQzAEMAA)を開設しました。
### オープンコレクティブ
@@ -249,11 +248,11 @@ Sanicコミュニティ組織は、Sanicの開発を財政的に支援したい
### 2021年版リリース管理者
-2019年、2020年ともにリリースマネージャーを務めてくれた@sjsadowskiと@yunstanfordに感謝します。今年のリリースマネージャーは@ahopkinsと@vltrです。
+2019年、2020年ともにリリースマネージャーを務めてくれた@sjsadowskiと@yunstanfordに感謝します。 今年のリリースマネージャーは@ahopkinsと@vltrです。
## 謝礼
-今回のリリースに参加された皆様、ありがとうございました。:clap:
+今回のリリースに参加された皆様、ありがとうございました。 :clap:
[@ahopkins](https://github.com/ahopkins) [@akshgpt7](https://github.com/akshgpt7) [@artcg](https://github.com/artcg) [@ashleysommer](https://github.com/ashleysommer) [@elis-k](https://github.com/elis-k) [@harshanarayana](https://github.com/harshanarayana) [@sjsadowski](https://github.com/sjsadowski) [@tronic](https://github.com/tronic) [@vltr](https://github.com/vltr),
From 28e9af41d05f8217d16ba07a44fc950ef339a874 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:13 +0300
Subject: [PATCH 167/776] New translations policies.md (Korean)
---
src/ko/org/policies.md | 62 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 src/ko/org/policies.md
diff --git a/src/ko/org/policies.md b/src/ko/org/policies.md
new file mode 100644
index 0000000000..cfac9b9a5b
--- /dev/null
+++ b/src/ko/org/policies.md
@@ -0,0 +1,62 @@
+# Policies
+
+## Versioning
+
+Sanic uses [calendar versioning](https://calver.org/), aka "calver". To be more specific, the pattern follows:
+
+```
+YY.MM.MICRO
+```
+
+Generally, versions are referred to in their `YY.MM` form. The `MICRO` number indicates an incremental patch version, starting at `0`.
+
+## Release Schedule
+
+There are four (4) scheduled releases per year: March, June, September, and December. Therefore, there are four (4) released versions per year: `YY.3`, `YY.6`, `YY.9`, and `YY.12`.
+
+This release schedule provides:
+
+- a predictable release cadence,
+- relatively short development windows allowing features to be regularly released,
+- controlled [deprecations](#deprecation), and
+- consistent stability with a yearly LTS.
+
+We also use the yearly release cycle in conjunction with our governance model, covered by the [S.C.O.P.E.](./scope.md)
+
+### Long term support v Interim releases
+
+Sanic releases a long term support release (aka "LTS") once a year in December. The LTS releases receive bug fixes and security updates for **24 months**. Interim releases throughout the year occur every three months, and are supported until the subsequent release.
+
+| Version | LTS | Supported |
+| ------- | ------------- | ------------------------- |
+| 22.6 | | :white_check_mark: |
+| 22.3 | | :x: |
+| 21.12 | until 2023-12 | :white_check_mark: |
+| 21.9 | | :x: |
+| 21.6 | | :x: |
+| 21.3 | | :x: |
+| 20.12 | until 2022-12 | :ballot_box_with_check: |
+| 20.9 | | :x: |
+| 20.6 | | :x: |
+| 20.3 | | :x: |
+| 19.12 | | :x: |
+| 19.9 | | :x: |
+| 19.6 | | :x: |
+| 19.3 | | :x: |
+| 18.12 | | :x: |
+| 0.8.3 | | :x: |
+| 0.7.0 | | :x: |
+| 0.6.0 | | :x: |
+| 0.5.4 | | :x: |
+| 0.4.1 | | :x: |
+| 0.3.1 | | :x: |
+| 0.2.0 | | :x: |
+| 0.1.9 | | :x: |
+
+:ballot_box_with_check: = security fixes :white_check_mark: = full support
+
+## Deprecation
+
+Before a feature is deprecated, or breaking changes are introduced into the API, it shall be publicized and shall appear with deprecation warnings through two release cycles. No deprecations shall be made in an LTS release.
+
+Breaking changes or feature removal may happen outside of these guidelines when absolutely warranted. These circumstances should be rare. For example, it might happen when no alternative is available to curtail a major security issue.
From bf09d20e6c5426bfc79174f4a679da4a9499f417 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:14 +0300
Subject: [PATCH 168/776] New translations README.md (Korean)
---
src/ko/org/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/ko/org/README.md
diff --git a/src/ko/org/README.md b/src/ko/org/README.md
new file mode 100644
index 0000000000..dab306f45e
--- /dev/null
+++ b/src/ko/org/README.md
@@ -0,0 +1 @@
+# Project
From 4333ec3c0e5ac68ffaaf5cdc32de967c1cbb4ffa Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:16 +0300
Subject: [PATCH 169/776] New translations README.md (Portuguese, Brazilian)
---
src/pt/org/README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/pt/org/README.md
diff --git a/src/pt/org/README.md b/src/pt/org/README.md
new file mode 100644
index 0000000000..dab306f45e
--- /dev/null
+++ b/src/pt/org/README.md
@@ -0,0 +1 @@
+# Project
From 2af8b868dbcbdba5c3fd85dec2c1b3b6d460e26d Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:17 +0300
Subject: [PATCH 170/776] New translations feature_requests.md (Japanese)
---
src/ja/org/feature_requests.md | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 src/ja/org/feature_requests.md
diff --git a/src/ja/org/feature_requests.md b/src/ja/org/feature_requests.md
new file mode 100644
index 0000000000..5c57ea1f02
--- /dev/null
+++ b/src/ja/org/feature_requests.md
@@ -0,0 +1,9 @@
+# Feature Requests
+
+[Create new feature request](https://github.com/sanic-org/sanic/issues/new?assignees=&labels=feature+request&template=feature_request.md)
+
+To vote on a feature request, visit the [GitHub Issues](https://github.com/sanic-org/sanic/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22%2CRFC+sort%3Areactions-%2B1-desc) and add a reaction
+
+---
+
+
From eb17613ce4eae5d39132e1c0d58ba8c5d2409901 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:18 +0300
Subject: [PATCH 171/776] New translations feature_requests.md (Korean)
---
src/ko/org/feature_requests.md | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 src/ko/org/feature_requests.md
diff --git a/src/ko/org/feature_requests.md b/src/ko/org/feature_requests.md
new file mode 100644
index 0000000000..5c57ea1f02
--- /dev/null
+++ b/src/ko/org/feature_requests.md
@@ -0,0 +1,9 @@
+# Feature Requests
+
+[Create new feature request](https://github.com/sanic-org/sanic/issues/new?assignees=&labels=feature+request&template=feature_request.md)
+
+To vote on a feature request, visit the [GitHub Issues](https://github.com/sanic-org/sanic/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22%2CRFC+sort%3Areactions-%2B1-desc) and add a reaction
+
+---
+
+
From 58c0aee6c09ceb29479422b41f66c67bae9c4c64 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:19 +0300
Subject: [PATCH 172/776] New translations feature_requests.md (Chinese
Simplified)
---
src/zh/org/feature_requests.md | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 src/zh/org/feature_requests.md
diff --git a/src/zh/org/feature_requests.md b/src/zh/org/feature_requests.md
new file mode 100644
index 0000000000..5c57ea1f02
--- /dev/null
+++ b/src/zh/org/feature_requests.md
@@ -0,0 +1,9 @@
+# Feature Requests
+
+[Create new feature request](https://github.com/sanic-org/sanic/issues/new?assignees=&labels=feature+request&template=feature_request.md)
+
+To vote on a feature request, visit the [GitHub Issues](https://github.com/sanic-org/sanic/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22%2CRFC+sort%3Areactions-%2B1-desc) and add a reaction
+
+---
+
+
From 7b90d0458fe64e4617cb044511bbaa80740de99d Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:19 +0300
Subject: [PATCH 173/776] New translations feature_requests.md (Portuguese,
Brazilian)
---
src/pt/org/feature_requests.md | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 src/pt/org/feature_requests.md
diff --git a/src/pt/org/feature_requests.md b/src/pt/org/feature_requests.md
new file mode 100644
index 0000000000..5c57ea1f02
--- /dev/null
+++ b/src/pt/org/feature_requests.md
@@ -0,0 +1,9 @@
+# Feature Requests
+
+[Create new feature request](https://github.com/sanic-org/sanic/issues/new?assignees=&labels=feature+request&template=feature_request.md)
+
+To vote on a feature request, visit the [GitHub Issues](https://github.com/sanic-org/sanic/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22%2CRFC+sort%3Areactions-%2B1-desc) and add a reaction
+
+---
+
+
From eb148ddf9886024ba612043a43dba32fc98183b0 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:20 +0300
Subject: [PATCH 174/776] New translations policies.md (Japanese)
---
src/ja/org/policies.md | 63 ++++++++++++++++++++++--------------------
1 file changed, 33 insertions(+), 30 deletions(-)
diff --git a/src/ja/org/policies.md b/src/ja/org/policies.md
index 413752a978..c9c3f1f05f 100644
--- a/src/ja/org/policies.md
+++ b/src/ja/org/policies.md
@@ -8,13 +8,14 @@ Sanicは[カレンダーバージョン進行](https://calver.org/)、通称"cal
YY.MM.MICRO
```
-基本的に、バージョンは``YY.MM``形式で参照されます。`MICRO`番号は`0`から順番に増えるパッチバージョンを表します。
+基本的に、バージョンは`YY.MM`形式で参照されます。 `MICRO`番号は`0`から順番に増えるパッチバージョンを表します。
## リリーススケジュール
-1年につき4回(3,6,9,12月)のリリーススケジュールがあります。したがって、年間でリリースされるバージョンは、`YY.3`, `YY.6`, `YY.9`, `YY.12`の4つです。
+1年につき4回(3,6,9,12月)のリリーススケジュールがあります。 したがって、年間でリリースされるバージョンは、`YY.3`, `YY.6`, `YY.9`, `YY.12`の4つです。
このリリーススケジュールでは以下のものを提供します。
+
- 予測可能なリリース間隔、
- 機能を定期的にリリースできる比較的短い開発ウィンドウ、
- コントロールされた[非推奨通知](#deprecation)、そして、
@@ -24,36 +25,38 @@ YY.MM.MICRO
### 長期サポートと暫定リリース
-Sanicは毎年12月に長期サポートリリース(通称LTS)をリリースします。LTSリリースはバグ修正やセキュリティアップデートを**24ヶ月間**サポートします。年間を通じて中間リリースは3か月ごとに行われ、次のリリースまでサポートされます。
-
-| Version | LTS | サポート状況 |
-| ------- | ------------- | ----------------------- |
-| 21.9 | | :white_check_mark: |
-| 21.6 | | :x: |
-| 21.3 | | :x: |
-| 20.12 | 2022年12月まで | :white_check_mark: |
-| 20.9 | | :x: |
-| 20.6 | | :x: |
-| 20.3 | | :x: |
-| 19.12 | 2021年12月まで | :ballot_box_with_check: |
-| 19.9 | | :x: |
-| 19.6 | | :x: |
-| 19.3 | | :x: |
-| 18.12 | | :x: |
-| 0.8.3 | | :x: |
-| 0.7.0 | | :x: |
-| 0.6.0 | | :x: |
-| 0.5.4 | | :x: |
-| 0.4.1 | | :x: |
-| 0.3.1 | | :x: |
-| 0.2.0 | | :x: |
-| 0.1.9 | | :x: |
-
-:ballot_box_with_check: = セキュリティ/バグ修正のみ
-:white_check_mark: = フルサポート
+Sanicは毎年12月に長期サポートリリース(通称LTS)をリリースします。 LTSリリースはバグ修正やセキュリティアップデートを**24ヶ月間**サポートします。 年間を通じて中間リリースは3か月ごとに行われ、次のリリースまでサポートされます。
+
+| Version | LTS | サポート状況 |
+| ---------- | ------------- | ------------------------- |
+| 22.6 | | :white_check_mark: |
+| 22.3 | | :x: |
+| 2021年12月まで | 2022年12月まで | :white_check_mark: |
+| 21.9 | | :x: |
+| 21.6 | | :x: |
+| 21.3 | | :x: |
+| 20.12 | until 2022-12 | :ballot_box_with_check: |
+| 20.9 | | :x: |
+| 20.6 | | :x: |
+| 20.3 | | :x: |
+| 19.12 | | :x: |
+| 19.9 | | :x: |
+| 19.6 | | :x: |
+| 19.3 | | :x: |
+| 18.12 | | :x: |
+| 0.8.3 | | :x: |
+| 0.7.0 | | :x: |
+| 0.6.0 | | :x: |
+| 0.5.4 | | :x: |
+| 0.4.1 | | :x: |
+| 0.3.1 | | :x: |
+| 0.2.0 | | :x: |
+| 0.1.9 | | :x: |
+
+:ballot_box_with_check: = セキュリティ/バグ修正のみ :white_check_mark: = フルサポート
## 非推奨
機能が非推奨になる前、またはAPIに破壊的更新が導入される前に、その機能は発表され、2つのリリースサイクルを通じて非推奨の警告とともに表示されます。 LTSリリースでは非推奨になりません。
-正当な理由がある場合、これらのガイドラインの範囲外で重大な変更または機能の削除が行われる可能性があります。これらの状況は稀なはずです。たとえば、主要なセキュリティ問題を削減するための代替手段が利用できない場合などに発生する可能性があります。
+正当な理由がある場合、これらのガイドラインの範囲外で重大な変更または機能の削除が行われる可能性があります。 これらの状況は稀なはずです。 たとえば、主要なセキュリティ問題を削減するための代替手段が利用できない場合などに発生する可能性があります。
From 35b55afa8735cdb791295dba6f47939775ca8861 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:22 +0300
Subject: [PATCH 175/776] New translations policies.md (Chinese Simplified)
---
src/zh/org/policies.md | 68 +++++++++++++++++++++---------------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/src/zh/org/policies.md b/src/zh/org/policies.md
index c8d9123f8e..5b82a8aa91 100644
--- a/src/zh/org/policies.md
+++ b/src/zh/org/policies.md
@@ -2,18 +2,17 @@
## 版本号(Versioning)
-Sanic 使用 [calendar versioning](https://calver.org/),别名 "calver"。具体使用如下格式:
+Sanic 使用 [calendar versioning](https://calver.org/),别名 "calver"。 具体使用如下格式:
```
YY.MM.MICRO
```
-通常来说,版本号是以 `YY.MM` 的格式来进行编排的,小版本号表示从 `0` 开始的增量补丁。
-
+通常来说,版本号是以 `YY.MM` 的格式来进行编排的,小版本号表示从 `0` 开始的增量补丁。 The `MICRO` number indicates an incremental patch version, starting at `0`.
## 发行安排(Release Schedule)
-每年有 4 次预定发布:3月,6月,9月,12月。因此,每年发布 4 个版本:`YY.3`, `YY.6`, `YY.9` 和 `YY.12`。
+每年有 4 次预定发布:3月,6月,9月,12月。 因此,每年发布 4 个版本:`YY.3`, `YY.6`, `YY.9` 和 `YY.12`。
该发行安排提供:
@@ -26,37 +25,38 @@ YY.MM.MICRO
### 长期支持版 v 临时版本(Long term support v Interim releases)
-Sanic 将在每年的 12 月发布一次长期支持版本(TLS 版本)TLS 版本会在 24个月内得到错误修复与安全更新。每年的 3 个临时发行版本每 3 个月发行一次,并且在后续版本发布之前一直受支持。
-
-| Version | LTS | Supported |
-| ------- | ------------- | ----------------------- |
-| 21.9 | | :white_check_mark: |
-| 21.6 | | :x: |
-| 21.3 | | :x: |
-| 20.12 | 2022-12 为止 | :white_check_mark: |
-| 20.9 | | :x: |
-| 20.6 | | :x: |
-| 20.3 | | :x: |
-| 19.12 | 2021-12 为止 | :ballot_box_with_check: |
-| 19.9 | | :x: |
-| 19.6 | | :x: |
-| 19.3 | | :x: |
-| 18.12 | | :x: |
-| 0.8.3 | | :x: |
-| 0.7.0 | | :x: |
-| 0.6.0 | | :x: |
-| 0.5.4 | | :x: |
-| 0.4.1 | | :x: |
-| 0.3.1 | | :x: |
-| 0.2.0 | | :x: |
-| 0.1.9 | | :x: |
-
-:ballot_box_with_check: = 安全/错误 修复
-:white_check_mark: = 长期支持
+Sanic 将在每年的 12 月发布一次长期支持版本(TLS 版本)TLS 版本会在 24个月内得到错误修复与安全更新。 The LTS releases receive bug fixes and security updates for **24 months**. 每年的 3 个临时发行版本每 3 个月发行一次,并且在后续版本发布之前一直受支持。
+
+| Version | LTS | Supported |
+| ---------- | ------------- | ------------------------- |
+| 22.6 | | :white_check_mark: |
+| 22.3 | | :x: |
+| 2021-12 为止 | 2022-12 为止 | :white_check_mark: |
+| 21.9 | | :x: |
+| 21.6 | | :x: |
+| 21.3 | | :x: |
+| 20.12 | until 2022-12 | :ballot_box_with_check: |
+| 20.9 | | :x: |
+| 20.6 | | :x: |
+| 20.3 | | :x: |
+| 19.12 | | :x: |
+| 19.9 | | :x: |
+| 19.6 | | :x: |
+| 19.3 | | :x: |
+| 18.12 | | :x: |
+| 0.8.3 | | :x: |
+| 0.7.0 | | :x: |
+| 0.6.0 | | :x: |
+| 0.5.4 | | :x: |
+| 0.4.1 | | :x: |
+| 0.3.1 | | :x: |
+| 0.2.0 | | :x: |
+| 0.1.9 | | :x: |
+
+:ballot_box_with_check: = 安全/错误 修复 :white_check_mark: = 长期支持
## 弃用(Deprecation)
-在一个特性被否决之前,或者在接口中引入突破性的变化之前,它应该被公开,并在两个发布周期中出现弃用警告。在LTS版本中不得有任何弃用行为。
-
-绝对必要时,可能会在这些准则之外发生中断更新或功能删除的状况。这些情况应该很少见。例如,当没有替代方案来解决重大安全问题时,就可能发生这种情况。
+在一个特性被否决之前,或者在接口中引入突破性的变化之前,它应该被公开,并在两个发布周期中出现弃用警告。 在LTS版本中不得有任何弃用行为。
+绝对必要时,可能会在这些准则之外发生中断更新或功能删除的状况。 这些情况应该很少见。 例如,当没有替代方案来解决重大安全问题时,就可能发生这种情况。
From c107d36d7068d4e04bdcb200940009661b5ae4b7 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:23 +0300
Subject: [PATCH 176/776] New translations getting-started.md (Chinese
Simplified)
---
src/zh/guide/getting-started.md | 44 ++++++++++-----------------------
1 file changed, 13 insertions(+), 31 deletions(-)
diff --git a/src/zh/guide/getting-started.md b/src/zh/guide/getting-started.md
index b0de667300..2ea7bd09f8 100644
--- a/src/zh/guide/getting-started.md
+++ b/src/zh/guide/getting-started.md
@@ -1,6 +1,6 @@
# 快速开始(Getting Started)
-在我们开始之前,请确保您使用的是 Python3.7 或更高版本。目前已知可以使用的 Python 版本包括:3.7,3.8 和 3.9。
+在我们开始之前,请确保您使用的是 Python3.7 或更高版本。 目前已知可以使用的 Python 版本包括:3.7,3.8 和 3.9。
## 安装(Install)
@@ -14,11 +14,9 @@ pip install sanic
如果您熟悉其他任意一款基于装饰器的框架,那么您可能对此感觉有些亲切。
-::: tip 小提示
+如果您来自 Flask 或其他框架,则需要指出一些重要的事情。 请记住,Sanic 旨在提高性能、灵活性和易用性。 这些指导原则对 API 及其工作方式产生了重要影响。 :::
-如果您来自 Flask 或其他框架,则需要指出一些重要的事情。 请记住,Sanic 旨在提高性能、灵活性和易用性。 这些指导原则对 API 及其工作方式产生了重要影响。
-:::
:--:1
@@ -37,39 +35,27 @@ async def hello_world(request):
### 注意(Important to note)
-- 每一个请求响应函数都可以使用同步方式(`def hello_world`)和异步方式(`async def hello_world`)进行声明。除非您有一个明确的需求和完善的使用方法,否则的话,请尽量使用 `async` 来声明响应函数。
-
-- `request` 对象始终是响应函数的第一个参数。 其他框架在需要导入的上下文变量中进行传递。 在 `async` 的世界里,如果使用隐式传递,那么它将无法完美的运行,更何况还要兼顾简洁且高效的表现形式。所以我们在这里进行显式传递。
-
-- 您 **必须** 使用 `Response` 或继承自 `Response` 的类作为响应类型。在许多其他框架中,它们允许您使用诸如 `return "Hello World"` 或者 `return {"foo":"bar"}` 的方式来进行返回,但是为了执行这类隐式调用,需要在响应流程中的某个位置花费大量的时间来确定您到底想要表达什么意思。因此,我们以轻松调用为代价,来提升服务的响应速度,Sanic 会要求您对您的响应进行显式调用。
+- 每一个请求响应函数都可以使用同步方式(`def hello_world`)和异步方式(`async def hello_world`)进行声明。 除非您有一个明确的需求和完善的使用方法,否则的话,请尽量使用 `async` 来声明响应函数。
+- `request` 对象始终是响应函数的第一个参数。 其他框架在需要导入的上下文变量中进行传递。 在 `async` 的世界里,如果使用隐式传递,那么它将无法完美的运行,更何况还要兼顾简洁且高效的表现形式。
+- 您 **必须** 使用 `Response` 或继承自 `Response` 的类作为响应类型。 在许多其他框架中,它们允许您使用诸如 `return "Hello World"` 或者 `return {"foo":"bar"}` 的方式来进行返回,但是为了执行这类隐式调用,需要在响应流程中的某个位置花费大量的时间来确定您到底想要表达什么意思。 But, in order to do this implicit calling, somewhere in the chain needs to spend valuable time trying to determine what you meant. So, at the expense of this ease, Sanic has decided to require an explicit call.
### 运行(Running)
----:1
-
-让我们将上面写好的文件保存为 `server.py`, 然后运行它。
-
-:--:1
-
+---:1 Let's save the above file as `server.py`. And launch it. :--:1
```bash
sanic server.app
```
-
:---
-::: tip 小提示
-
-这是 **另一个** 重要的区别。其他框架带有一个内置的开发服务器,并明确表示它只用于开发。而 Sanic 的情况恰好相反。
+这是 **另一个** 重要的区别。 其他框架带有一个内置的开发服务器,并明确表示它只用于开发。 而 Sanic 的情况恰好相反。
-**可以用于生产环境的服务器已经准备就绪**
-
-:::
+让我们将上面写好的文件保存为 `server.py`, 然后运行它。
## Sanic 拓展(Sanic Extensions)
-Sanic 致力于构建一个简洁且没有任何偏见的特征表。该项目不想要求您以某种方式构建应用程序,并试图避免指定特定的开发模式。有许多由社区构建和维护的第三方插件,用于添加不符合核心库要求的附加功能。
+Sanic 致力于构建一个简洁且没有任何偏见的特征表。 该项目不想要求您以某种方式构建应用程序,并试图避免指定特定的开发模式。 有许多由社区构建和维护的第三方插件,用于添加不符合核心库要求的附加功能。
-但是,为了 **帮助 API 开发者** ,Sanic 组织维护了一个名为 [Sanic Extensions](../plugins/sanic-ext/getting-started.md) 的项目来提供各种易用的功能,包括:
+请查看 [插件文档](../plugins/sanic-ext/getting-started.md) 来了解如何使用拓展插件。
- **OpenAPI** 使用 Redoc 和/或 Swagger 的文档
- **CORS** 保护
@@ -78,25 +64,21 @@ Sanic 致力于构建一个简洁且没有任何偏见的特征表。该项目
- 自动创建 `HEAD`, `OPTIONS`, 和 `TRACE` 响应函数
- 响应序列化
-安装它的首选方法是与 Sanic 一起安装,当然您也可以单独安装。
+::: tip 小提示
---:1
-
```
$ pip install sanic[ext]
```
-
:--:1
-
```
$ pip install sanic sanic-ext
```
-
:---
-从 v21.12 开始,如果在相同的环境中,Sanic 将自动设置 Sanic 扩展。您可以通过以下的两种方式来进行访问拓展功能:
+从 v21.12 开始,如果在相同的环境中,Sanic 将自动设置 Sanic 扩展。 您可以通过以下的两种方式来进行访问拓展功能:
- `app.extend()` - 用于配置 Sanic 拓展
- `app.ext` - 注入到应用程序的扩展实例
-请查看 [插件文档](../plugins/sanic-ext/getting-started.md) 来了解如何使用拓展插件。
+但是,为了 **帮助 API 开发者** ,Sanic 组织维护了一个名为 [Sanic Extensions](../plugins/sanic-ext/getting-started.md) 的项目来提供各种易用的功能,包括:
From 3d9e17ca786243773b1c6809fa34cbc016f29139 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:24 +0300
Subject: [PATCH 177/776] New translations policies.md (Portuguese, Brazilian)
---
src/pt/org/policies.md | 62 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 src/pt/org/policies.md
diff --git a/src/pt/org/policies.md b/src/pt/org/policies.md
new file mode 100644
index 0000000000..cfac9b9a5b
--- /dev/null
+++ b/src/pt/org/policies.md
@@ -0,0 +1,62 @@
+# Policies
+
+## Versioning
+
+Sanic uses [calendar versioning](https://calver.org/), aka "calver". To be more specific, the pattern follows:
+
+```
+YY.MM.MICRO
+```
+
+Generally, versions are referred to in their `YY.MM` form. The `MICRO` number indicates an incremental patch version, starting at `0`.
+
+## Release Schedule
+
+There are four (4) scheduled releases per year: March, June, September, and December. Therefore, there are four (4) released versions per year: `YY.3`, `YY.6`, `YY.9`, and `YY.12`.
+
+This release schedule provides:
+
+- a predictable release cadence,
+- relatively short development windows allowing features to be regularly released,
+- controlled [deprecations](#deprecation), and
+- consistent stability with a yearly LTS.
+
+We also use the yearly release cycle in conjunction with our governance model, covered by the [S.C.O.P.E.](./scope.md)
+
+### Long term support v Interim releases
+
+Sanic releases a long term support release (aka "LTS") once a year in December. The LTS releases receive bug fixes and security updates for **24 months**. Interim releases throughout the year occur every three months, and are supported until the subsequent release.
+
+| Version | LTS | Supported |
+| ------- | ------------- | ------------------------- |
+| 22.6 | | :white_check_mark: |
+| 22.3 | | :x: |
+| 21.12 | until 2023-12 | :white_check_mark: |
+| 21.9 | | :x: |
+| 21.6 | | :x: |
+| 21.3 | | :x: |
+| 20.12 | until 2022-12 | :ballot_box_with_check: |
+| 20.9 | | :x: |
+| 20.6 | | :x: |
+| 20.3 | | :x: |
+| 19.12 | | :x: |
+| 19.9 | | :x: |
+| 19.6 | | :x: |
+| 19.3 | | :x: |
+| 18.12 | | :x: |
+| 0.8.3 | | :x: |
+| 0.7.0 | | :x: |
+| 0.6.0 | | :x: |
+| 0.5.4 | | :x: |
+| 0.4.1 | | :x: |
+| 0.3.1 | | :x: |
+| 0.2.0 | | :x: |
+| 0.1.9 | | :x: |
+
+:ballot_box_with_check: = security fixes :white_check_mark: = full support
+
+## Deprecation
+
+Before a feature is deprecated, or breaking changes are introduced into the API, it shall be publicized and shall appear with deprecation warnings through two release cycles. No deprecations shall be made in an LTS release.
+
+Breaking changes or feature removal may happen outside of these guidelines when absolutely warranted. These circumstances should be rare. For example, it might happen when no alternative is available to curtail a major security issue.
From 67098b5f7ece1089c3a921841773f74d402ae6fc Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:25 +0300
Subject: [PATCH 178/776] New translations scope.md (Japanese)
---
src/ja/org/scope.md | 174 ++++++++++++++++++++++----------------------
1 file changed, 87 insertions(+), 87 deletions(-)
diff --git a/src/ja/org/scope.md b/src/ja/org/scope.md
index 9d06af6490..71d2d8ce85 100644
--- a/src/ja/org/scope.md
+++ b/src/ja/org/scope.md
@@ -4,137 +4,137 @@ title: S.C.O.P.E
サニックコミュニティ組織ポリシーE-manual
-===================================
+============================================
2019年12月、バージョン1
目標
----
+-----
Sanicプロジェクトを中心に、持続可能なコミュニティ主導の組織を作り、それを推進すること: (1) 安定性と予測可能性、(2) 迅速な反復と強化サイクル、(3) 外部貢献者の関与、(4) 全体的に信頼できるソフトウェア、(5) コミュニティメンバーにとって安全でやりがいのある環境、などを推進するコミュニティ主導の組織を作る。
概要
----
+--------
-本ポリシーは、Sanic Community Organization(以下、「SCO」という)の経営モデルである。SCOは、実力主義、合意主義に基づくコミュニティ組織で、採択されたすべてのプロジェクトに責任を持ちます。いずれかのプロジェクトに興味を持つ人は誰でもコミュニティに参加し、コミュニティやプロジェクトに貢献し、意思決定プロセスに参加することができます。この文書では、その参加方法と、プロジェクト・コミュニティ内で功労を得るための方法について説明します。
+本ポリシーは、Sanic Community Organization(以下、「SCO」という)の経営モデルである。 SCOは、実力主義、合意主義に基づくコミュニティ組織で、採択されたすべてのプロジェクトに責任を持ちます。 いずれかのプロジェクトに興味を持つ人は誰でもコミュニティに参加し、コミュニティやプロジェクトに貢献し、意思決定プロセスに参加することができます。 この文書では、その参加方法と、プロジェクト・コミュニティ内で功労を得るための方法について説明します。
構造
----
+---------
-SCOには複数の**プロジェクト**があります。各プロジェクトは、Sanic コミュニティ傘下の単一の GitHub リポジトリによって表現されています。これらのプロジェクトは**ユーザ**によって使用され、**貢献者**によって開発され、**コア開発者**によって管理され、**リリースマネージャ**によってリリースされ、最終的に**運営評議会**によって監督される。もしこれがPythonプロジェクトやPEP 8016に似ていると思われるなら、それは意図的にそのように設計されているからです。
+SCOには複数の**プロジェクト**があります。 各プロジェクトは、Sanic コミュニティ傘下の単一の GitHub リポジトリによって表現されています。 これらのプロジェクトは**ユーザ**によって使用され、**貢献者**によって開発され、**コア開発者**によって管理され、**リリースマネージャ**によってリリースされ、最終的に**運営評議会**によって監督される。 もしこれがPythonプロジェクトやPEP 8016に似ていると思われるなら、それは意図的にそのように設計されているからです。
役割と責任
---------
+--------------------------
### ユーザー
-ユーザーは、プロジェクトに必要なコミュニティメンバーです。彼らは、開発者であり、パッケージをダウンロードしインストールする人員でもあります。ユーザーはコミュニティの **最も重要な** メンバーであり、彼らなしではプロジェクトは目的を持ちません。ユーザーは誰でもなることができ、プロジェクトが採用するライセンスは適切なオープンソースライセンスでなければならない。
+ユーザーは、プロジェクトに必要なコミュニティメンバーです。 彼らは、開発者であり、パッケージをダウンロードしインストールする人員でもあります。 ユーザーはコミュニティの **最も重要な** メンバーであり、彼らなしではプロジェクトは目的を持ちません。 ユーザーは誰でもなることができ、プロジェクトが採用するライセンスは適切なオープンソースライセンスでなければならない。
_SCOは、ユーザーにできるだけプロジェクトやコミュニティに参加するよう求めています。_
-ユーザーの貢献により、プロジェクトチームは、そのユーザーのニーズを確実に満たすことができるようになります。一般的なユーザー貢献には、以下のようなものがある(ただし、これらに限定されない)。
+ユーザーの貢献により、プロジェクトチームは、そのユーザーのニーズを確実に満たすことができるようになります。 一般的なユーザー貢献には、以下のようなものがある(ただし、これらに限定されない)。
-* プロジェクトについての伝道(例:ウェブサイト上のリンク、口コミによる認知度の向上)
-* 新しいユーザーの視点から、開発者に長所と短所を知らせる。
-* 精神的なサポート("ありがとう"の一言が大きな力になります)
-* 金銭的な支援(オープンソースのソフトウェアですが、開発者は食べていく必要があります。)
+* プロジェクトについての伝道(例:ウェブサイト上のリンク、口コミによる認知度の向上)
+* 新しいユーザーの視点から、開発者に長所と短所を知らせる。
+* 精神的なサポート("ありがとう"の一言が大きな力になります)
+* 金銭的な支援(オープンソースのソフトウェアですが、開発者は食べていく必要があります。 )
-SCO、そのプロジェクト、そのコミュニティに関わり続けるユーザーは、多くの場合、より深く関わるようになります。そのようなユーザは、次のセクションで説明するように、自分自身が貢献者になることに気づくかもしれません。
+SCO、そのプロジェクト、そのコミュニティに関わり続けるユーザーは、多くの場合、より深く関わるようになります。 そのようなユーザは、次のセクションで説明するように、自分自身が貢献者になることに気づくかもしれません。
### コントリビューター
-コントリビューターは、1つまたは複数のプロジェクトに具体的な方法で貢献するコミュニティのメンバーです。誰でもコントリビューターとなることができ、コントリビューターにはさまざまな形態があります。貢献と要件は、各プロジェクトが個別に定める貢献ポリシーによって管理されます。
+コントリビューターは、1つまたは複数のプロジェクトに具体的な方法で貢献するコミュニティのメンバーです。 誰でもコントリビューターとなることができ、コントリビューターにはさまざまな形態があります。 貢献と要件は、各プロジェクトが個別に定める貢献ポリシーによって管理されます。
プロジェクトに対するコミットメントを**期待せず**、特定のスキルを**要求せず**、選考過程も**行いません**。
また、ユーザーとしての活動だけでなく、以下のような活動も行っている場合があります。
-* 新規ユーザーのサポート(新規ユーザーをサポートするには、既存のユーザーが最適であることが多い)。
-* バグ報告
-* 要件定義
-* グラフィックやウェブデザインの提供
-* プログラミング
-* 使用例
-* プロジェクトのインフラを支援する
-* ドキュメント作成
-* バグ修正
-* 機能追加
-* 建設的な意見を提供し、コミュニティの議論に参加する
+* 新規ユーザーのサポート(新規ユーザーをサポートするには、既存のユーザーが最適であることが多い)。
+* バグ報告
+* 要件定義
+* グラフィックやウェブデザインの提供
+* プログラミング
+* 使用例
+* プロジェクトのインフラを支援する
+* ドキュメント作成
+* バグ修正
+* 機能追加
+* 建設的な意見を提供し、コミュニティの議論に参加する
-コントリビューターは、GitHubやコミュニティ・フォーラムを通じてプロジェクトに参加します。コントリビューターはプルリクエストを通じてプロジェクトに変更を加え、それをコミュニティ全体がプロジェクトに取り入れるかどうか検討します。コミュニティ・フォーラムは、最初のコントリビューションを行う際に助けを求めるのに最も適切な場所です。
+コントリビューターは、GitHubやコミュニティ・フォーラムを通じてプロジェクトに参加します。 コントリビューターはプルリクエストを通じてプロジェクトに変更を加え、それをコミュニティ全体がプロジェクトに取り入れるかどうか検討します。 コミュニティ・フォーラムは、最初のコントリビューションを行う際に助けを求めるのに最も適切な場所です。
-実際、コントリビューターの最も重要な役割の1つは、**単にコミュニティの会話に参加すること**かもしれません。プロジェクトの方向性に関するほとんどの決定は、コンセンサスによって行われます。これについては、以下で詳しく説明します。しかし、一般的には、貢献者が(行動規範の範囲内で)自由に発言し、**自分の意見や経験を述べる**ことは、プロジェクトの健全性と方向性のために役立ち、合意形成の推進を助けることになります。
+実際、コントリビューターの最も重要な役割の1つは、**単にコミュニティの会話に参加すること**かもしれません。 プロジェクトの方向性に関するほとんどの決定は、コンセンサスによって行われます。 これについては、以下で詳しく説明します。 しかし、一般的には、貢献者が(行動規範の範囲内で)自由に発言し、**自分の意見や経験を述べる**ことは、プロジェクトの健全性と方向性のために役立ち、合意形成の推進を助けることになります。
-コントリビューターがプロジェクトで経験を積み、親しみを持つようになると、コミュニティ内での知名度やコミュニティへの貢献度が高まります。ある段階では、コア開発者チームに推薦されるかもしれません。
+コントリビューターがプロジェクトで経験を積み、親しみを持つようになると、コミュニティ内での知名度やコミュニティへの貢献度が高まります。 ある段階では、コア開発者チームに推薦されるかもしれません。
### コア開発者
-SCO傘下の各プロジェクトは、それぞれコア開発者のチームを持っています。彼らはそのプロジェクトの責任者です。
+SCO傘下の各プロジェクトは、それぞれコア開発者のチームを持っています。 彼らはそのプロジェクトの責任者です。
_コア開発者とは?_
-コア開発者は、コミュニティとの継続的な関わりを通じて、プロジェクトの継続的な発展にコミットしていることを示したコミュニティのメンバーです。コア開発者になると、プロジェクトのリソースに直接アクセスできるようになるため、貢献者はより簡単にプロジェクトに関連した活動を行うことができるようになります。彼らは、フォークからのプルリクエストによって変更を提出することなく、プロジェクトのリポジトリに直接変更を加えることができます。
+コア開発者は、コミュニティとの継続的な関わりを通じて、プロジェクトの継続的な発展にコミットしていることを示したコミュニティのメンバーです。 コア開発者になると、プロジェクトのリソースに直接アクセスできるようになるため、貢献者はより簡単にプロジェクトに関連した活動を行うことができるようになります。 彼らは、フォークからのプルリクエストによって変更を提出することなく、プロジェクトのリポジトリに直接変更を加えることができます。
-これは、コア開発者が自由に好きなことをできるという意味ではありません。実際、コア開発者はコントリビューター以上にパッケージの最終的なリリースに対して直接的な権限を持っていません。この栄誉は、プロジェクトの目的と目標を健全に尊重しているコミュニティの大切なメンバーであることを示していますが、彼らの仕事は、公式リリースに採用される前に、コミュニティによってレビューされ続けています。
+これは、コア開発者が自由に好きなことをできるという意味ではありません。 実際、コア開発者はコントリビューター以上にパッケージの最終的なリリースに対して直接的な権限を持っていません。 この栄誉は、プロジェクトの目的と目標を健全に尊重しているコミュニティの大切なメンバーであることを示していますが、彼らの仕事は、公式リリースに採用される前に、コミュニティによってレビューされ続けています。
_コア開発者がプロジェクトでできることは?_
-プロジェクトによって、この役割の定義は若干異なるかもしれません。しかし、この呼称の一般的な使い方は、ある個人がコミュニティ内で信頼されるようになり、ある程度のコントロールを与えられるようになったというものです。これは、保護されていないブランチへのプッシュ権や、プルリクエストの承認に発言権を持つという形で実現されます。
+プロジェクトによって、この役割の定義は若干異なるかもしれません。 しかし、この呼称の一般的な使い方は、ある個人がコミュニティ内で信頼されるようになり、ある程度のコントロールを与えられるようになったというものです。 これは、保護されていないブランチへのプッシュ権や、プルリクエストの承認に発言権を持つという形で実現されます。
-プロジェクトでは、すべての貢献がコミュニティ全体によってレビューされることを保証するために、さまざまなコミュニケーションメカニズムを採用しています。これには、GitHubが提供するツールや、コミュニティフォーラムが含まれます。貢献者がコア開発者として招待されるまでに、ユーザーとして、そして貢献者として、さまざまなツールやワークフローに慣れておく必要があります。
+プロジェクトでは、すべての貢献がコミュニティ全体によってレビューされることを保証するために、さまざまなコミュニケーションメカニズムを採用しています。 これには、GitHubが提供するツールや、コミュニティフォーラムが含まれます。 貢献者がコア開発者として招待されるまでに、ユーザーとして、そして貢献者として、さまざまなツールやワークフローに慣れておく必要があります。
_コア開発者になるには?_
コア開発者になるには、チームプレーヤーとしてプロジェクトに積極的に参加する意欲と能力があればよく、特別な要件はありません。
-一般的に、コア開発者候補は、プロジェクトやその目的、戦略について理解していることを示す必要があります。また、一定期間にわたってプロジェクトに貴重な貢献をしてきたことも必要です。ただし、技術やその他のスキルの要件はありません。
+一般的に、コア開発者候補は、プロジェクトやその目的、戦略について理解していることを示す必要があります。 また、一定期間にわたってプロジェクトに貴重な貢献をしてきたことも必要です。 ただし、技術やその他のスキルの要件はありません。
-新しいコア開発者は、**既存のコア開発者によっていつでも推薦される**ことができます。少なくとも年に二回 (4月と10月)、運営評議会による投票が行われます。投票は秘密投票で行われるべきです。そのプロジェクトの既存の各コア開発者は、投票用紙に書かれた候補者の数に等しい数の票を受け取ります。例えば、候補者が四人いた場合、既存の各コア開発者は四票を持ちます。コア開発者はそれらの票を好きなように投じることができますが、 ひとつの候補者に複数回投票することはできません。候補者は、投票数 (投票資格のある人の数ではありません) の三分の二の承認を受けなければなりません。コア開発者が承認した後は、運営評議会がそのノミニーを承認し、最終決定する責任を負います。運営評議会は、ノミニーがコア開発者の称号を受けるに十分な功労があるかどうかを判断する権利を持ちません。しかし、コミュニティの健全性を保つために必要であれば、投票を無効とする権利を有します。
+新しいコア開発者は、**既存のコア開発者によっていつでも推薦される**ことができます。 少なくとも年に二回 (4月と10月)、運営評議会による投票が行われます。 投票は秘密投票で行われるべきです。 そのプロジェクトの既存の各コア開発者は、投票用紙に書かれた候補者の数に等しい数の票を受け取ります。 例えば、候補者が四人いた場合、既存の各コア開発者は四票を持ちます。 コア開発者はそれらの票を好きなように投じることができますが、 ひとつの候補者に複数回投票することはできません。 候補者は、投票数 (投票資格のある人の数ではありません) の三分の二の承認を受けなければなりません。 コア開発者が承認した後は、運営評議会がそのノミニーを承認し、最終決定する責任を負います。 運営評議会は、ノミニーがコア開発者の称号を受けるに十分な功労があるかどうかを判断する権利を持ちません。 しかし、コミュニティの健全性を保つために必要であれば、投票を無効とする権利を有します。
-投票が行われた後、集計された投票結果はコミュニティフォーラムで公開されます。ノミニーは、自分に対する無効の説明について要求する権利を有します。コア開発者として認められなかったノミニーは、 将来再びされることができます。
+投票が行われた後、集計された投票結果はコミュニティフォーラムで公開されます。 ノミニーは、自分に対する無効の説明について要求する権利を有します。 コア開発者として認められなかったノミニーは、 将来再びされることができます。
-コア開発者であることは、権利ではなく特権であることを認識することが重要です。その特権は獲得しなければならず、いったん獲得した特権は、極端な場合には運営評議会 (次のセクションを参照) によって削除されることがあります。しかし、通常の状況下では、コア開発者の肩書きは、その個人がプロジェクトやコミュニティとの関わりを続けたいと望む限り存在します。
+コア開発者であることは、権利ではなく特権であることを認識することが重要です。 その特権は獲得しなければならず、いったん獲得した特権は、極端な場合には運営評議会 (次のセクションを参照) によって削除されることがあります。 しかし、通常の状況下では、コア開発者の肩書きは、その個人がプロジェクトやコミュニティとの関わりを続けたいと望む限り存在します。
-特にプロジェクトの戦略的方向性や長期的健全性に関して平均以上の貢献度を示したコミッターは、運営評議会のメンバー、またはリリースマネージャに推薦されることがあります。この役割については後述します。
+特にプロジェクトの戦略的方向性や長期的健全性に関して平均以上の貢献度を示したコミッターは、運営評議会のメンバー、またはリリースマネージャに推薦されることがあります。 この役割については後述します。
_コア開発者の権利と責任は?_
-議論されているように、決定すべきことの大半は合意形成によるものです。ある問題がより論争的になった、または重大な決定を下す必要がある特定の状況では、リリースマネージャまたは運営評議会は、以下に詳しく説明するRFCプロセスの実施を決定する(または要求する)ことができます。
+議論されているように、決定すべきことの大半は合意形成によるものです。 ある問題がより論争的になった、または重大な決定を下す必要がある特定の状況では、リリースマネージャまたは運営評議会は、以下に詳しく説明するRFCプロセスの実施を決定する(または要求する)ことができます。
-また、コミュニティの運営に発言力を持つことは、コア開発者の責務です。すべてのプロジェクトのすべてのコア開発者は、運営評議会のメンバーに推薦され、その選挙で投票することができます。
+また、コミュニティの運営に発言力を持つことは、コア開発者の責務です。 すべてのプロジェクトのすべてのコア開発者は、運営評議会のメンバーに推薦され、その選挙で投票することができます。
-このポリシー (「SCOPE」) は、アクティブなコア開発者の3分の2の権限でのみ変更できます。ただし採択後6ヶ月間は、コア開発者はアクティブなコア開発者の単純多数の権限で変更する権利を留保します。
+このポリシー (「SCOPE」) は、アクティブなコア開発者の3分の2の権限でのみ変更できます。 ただし採択後6ヶ月間は、コア開発者はアクティブなコア開発者の単純多数の権限で変更する権利を留保します。
_コア開発者が活動停止になった場合は?_
-すべてのコア開発者がプロジェクトに参加し、定期的に活動し続けることが望まれます。しかし、そのような約束が現実的でない、あるいは不可能な場合があることも理解されています。
+すべてのコア開発者がプロジェクトに参加し、定期的に活動し続けることが望まれます。 しかし、そのような約束が現実的でない、あるいは不可能な場合があることも理解されています。
-したがって、運営評議会は参加を奨励する義務を負うとともに、参加する意思や能力がなくなったコア開発者を非活動状態にする責任を負います。この主な目的は、**その人の行動を罰すること**ではなく、アクティブであり続ける人のために開発プロセスを継続することを支援することです。
+したがって、運営評議会は参加を奨励する義務を負うとともに、参加する意思や能力がなくなったコア開発者を非活動状態にする責任を負います。 この主な目的は、**その人の行動を罰すること**ではなく、アクティブであり続ける人のために開発プロセスを継続することを支援することです。
-このため、「活動停止」したコア開発者はリポジトリへのコミット権を持たず、いかなる投票にも参加しないものとします。選挙の投票権を得るには、コア開発者は **前回予定されていたプロジェクトのリリースの時点で** アクティブである必要があります。
+このため、「活動停止」したコア開発者はリポジトリへのコミット権を持たず、いかなる投票にも参加しないものとします。 選挙の投票権を得るには、コア開発者は **前回予定されていたプロジェクトのリリースの時点で** アクティブである必要があります。
活動停止中のメンバーは、いつでもその地位を復活させるよう運営評議会に要求でき、 その要求があれば運営評議会はそのコア開発者を再び活動可能にするものとします。
アクティブな状態を一定期間維持できないことが分かっている個人は、運営評議会と連絡を取り合い、必要に応じて非アクティブを宣言することが求められます。
-「活動的な」コア開発者とは、過去六か月間に有意義な形で参加した人です。それ以上の定義は、運営評議会の裁量に委ねられます。
+「活動的な」コア開発者とは、過去六か月間に有意義な形で参加した人です。 それ以上の定義は、運営評議会の裁量に委ねられます。
### リリースマネージャー
-コア開発者は、非保護ブランチへのコミットおよびマージを行うためのアクセス権のみを有するものとします。masterブランチおよびその他の保護されたブランチは、そのプロジェクトのリリース管理チームによって管理されます。リリース管理者は、コア開発チームによってコア開発チームから選出され、全リリースサイクルの間、その役割を果たすものとします。
+コア開発者は、非保護ブランチへのコミットおよびマージを行うためのアクセス権のみを有するものとします。 masterブランチおよびその他の保護されたブランチは、そのプロジェクトのリリース管理チームによって管理されます。 リリース管理者は、コア開発チームによってコア開発チームから選出され、全リリースサイクルの間、その役割を果たすものとします。
-各コア開発チームは、各リリースサイクルに対して何人のリリースマネージャを置くかを決定することができます。責任を分担し、一人に過度の負担を強いないために、1つのリリースサイクルには少なくとも2人のリリースマネージャがいることが強く推奨されます。しかし、マネージャーの数が多すぎて、彼らの努力が妨げられるようなことがあってはなりません。
+各コア開発チームは、各リリースサイクルに対して何人のリリースマネージャを置くかを決定することができます。 責任を分担し、一人に過度の負担を強いないために、1つのリリースサイクルには少なくとも2人のリリースマネージャがいることが強く推奨されます。 しかし、マネージャーの数が多すぎて、彼らの努力が妨げられるようなことがあってはなりません。
リリース管理チームの主な職務は以下の通りです。
-* 技術的な議論を監視し、促進することによって、開発サイクルを前進させる。
-* リリースカレンダーを作成し、パッケージのリリースに必要なアクションを実行します。
-* masterブランチおよびその他の保護されたブランチへのプルリクエストの承認
-* masterブランチおよび他のprotectedブランチへのプルリクエストをマージします。
+* 技術的な議論を監視し、促進することによって、開発サイクルを前進させる。
+* リリースカレンダーを作成し、パッケージのリリースに必要なアクションを実行します。
+* masterブランチおよびその他の保護されたブランチへのプルリクエストの承認
+* masterブランチおよび他のprotectedブランチへのプルリクエストをマージします。
-リリースマネージャーは、貢献の基準を満たし、コミュニティによって受け入れられたプルリクエストに対して、**拒否権やマージを差し控える権限を持っていません**。何が開発されるべきかを決めるのは彼らの責任ではなく、コミュニティの決定が実行され、プロジェクトが前進していることを確認するためのものです。
+リリースマネージャーは、貢献の基準を満たし、コミュニティによって受け入れられたプルリクエストに対して、**拒否権やマージを差し控える権限を持っていません**。 何が開発されるべきかを決めるのは彼らの責任ではなく、コミュニティの決定が実行され、プロジェクトが前進していることを確認するためのものです。
-時には、コンセンサスで達成できない決定をする必要があるかもしれません。その場合、リリースマネージャーは、その決定をRFCプロセスに削除するよう求める権限を持っています。これは(後述するように必要な場合を除き)定期的に行われるべきではなく、より共同的な合意形成戦略を優先するため、この使用は控えるべきでしょう。
+時には、コンセンサスで達成できない決定をする必要があるかもしれません。 その場合、リリースマネージャーは、その決定をRFCプロセスに削除するよう求める権限を持っています。 これは(後述するように必要な場合を除き)定期的に行われるべきではなく、より共同的な合意形成戦略を優先するため、この使用は控えるべきでしょう。
すべてのプロジェクトに同じ要件があるわけではないので、プロジェクトにおけるリリースマネージャに関する詳細は、本ポリシーの付録、またはプロジェクトの貢献ガイドラインに記載されるものとします。
@@ -142,7 +142,7 @@ _コア開発者が活動停止になった場合は?_
### 運営協議会
-運営評議会は、「プロジェクトオーナー」として特定され、SCOの資源と資産を管理する個人で構成される運営組織です。彼らの最終的な目標は、障害物を取り除き、必要に応じてメンバーを支援することによって、プロジェクトの円滑な運営を確保することです。また、コミュニティーの中で定期的に発言することが期待されています。
+運営評議会は、「プロジェクトオーナー」として特定され、SCOの資源と資産を管理する個人で構成される運営組織です。 彼らの最終的な目標は、障害物を取り除き、必要に応じてメンバーを支援することによって、プロジェクトの円滑な運営を確保することです。 また、コミュニティーの中で定期的に発言することが期待されています。
_運営協議会は何ができる?_
@@ -150,11 +150,11 @@ _運営協議会は何ができる?_
ただし、運営協議会は組織として以下のような能力を有しています。
-* すべてのRFCの受理、差し戻し、および拒否
-* コミュニティ行動規範の実施
-* リポジトリ、サーバ、フォーラム、統合サービスなどのコミュニティ資産を管理する(または、そのような権限を他の誰かに委譲する)。
-* 極端な場合、コア開発者の解任を含め、本ポリシーで認められている他のあらゆる強制的な手段を取ることができます。
-* コミュニティ傘下のプロジェクトを採用または削除する
+* すべてのRFCの受理、差し戻し、および拒否
+* コミュニティ行動規範の実施
+* リポジトリ、サーバ、フォーラム、統合サービスなどのコミュニティ資産を管理する(または、そのような権限を他の誰かに委譲する)。
+* 極端な場合、コア開発者の解任を含め、本ポリシーで認められている他のあらゆる強制的な手段を取ることができます。
+* コミュニティ傘下のプロジェクトを採用または削除する
運営協議会は、可能な限りその権限を他の意欲的なコミュニティメンバーに委譲することが強く望まれます。
@@ -164,11 +164,11 @@ _運営協議会には何人いる?_
4人です。
-4票の委員会は、多数決を破る方法がなく、デッドロックに陥る可能性があるように思えますが、運営協議会はできるだけ投票をしないように推奨されています。その代わり、合意形成に努めるべきであり、議決が必要な場合は3名の同意票を必要とします。
+4票の委員会は、多数決を破る方法がなく、デッドロックに陥る可能性があるように思えますが、運営協議会はできるだけ投票をしないように推奨されています。 その代わり、合意形成に努めるべきであり、議決が必要な場合は3名の同意票を必要とします。
_運営協議会のメンバーは何年間在籍する?_
-1期は、1月から始まる暦年2年間とします。任期は、毎年、前年の審議会から継続する委員が2名となるようにずらされます。
+1期は、1月から始まる暦年2年間とします。 任期は、毎年、前年の審議会から継続する委員が2名となるようにずらされます。
従って、就任時の投票では、2年任期が2名、1年任期が2名の役職が用意されています。
@@ -176,17 +176,17 @@ _運営協議会のメンバーは何年間在籍する?_
_運営協議会は誰が運営しているのか?_
-運営協議会が選出された後、グループ全体で議長として活動する1名を決定するものとします。議長は、運営協議会の他のメンバーに対する追加的な権利や権限を有しません。
+運営協議会が選出された後、グループ全体で議長として活動する1名を決定するものとします。 議長は、運営協議会の他のメンバーに対する追加的な権利や権限を有しません。
-議長の役割は、単に調整役および進行役です。議長は、すべてのガバナンス・プロセスが順守されていることを確認することが期待されます。この役職はより管理的、事務的なものであり、議長が議題を設定し、グループの議論を調整することが期待されます。
+議長の役割は、単に調整役および進行役です。 議長は、すべてのガバナンス・プロセスが順守されていることを確認することが期待されます。 この役職はより管理的、事務的なものであり、議長が議題を設定し、グループの議論を調整することが期待されます。
_議員はどのように選出されるのですか?_
年に一度、各プロジェクトの **すべての適格なコア開発者** は、運営評議会のメンバーを選出する権利があります。
-指名は 9 月 1 日から始まり、9 月 30 日に締め切られます。その後、投票は 10 月 1 日から始まり 10 月 31 日に締め切られます。その年の Sanic フレームワークの 6 月のリリース日にアクティブなすべてのコア開発者は、運営評議会の空席につき 1 票を得る資格を得ます。明確にするために、投票資格を得るために、コア開発者は Sanic フレームワークのコア開発者である必要はなく、むしろその日にそれぞれのプロジェクトで活動している必要があります。
+指名は 9 月 1 日から始まり、9 月 30 日に締め切られます。 その後、投票は 10 月 1 日から始まり 10 月 31 日に締め切られます。 その年の Sanic フレームワークの 6 月のリリース日にアクティブなすべてのコア開発者は、運営評議会の空席につき 1 票を得る資格を得ます。 明確にするために、投票資格を得るために、コア開発者は Sanic フレームワークのコア開発者である必要はなく、むしろその日にそれぞれのプロジェクトで活動している必要があります。
-投票のトップ受信者は、勝者として宣言されるものとします。もし同点であれば、ランダムに決定される前に、同点の候補者自身が論争を解決することが強く推奨されます。
+投票のトップ受信者は、勝者として宣言されるものとします。 もし同点であれば、ランダムに決定される前に、同点の候補者自身が論争を解決することが強く推奨されます。
運営協議会の設立投票については、上位2名の得票者が2年間、次の2名の得票者が1年間の任期で就任するものとします。
@@ -194,7 +194,7 @@ _議員はどのように選出されるのですか?_
_欠員が出た場合は?_
-任期中に運営協議会に欠員が出た場合は、前回の選挙で次に得票数の多かった者が残りの任期を務めることを申し出るべきです。この方法で空席を埋めることができない場合、運営協議会はその空席を埋めるための最も適切な方法(任命、投票、その他の方法のいずれか)を決定することができます。
+任期中に運営協議会に欠員が出た場合は、前回の選挙で次に得票数の多かった者が残りの任期を務めることを申し出るべきです。 この方法で空席を埋めることができない場合、運営協議会はその空席を埋めるための最も適切な方法(任命、投票、その他の方法のいずれか)を決定することができます。
運営協議会のメンバーが活動しなくなった場合、その人物は直ちに運営協議会から外され、その席は空席となります。
@@ -202,31 +202,31 @@ _欠員が出た場合は?_
_運営協議会はどのように業務を遂行する?_
-運営協議会は、できる限りオープンに事業や議論を行います。コミュニティーのメンバーであれば、誰でもその会話に加わることができるようにします。しかし、時には非公開で議論を行うことが必要または適切である場合もあります。会話のための適切な場を選択することは、議長の管理業務の一部です。
+運営協議会は、できる限りオープンに事業や議論を行います。 コミュニティーのメンバーであれば、誰でもその会話に加わることができるようにします。 しかし、時には非公開で議論を行うことが必要または適切である場合もあります。 会話のための適切な場を選択することは、議長の管理業務の一部です。
-運営方法の詳細は本方針の範囲外ですが、運営審議会は、少なくとも四半期に一度、「リアルタイムの」話し合いの場を持つよう努めることが推奨されます。これは、ビデオ会議、ライブチャット、またはその他の適切な手段で実現できます。
+運営方法の詳細は本方針の範囲外ですが、運営審議会は、少なくとも四半期に一度、「リアルタイムの」話し合いの場を持つよう努めることが推奨されます。 これは、ビデオ会議、ライブチャット、またはその他の適切な手段で実現できます。
サポート
-------
+-------
-コミュニティの参加者は全員、プロジェクト管理インフラ内のユーザーをサポートすることが推奨されています。このサポートは、コミュニティを成長させる方法として提供されます。サポートを求める人は、プロジェクト内のすべてのサポート活動は自発的なものであり、したがって時間の許す限り提供されるものであることを認識する必要があります。保証された応答時間や結果を必要とするユーザは、コミュニティのメンバーからサポート契約を購入する必要があります。しかし、このプロジェクトに参加し、他のユーザーをサポートすることを望むユーザーにとっては、コミュニティのサポートチャネルは理想的です。
+コミュニティの参加者は全員、プロジェクト管理インフラ内のユーザーをサポートすることが推奨されています。 このサポートは、コミュニティを成長させる方法として提供されます。 サポートを求める人は、プロジェクト内のすべてのサポート活動は自発的なものであり、したがって時間の許す限り提供されるものであることを認識する必要があります。 保証された応答時間や結果を必要とするユーザは、コミュニティのメンバーからサポート契約を購入する必要があります。 しかし、このプロジェクトに参加し、他のユーザーをサポートすることを望むユーザーにとっては、コミュニティのサポートチャネルは理想的です。
意思決定プロセス
--------------
+-----------------------
-プロジェクトの将来についての決定は、最も新しいユーザーから最も経験豊かなメンバーまで、コミュニティのすべてのメンバーとの議論を通じて行われます。誰もが声を上げることができるのです。
+プロジェクトの将来についての決定は、最も新しいユーザーから最も経験豊かなメンバーまで、コミュニティのすべてのメンバーとの議論を通じて行われます。 誰もが声を上げることができるのです。
-プロジェクト管理に関する機密性のない議論は、すべてコミュニティフォーラムやその他の指定されたチャンネルで行われます。時折、機密性の高い議論が非公開で行われることもあります。
+プロジェクト管理に関する機密性のない議論は、すべてコミュニティフォーラムやその他の指定されたチャンネルで行われます。 時折、機密性の高い議論が非公開で行われることもあります。
-プロジェクトが終わりのない議論や継続的な投票によって停滞しないように、プロジェクトは**レイジーコンセンサス**というポリシーを運用しています。これにより、正式な投票に頼ることなく、大部分の決定を行うことができます。**重要な決定事項** (以下に定義) については、別途 Request for Comment (RFC) プロセスがあります。
+プロジェクトが終わりのない議論や継続的な投票によって停滞しないように、プロジェクトは**レイジーコンセンサス**というポリシーを運用しています。 これにより、正式な投票に頼ることなく、大部分の決定を行うことができます。 **重要な決定事項** (以下に定義) については、別途 Request for Comment (RFC) プロセスがあります。
### 技術的意思決定
プルリクエストと技術的な決定は、一般的に以下のカテゴリーに分類されるべきです。
-* **Routine**: ドキュメントの修正、クリーンアップや追加テストのためのコード変更。機能的な変更はありません。
-* **Minor**: コードベースへの変更は、バグを修正するか、または些細な機能を導入する。破壊的な変更はありません。
-* **Major**。既存のAPIを破壊または非推奨とする、自明ではない方法で操作を変更する、または重要な機能を追加するコードベースへの変更。
+* **Routine**: ドキュメントの修正、クリーンアップや追加テストのためのコード変更。 機能的な変更はありません。
+* **Minor**: コードベースへの変更は、バグを修正するか、または些細な機能を導入する。 破壊的な変更はありません。
+* **Major**。 既存のAPIを破壊または非推奨とする、自明ではない方法で操作を変更する、または重要な機能を追加するコードベースへの変更。
一般に、リポジトリへの変更がマージ前に適切な承認を受けるようにすることは、リリースマネージャの責任です。
@@ -241,24 +241,24 @@ _運営協議会はどのように業務を遂行する?_
* 投票(議論しても意見がまとまらない場合)
* 決定
-コミュニティメンバーは誰でも、コミュニティで検討するための提案を行うことができます。新しいアイデアについて議論を始めるには、コミュニティフォーラムの適切なチャンネルにメッセージを投稿するか、GitHub にそのアイデアを実装したプルリクエストを送信してください。これにより、そのアイデアのレビューが行われ、必要であれば議論が行われます。
+コミュニティメンバーは誰でも、コミュニティで検討するための提案を行うことができます。 新しいアイデアについて議論を始めるには、コミュニティフォーラムの適切なチャンネルにメッセージを投稿するか、GitHub にそのアイデアを実装したプルリクエストを送信してください。 これにより、そのアイデアのレビューが行われ、必要であれば議論が行われます。
-このレビューとディスカッションの目的は、コントリビューションに対する承認を得ることです。プロジェクトコミュニティのほとんどの人はビジョンを共有しているので、合意に達するための議論はほとんど必要ないことが多いです。
+このレビューとディスカッションの目的は、コントリビューションに対する承認を得ることです。 プロジェクトコミュニティのほとんどの人はビジョンを共有しているので、合意に達するための議論はほとんど必要ないことが多いです。
-一般に、誰も明確に反対しない限り、その提案やパッチはコミュニティの支持を得たものとして認識されます。これはレイジーコンセンサスと呼ばれるもので、つまり、明確に意見を述べなかった人は、暗黙のうちにその提案の実現に同意していることになるのです。
+一般に、誰も明確に反対しない限り、その提案やパッチはコミュニティの支持を得たものとして認識されます。 これはレイジーコンセンサスと呼ばれるもので、つまり、明確に意見を述べなかった人は、暗黙のうちにその提案の実現に同意していることになるのです。
-レイジーコンセンサスは、SCOの中で非常に重要な概念です。ある提案に異論がない人が自分の立場を表明するのに時間をかける必要がなく、他の人もそのようなメッセージを読むのに時間をかける必要がないため、このプロセスによって大勢の人が効率よく合意に達することができるのです。
+レイジーコンセンサスは、SCOの中で非常に重要な概念です。 ある提案に異論がない人が自分の立場を表明するのに時間をかける必要がなく、他の人もそのようなメッセージを読むのに時間をかける必要がないため、このプロセスによって大勢の人が効率よく合意に達することができるのです。
-ダラダラとした合意形成を効果的に行うためには、その提案に異論がないと判断するまでに適切な時間を置く必要があリマス。これは状況によって多少異なりますが、一般的には72時間が妥当であると考えられています。この要件により、誰もが提案を読み、咀嚼し、反応するための十分な時間が与えられます。この期間は、場所や時間の制約に関係なく、すべての参加者ができるだけ参加できるように選択されます。議論の進行役(議長であれ、リリースマネージャであれ、該当する場合)は、このような合意形成のための適切な時間の長さを決定する責任を負うものとします。
+ダラダラとした合意形成を効果的に行うためには、その提案に異論がないと判断するまでに適切な時間を置く必要があリマス。 これは状況によって多少異なりますが、一般的には72時間が妥当であると考えられています。 この要件により、誰もが提案を読み、咀嚼し、反応するための十分な時間が与えられます。 この期間は、場所や時間の制約に関係なく、すべての参加者ができるだけ参加できるように選択されます。 議論の進行役(議長であれ、リリースマネージャであれ、該当する場合)は、このような合意形成のための適切な時間の長さを決定する責任を負うものとします。
-いわゆる定型的な決定に関して前に書いたように、リリースマネージャはより短い時間内に決定を下す権利を持ちます。このような場合、怠惰な合意は黙示されるものとします。
+いわゆる定型的な決定に関して前に書いたように、リリースマネージャはより短い時間内に決定を下す権利を持ちます。 このような場合、怠惰な合意は黙示されるものとします。
### コメント要求(RFC)
-運営協議会は、RFCのプロセスを監督する責任を負います。このプロセスは、コミュニティの全メンバーに対して開かれた議論を維持し、提案を検討する十分な時間、メンバーが返答し、有意義な議論を行うための時間を確保します。
+運営協議会は、RFCのプロセスを監督する責任を負います。 このプロセスは、コミュニティの全メンバーに対して開かれた議論を維持し、提案を検討する十分な時間、メンバーが返答し、有意義な議論を行うための時間を確保します。
-最終的な決定は運営協議会に委ねられます。しかし、コミュニティ内に存在するコンセンサスに反する決定を運営協議会が採択することは、強く推奨されません。コンセンサスとプロジェクト全体およびコミュニティの目標との間に矛盾がある場合、時折このようなことが起こるかもしれません。
+最終的な決定は運営協議会に委ねられます。 しかし、コミュニティ内に存在するコンセンサスに反する決定を運営協議会が採択することは、強く推奨されません。 コンセンサスとプロジェクト全体およびコミュニティの目標との間に矛盾がある場合、時折このようなことが起こるかもしれません。
-RFCは、運営評議会が定める公開の方法で運営評議会に提出することにより開始されます。議論は、一般的には運営協議会、特に議長によって継続され、促進されます。
+RFCは、運営評議会が定める公開の方法で運営評議会に提出することにより開始されます。 議論は、一般的には運営協議会、特に議長によって継続され、促進されます。
運営協議会が適切と考える状況においては、RFCのプロセスを放棄し、怠惰な合意を優先させることができます。
From 169f542db3446a46b564c283ed78342ad2071d2e Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:26 +0300
Subject: [PATCH 179/776] New translations scope.md (Korean)
---
src/ko/org/scope.md | 264 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 264 insertions(+)
create mode 100644 src/ko/org/scope.md
diff --git a/src/ko/org/scope.md b/src/ko/org/scope.md
new file mode 100644
index 0000000000..1af529361a
--- /dev/null
+++ b/src/ko/org/scope.md
@@ -0,0 +1,264 @@
+---
+title: S.C.O.P.E
+---
+
+
+Sanic Community Organization Policy E-manual
+============================================
+
+December 2019, version 1
+
+Goals
+-----
+
+To create a sustainable, community-driven organization around the Sanic projects that promote: (1) stability and predictability, (2) quick iteration and enhancement cycles, (3) engagement from outside contributors, (4) overall reliable software, and (5) a safe, rewarding environment for the community members.
+
+Overview
+--------
+
+This Policy is the governance model for the Sanic Community Organization (“SCO”). The SCO is a meritocratic, consensus-based community organization responsible for all projects adopted by it. Anyone with an interest in one of the projects can join the community, contribute to the community or projects, and participate in the decision making process. This document describes how that participation takes place and how to set about earning merit within the project community.
+
+Structure
+---------
+
+The SCO has multiple **projects**. Each project is represented by a single GitHub repository under the Sanic community umbrella. These projects are used by **users**, developed by **contributors**, governed by **core developers**, released by **release managers**, and ultimately overseen by a **steering council**. If this sounds similar to the Python project and PEP 8016 that is because it is intentionally designed that way.
+
+Roles and responsibilities
+--------------------------
+
+### Users
+
+Users are community members who have a need for the projects. They are the developers and personnel that download and install the packages. Users are the **most important** members of the community and without them the projects would have no purpose. Anyone can be a user and the licenses adopted by the projects shall be appropriate open source licenses.
+
+_The SCO asks its users to participate in the project and community as much as possible._
+
+User contributions enable the project team to ensure that they are satisfying the needs of those users. Common user contributions include (but are not limited to):
+
+* evangelizing about the project (e.g. a link on a website and word-of-mouth awareness raising)
+* informing developers of strengths and weaknesses from a new user perspective
+* providing moral support (a ‘thank you’ goes a long way)
+* providing financial support (the software is open source, but its developers need to eat)
+
+Users who continue to engage with the SCO, its projects, and its community will often become more and more involved. Such users may find themselves becoming contributors, as described in the next section.
+
+### Contributors
+
+Contributors are community members who contribute in concrete ways to one or more of the projects. Anyone can become a contributor and contributions can take many forms. Contributions and requirements are governed by each project separately by a contribution policy.
+
+There is **no expectation** of commitment to the project, **no specific skill requirements** and **no selection process**.
+
+In addition to their actions as users, contributors may also find themselves doing one or more of the following:
+
+* supporting new users (existing users are often the best people to support new users)
+* reporting bugs
+* identifying requirements
+* providing graphics and web design
+* Programming
+* example use cases
+* assisting with project infrastructure
+* writing documentation
+* fixing bugs
+* adding features
+* providing constructive opinions and engaging in community discourse
+
+Contributors engage with the projects through GitHub and the Community Forums. They submit changes to the projects itself via pull requests, which will be considered for inclusion in the project by the community at large. The Community Forums are the most appropriate place to ask for help when making that first contribution.
+
+Indeed one of the most important roles of a contributor may be to **simply engage in the community conversation**. Most decisions about the direction of a project are made by consensus. This is discussed in more detail below. In general, however, it is helpful for the health and direction of the projects for the contributors to **speak freely** (within the confines of the code of conduct) and **express their opinions and experiences** to help drive the consensus building.
+
+As contributors gain experience and familiarity with a project, their profile within, and commitment to, the community will increase. At some stage, they may find themselves being nominated for a core developer team.
+
+### Core Developer
+
+Each project under the SCO umbrella has its own team of core developers. They are the people in charge of that project.
+
+_What is a core developer?_
+
+Core developers are community members who have shown that they are committed to the continued development of the project through ongoing engagement with the community. Being a core developer allows contributors to more easily carry on with their project related activities by giving them direct access to the project’s resources. They can make changes directly to the project repository without having to submit changes via pull requests from a fork.
+
+This does not mean that a core developer is free to do what they want. In fact, core developers have no more direct authority over the final release of a package than do contributors. While this honor does indicate a valued member of the community who has demonstrated a healthy respect for the project’s aims and objectives, their work continues to be reviewed by the community before acceptance in an official release.
+
+_What can a core developer do on a project?_
+
+Each project might define this role slightly differently. However, the general usage of this designation is that an individual has risen to a level of trust within the community such that they now are given some control. This comes in the form of push rights to non-protected branches, and the ability to have a voice in the approval of pull requests.
+
+The projects employ various communication mechanisms to ensure that all contributions are reviewed by the community as a whole. This includes tools provided by GitHub, as well as the Community Forums. By the time a contributor is invited to become a core developer, they should be familiar with the various tools and workflows as a user and then as a contributor.
+
+_How to become a core developer?_
+
+Anyone can become a core developer; there are no special requirements, other than to have shown a willingness and ability to positively participate in the project as a team player.
+
+Typically, a potential core developer will need to show that they have an understanding of the project, its objectives and its strategy. They will also have provided valuable contributions to the project over a period of time. However, there is **no technical or other skill** requirement for eligibility.
+
+New core developers can be **nominated by any existing core developer** at any time. At least twice a year (April and October) there will be a ballot process run by the Steering Council. Voting should be done by secret ballot. Each existing core developer for that project receives a number of votes equivalent to the number of nominees on the ballot. For example, if there are four nominees, then each existing core developer has four votes. The core developer may cast those votes however they choose, but may not vote for a single nominee more than once. A nominee must receive two-thirds approval from the number of cast ballots (not the number of eligible ballots). Once accepted by the core developers, it is the responsibility of the Steering Council to approve and finalize the nomination. The Steering Council does not have the right to determine whether a nominee is meritorious enough to receive the core developer title. However, they do retain the right to override a vote in cases where the health of the community would so require.
+
+Once the vote has been held, the aggregated voting results are published on the Community Forums. The nominee is entitled to request an explanation of any override against them. A nominee that fails to be admitted as a core developer may be nominated again in the future.
+
+It is important to recognize that being a core developer is a privilege, not a right. That privilege must be earned and once earned it can be removed by the Steering Council (see next section) in extreme circumstances. However, under normal circumstances the core developer title exists for as long as the individual wishes to continue engaging with the project and community.
+
+A committer who shows an above-average level of contribution to the project, particularly with respect to its strategic direction and long-term health, may be nominated to become a member of the Steering Council, or a Release Manager. This role is described below.
+
+_What are the rights and responsibilities of core developers?_
+
+As discussed, the majority of decisions to be made are by consensus building. In certain circumstances where an issue has become more contentious, or a major decision needs to be made, the Release Manager or Steering Council may decide (or be required) to implement the RFC process, which is outlined in more detail below.
+
+It is also incumbent upon core developers to have a voice in the governance of the community. All core developers for all of the projects have the ability to be nominated to be on the Steering Council and vote in their elections.
+
+This Policy (the “SCOPE”) may only be changed under the authority of two-thirds of active core developers, except that in the first six (6) months after adoption, the core developers reserve the right to make changes under the authority of a simple majority of active core developers.
+
+_What if a core developer becomes inactive?_
+
+It is hoped that all core developers participate and remain active on a regular basis in their projects. However, it is also understood that such commitments may not be realistic or possible from time to time.
+
+Therefore, the Steering Council has the duty to encourage participation and the responsibility to place core developers into an inactive status if they are no longer willing or capable to participate. The main purpose of this is **not to punish** a person for behavior, but to help the development process to continue for those that do remain active.
+
+To this end, a core developer that becomes “inactive” shall not have commit rights to a repository, and shall not participate in any votes. To be eligible to vote in an election, a core developer **must have been active** at the time of the previous scheduled project release.
+
+Inactive members may ask the Steering Council to reinstate their status at any time, and upon such request the Steering Council shall make the core developer active again.
+
+Individuals that know they will be unable to maintain their active status for a period are asked to be in communication with the Steering Council and declare themselves inactive if necessary.
+
+An “active” core developer is an individual that has participated in a meaningful way during the previous six months. Any further definition is within the discretion of the Steering Council.
+
+### Release Manager
+
+Core developers shall have access only to make commits and merges on non-protected branches. The “master” branch and other protected branches are controlled by the release management team for that project. Release managers shall be elected from the core development team by the core development team, and shall serve for a full release cycle.
+
+Each core developer team may decide how many release managers to have for each release cycle. It is highly encouraged that there be at least two release managers for a release cycle to help divide the responsibilities and not force too much effort upon a single person. However, there also should not be so many managers that their efforts are impeded.
+
+The main responsibilities of the release management team include:
+
+* push the development cycle forward by monitoring and facilitating technical discussions
+* establish a release calendar and perform actions required to release packages
+* approve pull requests to the master branch and other protected branches
+* merge pull requests to the master branch and other protected branches
+
+The release managers **do not have the authority to veto or withhold a merge** of a pull request that otherwise meets contribution criteria and has been accepted by the community. It is not their responsibility to decide what should be developed, but rather that the decisions of the community are carried out and that the project is being moved forward.
+
+From time to time, a decision may need to be made that cannot be achieved through consensus. In that case, the release managers have the authority to call upon the removal of the decision to the RFC process. This should not occur regularly (unless required as discussed below), and its use should be discouraged in favor of the more communal consensus building strategy.
+
+Since not all projects have the same requirements, the specifics governing release managers on a project shall be set forth in an Appendix to this Policy, or in the project’s contribution guidelines.
+
+If necessary, the Steering Council has the right to remove a release manager that is derelict in their duties, or for other good cause.
+
+### Steering Council
+
+The Steering Council is the governing body consisting of those individuals identified as the “project owner” and having control of the resources and assets of the SCO. Their ultimate goal is to ensure the smooth operation of the projects by removing impediments, and assisting the members as needed. It is expected that they will be regular voices in the community.
+
+_What can the Steering Council do?_
+
+The members of the Steering Council **do not individually have any more authority than any other core developer**, and shall not have any additional rights to make decisions, commits, merges, or the like on a project.
+
+However, as a body, the Steering Council has the following capacity:
+
+* accept, remand, and reject all RFCs
+* enforce the community code of conduct
+* administer community assets such as repositories, servers, forums, integration services, and the like (or, to delegate such authority to someone else)
+* place core developers into inactive status where appropriate take any other enforcement measures afforded to it in this Policy, including, in extreme cases, removing core developers
+* adopt or remove projects from the community umbrella
+
+It is highly encouraged that the Steering Council delegate its authority as much as possible, and where appropriate, to other willing community members.
+
+The Steering Council **does not have the authority** to change this Policy.
+
+_How many members are on the Steering Council?_
+
+Four.
+
+While it seems like a committee with four votes may potentially end in a deadlock with no way to break a majority vote, the Steering Council is discouraged from voting as much as possible. Instead, it should try to work by consensus, and requires three consenting votes when it is necessary to vote on a matter.
+
+_How long do members serve on the Steering Council?_
+
+A single term shall be for two calendar years starting in January. Terms shall be staggered so that each year there are two members continuing from the previous year’s council.
+
+Therefore, the inaugural vote shall have two positions available for a two year term, and two positions available for a one year term.
+
+There are no limits to the number of terms that can be served, and it is possible for an individual to serve consecutive terms.
+
+_Who runs the Steering Council?_
+
+After the Steering Council is elected, the group shall collectively decide upon one person to act as the Chair. The Chair does not have any additional rights or authority over any other member of the Steering Council.
+
+The role of the Chair is merely as a coordinator and facilitator. The Chair is expected to ensure that all governance processes are adhered to. The position is more administrative and clerical, and is expected that the Chair sets agendas and coordinates discussion of the group.
+
+_How are council members elected?_
+
+Once a year, **all eligible core developers** for each of the projects shall have the right to elect members to the Steering Council.
+
+Nominations shall be open from September 1 and shall close on September 30. After that, voting shall begin on October 1 and shall close on October 31. Every core developer active on the date of the June release of the Sanic Framework for that year shall be eligible to receive one vote per vacant seat on the Steering Council. For the sake of clarity, to be eligible to vote, a core developer **does not** need to be a core developer on Sanic Framework, but rather just have been active within their respective project on that date.
+
+The top recipients of votes shall be declared the winners. If there is any tie, it is highly encouraged that the tied nominees themselves resolve the dispute before a decision is made at random.
+
+In regards to the inaugural vote of the Steering Council, the top two vote-recipients shall serve for two years, and the next two vote-recipients shall assume the one-year seats.
+
+To be an eligible candidate for the Steering Council, the individual must have been a core developer in active status on at least one project for the previous twelve months.
+
+_What if there is a vacancy?_
+
+If a vacancy on the Steering Council exists during a term, then the next highest vote-recipient in the previous election shall be offered to complete the remainder of the term. If one cannot be found this way, the Steering Council may decide the most appropriate course of action to fill the seat (whether by appointment, vote, or other means).
+
+If a member of the Steering Council becomes inactive, then that individual shall be removed from the Steering Council immediately and the seat shall become vacant.
+
+In extreme cases, the body of all core developers has the right to bring a vote to remove a member of the Steering Council for cause by a two-thirds majority of all eligible voting core developers.
+
+_How shall the Steering Council conduct its business?_
+
+As much as possible, the Steering Council shall conduct its business and discussions in the open. Any member of the community should be allowed to enter the conversation with them. However, at times it may be necessary or appropriate for discussions to be held privately. Selecting the proper venue for conversations is part of the administrative duties of the Chair.
+
+While the specifics of how to operate are beyond the scope of the Policy, it is encouraged that the Steering Council attempt to meet at least one time per quarter in a “real-time” discussion. This could be achieved via video conferencing, live chatting, or other appropriate means.
+
+Support
+-------
+
+All participants in the community are encouraged to provide support for users within the project management infrastructure. This support is provided as a way of growing the community. Those seeking support should recognize that all support activity within the project is voluntary and is therefore provided as and when time allows. A user requiring guaranteed response times or results should therefore seek to purchase a support contract from a community member. However, for those willing to engage with the project on its own terms, and willing to help support other users, the community support channels are ideal.
+
+Decision making process
+-----------------------
+
+Decisions about the future of the projects are made through discussion with all members of the community, from the newest user to the most experienced member. Everyone has a voice.
+
+All non-sensitive project management discussion takes place on the community forums, or other designated channels. Occasionally, sensitive discussions may occur in private.
+
+In order to ensure that the project is not bogged down by endless discussion and continual voting, the project operates a policy of **lazy consensus**. This allows the majority of decisions to be made without resorting to a formal vote. For any **major decision** (as defined below), there is a separate Request for Comment (RFC) process.
+
+### Technical decisions
+
+Pull requests and technical decisions should generally fall into the following categories.
+
+* **Routine**: Documentation fixes, code changes that are for cleanup or additional testing. No functionality changes.
+* **Minor**: Changes to the code base that either fix a bug, or introduce a trivial feature. No breaking changes.
+* **Major**: Any change to the code base that breaks or deprecates existing API, alters operation in a non-trivial manner, or adds a significant feature.
+
+It is generally the responsibility of the release managers to make sure that changes to the repositories receive the proper authorization before merge.
+
+The release managers retain the authority to individually review and accept routine decisions that meet standards for code quality without additional input.
+
+### Lazy consensus
+
+Decision making (whether by the community or Steering Council) typically involves the following steps:
+
+* proposal
+* discussion
+* vote (if consensus is not reached through discussion)
+* decision
+
+Any community member can make a proposal for consideration by the community. In order to initiate a discussion about a new idea, they should post a message on the appropriate channel on the Community forums, or submit a pull request implementing the idea on GitHub. This will prompt a review and, if necessary, a discussion of the idea.
+
+The goal of this review and discussion is to gain approval for the contribution. Since most people in the project community have a shared vision, there is often little need for discussion in order to reach consensus.
+
+In general, as long as nobody explicitly opposes a proposal or patch, it is recognized as having the support of the community. This is called lazy consensus; that is, those who have not stated their opinion explicitly have implicitly agreed to the implementation of the proposal.
+
+Lazy consensus is a very important concept within the SCO. It is this process that allows a large group of people to efficiently reach consensus, as someone with no objections to a proposal need not spend time stating their position, and others need not spend time reading such messages.
+
+For lazy consensus to be effective, it is necessary to allow an appropriate amount of time before assuming that there are no objections to the proposal. This is somewhat dependent upon the circumstances, but it is generally assumed that 72 hours is reasonable. This requirement ensures that everyone is given enough time to read, digest and respond to the proposal. This time period is chosen so as to be as inclusive as possible of all participants, regardless of their location and time commitments. The facilitators of discussion (whether it be the Chair or the Release Managers, where applicable) shall be charged with determining the proper length of time for such consensus to be reached.
+
+As discussed above regarding so-called routine decisions, the release managers have the right to make decisions within a shorter period of time. In such cases, lazy consensus shall be implied.
+
+### Request for Comment (RFC)
+
+The Steering Council shall be in charge of overseeing the RFC process. It shall be a process that remains open to debate to all members of the community, and shall allow for ample time to consider a proposal and for members to respond and engage in meaningful discussion.
+
+The final decision is vested with the Steering Council. However, it is strongly discouraged that the Steering Council adopt a decision that is contrary to any consensus that may exist in the community. From time to time this may happen if there is a conflict between consensus and the overall project and community goals.
+
+An RFC shall be initiated by submission to the Steering Council in the public manner as set forth by the Steering Council. Debate shall continue and be facilitated by the Steering Council in general, and the Chair specifically.
+
+In circumstances that the Steering Council feels it is appropriate, the RFC process may be waived in favor of lazy consensus.
From 8a854603f103fcb90a73995d8e02f140bb5c823f Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:27 +0300
Subject: [PATCH 180/776] New translations scope.md (Chinese Simplified)
---
src/zh/org/scope.md | 247 ++++++++++++++++++++++----------------------
1 file changed, 122 insertions(+), 125 deletions(-)
diff --git a/src/zh/org/scope.md b/src/zh/org/scope.md
index 0037284116..41580570f1 100644
--- a/src/zh/org/scope.md
+++ b/src/zh/org/scope.md
@@ -2,162 +2,159 @@
title: S.C.O.P.E
---
-# Sanic 社区公约白皮书
+
+Sanic 社区公约白皮书
+============================================
2019 年 12 月 第一版
-## 目标(Goals)
+目标(Goals)
+-----
围绕 Sanic 项目创建一个可持续的、社区驱动的组织,以促进:
-(1)增强 Sanic 的稳定性和可预测性。
-
-(2)对 Sanic 进行快速迭代并增强周期支持。
-
-(3)外部贡献者参与其中。
-
-(4)创造一个整体可靠的软件。
-
-(5)为社区成员提供一个安全有益的环境。
-
-## 概览(Overview)
+概览(Overview)
+--------
-本公约是 Sanic 社区组织(Sanic Community Organization 简称 SCO)的管理概述。SCO 是一个精英主义、以共识为基础的社区组织。负责其下所有的项目。任何对组织下任一项目感兴趣的人都可以加入社区。为社区或项目做贡献,并参与决策过程。本公约用于描述如何参与其中以及如何从中获益。
+本公约是 Sanic 社区组织(Sanic Community Organization 简称 SCO)的管理概述。 SCO 是一个精英主义、以共识为基础的社区组织。 负责其下所有的项目。 任何对组织下任一项目感兴趣的人都可以加入社区。 为社区或项目做贡献,并参与决策过程。 This document describes how that participation takes place and how to set about earning merit within the project community.
-## 架构(Structure)
+架构(Structure)
+---------
-SCO 有多个 **项目**。每一个项目都由单独的 Github 仓库进行存储。这些项目由 **用户** 使用,由 **贡献者** 开发, **核心开发者** 管理, **发布经理** 发布 最终由 **指导委员会** 监督。这看起来与 Python 项目和 PEP8016 类似, 因为那是有意设计的。
+SCO 有多个 **项目**。 每一个项目都由单独的 Github 仓库进行存储。 这些项目由 **用户** 使用,由 **贡献者** 开发, **核心开发者** 管理, **发布经理** 发布 最终由 **指导委员会** 监督。 这看起来与 Python 项目和 PEP8016 类似, 因为那是有意设计的。
-## 角色与责任(Roles and responsibilities)
+角色与责任(Roles and responsibilities)
+--------------------------
### 用户(Users)
-用户是对项目有需求的社区成员。他们是下载和安装软件包的开发者和使用者。他们是社区中 **最重要** 的成员,没有他们,项目就没有意义。任何人都可以是用户,项目采用的许可证应该是适当的开源许可证。
+用户是对项目有需求的社区成员。 他们是下载和安装软件包的开发者和使用者。 他们是社区中 **最重要** 的成员,没有他们,项目就没有意义。 任何人都可以是用户,项目采用的许可证应该是适当的开源许可证。
-SCO 认为 _用户应该尽可能多的_ 参与项目与社区活动
+_长期参与 SCO 的项目和社区的用户,随着时间的推移,他们可能会发现自己成为贡献者,就如下一章节所述。_
-用户贡献使项目团队能够确保他们满足这些用户的需求。常见的用户贡献包括(但不限于):
+用户贡献使项目团队能够确保他们满足这些用户的需求。 常见的用户贡献包括(但不限于):
-* 宣传项目(例如:网站链接或进行宣传)。
-* 从新用户的角度告知开发者优势与劣势。
-* 提供精神支持(您的一句谢谢会让您受益匪浅)。
-* 提供资金支持(该软件开源,但是开发者也需要糊口)。
+* 宣传项目(例如:网站链接或进行宣传)。
+* 从新用户的角度告知开发者优势与劣势。
+* 提供精神支持(您的一句谢谢会让您受益匪浅)。
+* 提供资金支持(该软件开源,但是开发者也需要糊口)。
-长期参与 SCO 的项目和社区的用户,随着时间的推移,他们可能会发现自己成为贡献者,就如下一章节所述。
+Users who continue to engage with the SCO, its projects, and its community will often become more and more involved. Such users may find themselves becoming contributors, as described in the next section.
### 贡献者(Contributors)
-贡献者是以具体的方式为一个或多个项目做出贡献的社区成员。
-任何人都可以成为贡献者,贡献者可以有很多种形式。捐款和需求由每个项目通过捐献政策分别管理。
+贡献者是以具体的方式为一个或多个项目做出贡献的社区成员。 任何人都可以成为贡献者,贡献者可以有很多种形式。 捐款和需求由每个项目通过捐献政策分别管理。
在贡献过程中,**不需要对项目进行负责**,也 **没有具体技能要求**,同样 **不需要对人员进行选拔**。
-除了作为用户的行为之外,贡献者可能还会发现自己在做以下一项或多项事情:
+SCO 认为 _用户应该尽可能多的_ 参与项目与社区活动
-* 为新用户提供技术支持(现有用户通常是为新用户提供技术支持的最佳人选)
-* 报告错误
-* 提交需求
-* 提供图像设计或网站设计
-* 编程
-* 提供使用示例
-* 协助项目进行改进
-* 编写文档
-* 修复 BUG
-* 添加功能
-* 提供建设性意见和参与社区讨论
+* 为新用户提供技术支持(现有用户通常是为新用户提供技术支持的最佳人选)
+* 报告错误
+* 提交需求
+* 提供图像设计或网站设计
+* 编程
+* 提供使用示例
+* 协助项目进行改进
+* 编写文档
+* 修复 BUG
+* 添加功能
+* 提供建设性意见和参与社区讨论
-贡献者通过 GitHub 和社区论坛参与项目。他们通过提交请求的方式向项目提交变更,这将被整个社区考虑纳入项目中。当做出第一次贡献时,社区论坛是寻求帮助最合适的地方。
+贡献者通过 GitHub 和社区论坛参与项目。 他们通过提交请求的方式向项目提交变更,这将被整个社区考虑纳入项目中。 当做出第一次贡献时,社区论坛是寻求帮助最合适的地方。
-事实上, 贡献者承担最多的任务可能是 **参与社区对话**。因为大多数关于项目方向的决定都是通过协商做出的。这将在下面详细讨论。但是,一般来说,有助于项目发展的事情,贡献者都可以 **畅所欲言** (在行为准则的范围内)并 **表达他们的意见和经验** 以帮助达大家成共识。
+事实上, 贡献者承担最多的任务可能是 **参与社区对话**。 因为大多数关于项目方向的决定都是通过协商做出的。 这将在下面详细讨论。 但是,一般来说,有助于项目发展的事情,贡献者都可以 **畅所欲言** (在行为准则的范围内)并 **表达他们的意见和经验** 以帮助达大家成共识。
-随着贡献者获得开发经验和对项目的熟悉度逐渐提升,他们在社区中的形象和在社区中承担的责任会也会逐步提升。直到某个阶段,他们可能会发现自己已经成为了核心开发者。
+随着贡献者获得开发经验和对项目的熟悉度逐渐提升,他们在社区中的形象和在社区中承担的责任会也会逐步提升。 直到某个阶段,他们可能会发现自己已经成为了核心开发者。
### 核心开发者(Core Developer)
-SCO 下的每一个项目都有自己的核心开发团队。他们是项目的负责人。
+SCO 下的每一个项目都有自己的核心开发团队。 他们是项目的负责人。
_什么是核心开发者?_
-核心开发者是社区成员,他们通过长期参与社区活动,表明他们致力于项目的持续发展。作为一名核心开发人员,通过让贡献者直接访问项目资源,使得他们可以更好的完成项目相关的内容。他们可以直接对项目库进行更改,不必通过 frok 项目的方式。
+核心开发者是社区成员,他们通过长期参与社区活动,表明他们致力于项目的持续发展。 作为一名核心开发人员,通过让贡献者直接访问项目资源,使得他们可以更好的完成项目相关的内容。 他们可以直接对项目库进行更改,不必通过 frok 项目的方式。
-这并不意味着核心开发者可以自由地做他们想做的事情。核心开发者并不比普通贡献者拥有更大的权力。他们并不能直接控制项目的最终发布。虽然这一荣誉确实表明他们作为社区中的重要成员对项目做出了具有积极意义的贡献,但他们的工作在正式发布前仍会受到社区的审查。
+这并不意味着核心开发者可以自由地做他们想做的事情。 In fact, core developers have no more direct authority over the final release of a package than do contributors. 虽然这一荣誉确实表明他们作为社区中的重要成员对项目做出了具有积极意义的贡献,但他们的工作在正式发布前仍会受到社区的审查。
_核心开发者能够在项目中做什么?_
-每个项目对核心开发者的定义可能略有不同。当然,通常来说,拥有这种称呼的人在社区中已经上升到一个信任的水平,因此他们现在被给予一些权限。这表现为对非受保护分支的推送权限,以及在批准请求时拥有发言权。
+每个项目对核心开发者的定义可能略有不同。 当然,通常来说,拥有这种称呼的人在社区中已经上升到一个信任的水平,因此他们现在被给予一些权限。 这表现为对非受保护分支的推送权限,以及在批准请求时拥有发言权。
+
+The projects employ various communication mechanisms to ensure that all contributions are reviewed by the community as a whole. This includes tools provided by GitHub, as well as the Community Forums. By the time a contributor is invited to become a core developer, they should be familiar with the various tools and workflows as a user and then as a contributor.
_如何成为核心开发者?_
-任何人都可以成为核心开发者。除了表现出作为团队成员积极参与项目的意愿和能力之外,没有其他特殊要求。
+任何人都可以成为核心开发者。 除了表现出作为团队成员积极参与项目的意愿和能力之外,没有其他特殊要求。
-通常,一个潜在的核心开发者需要展现出他对项目目标与理念的深度理解。他们还将在一段时间内为该项目做出宝贵贡献。但是,对于资格没有 **技术** 或 **其他技能** 的要求
+通常,一个潜在的核心开发者需要展现出他对项目目标与理念的深度理解。 他们还将在一段时间内为该项目做出宝贵贡献。 但是,对于资格没有 **技术** 或 **其他技能** 的要求
-新的核心开发者可以由现有的任何核心开发者 **随时** 提名。指导委员会每年至少举行两次投票(4 月 和 10 月)。投票应以无记名投票方式进行。该项目的每一个现有的核心开发者都将获得相当于选票上被提名者人数的票数。例如,如果有四个提名者,那么每个现有的核心开发者有四票。核心开发者可以投出他们的选票,但是不能将选票重复投给同一个候选人。被提名的候选人必须获得三分之二的选票数才会被批准。一旦被核心开发团队接受,指导委员会有责任批准并最终确定提名。指导委员会无权决定被提名人是否有足够的资格获得核心开发者称号。当然,在必要的情况下,他们保留否定投票结果的权利。
+新的核心开发者可以由现有的任何核心开发者 **随时** 提名。 指导委员会每年至少举行两次投票(4 月 和 10 月)。 投票应以无记名投票方式进行。 该项目的每一个现有的核心开发者都将获得相当于选票上被提名者人数的票数。 例如,如果有四个提名者,那么每个现有的核心开发者有四票。 核心开发者可以投出他们的选票,但是不能将选票重复投给同一个候选人。 被提名的候选人必须获得三分之二的选票数才会被批准。 一旦被核心开发团队接受,指导委员会有责任批准并最终确定提名。 指导委员会无权决定被提名人是否有足够的资格获得核心开发者称号。 当然,在必要的情况下,他们保留否定投票结果的权利。
-投票结束后,投票结果将在社区论坛上进行公布。被提名人有权要求对任何针对他们的否决进行解释。未被录取为核心开发者的被提名人,可以在之后的选举中被再次提名。
+投票结束后,投票结果将在社区论坛上进行公布。 被提名人有权要求对任何针对他们的否决进行解释。 未被录取为核心开发者的被提名人,可以在之后的选举中被再次提名。
-最重要的是要明白成为核心开发者是一种荣誉,而不是一种权利。只要成为核心开发者就必然获得这种荣誉。当然,指导委员会可以在极端情况下取消核心开发者称号(见下一节)。在正常情况下,只要个人希望继续参与项目和社区,核心开发者的头衔就一直存在。
+最重要的是要明白成为核心开发者是一种荣誉,而不是一种权利。 That privilege must be earned and once earned it can be removed by the Steering Council (see next section) in extreme circumstances. 在正常情况下,只要个人希望继续参与项目和社区,核心开发者的头衔就一直存在。
-对项目做出高于平均水平的贡献,特别是在战略方向和长期发展方面的贡献,可以被提名为指导委员会成员或发布经理。
+A committer who shows an above-average level of contribution to the project, particularly with respect to its strategic direction and long-term health, may be nominated to become a member of the Steering Council, or a Release Manager. This role is described below.
-_核心开发者的权力和责任是什么?_
+_如果核心开发者变得不活跃怎么办?_
-如前所述,大多数决策都是通过协商并达成共识做出的。在某些情况下,当某个问题变得具有争议,或者需要做出重大决策时,发布经理或指导委员会可能会决定(或被要求)实施 RFC 流程,这将在之后进行详细介绍。
+如前所述,大多数决策都是通过协商并达成共识做出的。 在某些情况下,当某个问题变得具有争议,或者需要做出重大决策时,发布经理或指导委员会可能会决定(或被要求)实施 RFC 流程,这将在之后进行详细介绍。
-核心开发者在社区治理中同样拥有发言权。所有项目的所有核心开发者都有被提名为指导委员会委员和在选举中投票的权力。
+核心开发者在社区治理中同样拥有发言权。 所有项目的所有核心开发者都有被提名为指导委员会委员和在选举中投票的权力。
-本社区公约只能在三分之二活跃核心开发者的授权下进行更改,除非在采用后的前六个月内,多数核心开发者否定了多数活跃核心开发者的授权。
+对项目做出高于平均水平的贡献,特别是在战略方向和长期发展方面的贡献,可以被提名为指导委员会成员或发布经理。
-_如果核心开发者变得不活跃怎么办?_
+_核心开发者的权力和责任是什么?_
-虽然我们希望所有核心开发者能够定期参与并保持活跃。但是大家都明白,这种承诺有时并不现实。
+虽然我们希望所有核心开发者能够定期参与并保持活跃。 但是大家都明白,这种承诺有时并不现实。
-因此,指导委员会有责任鼓励参与,并有责任将不再愿意或没有能力参与的核心开发者置于不活跃状态。这样做的主要目的 **不是为了惩罚** 一个人的行为,而是为了帮助那些确实保持活跃的人继续发展。
+因此,指导委员会有责任鼓励参与,并有责任将不再愿意或没有能力参与的核心开发者置于不活跃状态。 这样做的主要目的 **不是为了惩罚** 一个人的行为,而是为了帮助那些确实保持活跃的人继续发展。
-一个变得“不活跃”的核心开发者不应该拥有存储库的提交权,也不应该参与任何投票。为了有资格在选举中投票,核心开发人员必须在先前计划的项目发布时处于 **活跃状态**。
+一个变得“不活跃”的核心开发者不应该拥有存储库的提交权,也不应该参与任何投票。 为了有资格在选举中投票,核心开发人员必须在先前计划的项目发布时处于 **活跃状态**。
不活跃的成员可以随时要求指导委员会恢复他们的状态,根据这种请求,指导委员会应使核心开发者再次归为活跃状态。
-如果个人知道他们将在一段时间内无法保持其活跃状态,则会被要求与指导委员会保持联系,并在必要时宣布自己处于不活跃状态。
+Individuals that know they will be unable to maintain their active status for a period are asked to be in communication with the Steering Council and declare themselves inactive if necessary.
-“活跃的”核心开发者是指在过去六个月中以有意义的方式参与的核心开发者。最终解释权归指导委员会所有。
+“活跃的”核心开发者是指在过去六个月中以有意义的方式参与的核心开发者。 最终解释权归指导委员会所有。
### 发布经理(Release Manager)
-核心开发者只能在不受保护的分支上进行提交和合并。主分支和其他受保护的分支由该项目的发布管理团队控制。发布经理应由核心开发团队从核心开发团队中选出,并应在整个发布周期为大家服务。
+核心开发者只能在不受保护的分支上进行提交和合并。 主分支和其他受保护的分支由该项目的发布管理团队控制。 发布经理应由核心开发团队从核心开发团队中选出,并应在整个发布周期为大家服务。
-每个核心开发团队可以决定每个发布周期有多少个发布经理。建每一个发布周期至少有两个发布经理,以分担职责。不能让一个人承担所有的压力。但是,也不应该有太多的发布经理,这样项目维护起来会变得十分繁琐。
+每个核心开发团队可以决定每个发布周期有多少个发布经理。 建每一个发布周期至少有两个发布经理,以分担职责。 不能让一个人承担所有的压力。 However, there also should not be so many managers that their efforts are impeded.
-发布管理团队的主要职责:
+如果个人知道他们将在一段时间内无法保持其活跃状态,则会被要求与指导委员会保持联系,并在必要时宣布自己处于不活跃状态。
-* 通过监听和促进技术讨论来推进开发周期
-* 制定发布日历并执行发布所需的操作
-* 批准对主分支和其他受保护分支的请求
-* 将请求合并到主分支和其他受保护的分支
+* 通过监听和促进技术讨论来推进开发周期
+* 制定发布日历并执行发布所需的操作
+* 批准对主分支和其他受保护分支的请求
+* 将请求合并到主分支和其他受保护的分支
-发布经理 **无权否决或拒绝** 那些 **符合贡献标准并已被社区接受** 的合并请求。他们无权决定开发什么。他们的责任是执行社区的决定,推进项目的进度。
+发布经理 **无权否决或拒绝** 那些 **符合贡献标准并已被社区接受** 的合并请求。 他们无权决定开发什么。 他们的责任是执行社区的决定,推进项目的进度。
-有时,可能需要做出无法通过协商达成共识的决定。在这种情况下,发布经理有权要求 RFC 流程删除决策。这种情况不应经常发生(除非有以下讨论的要求)。不应该鼓励使用这种方法,而是采用更有利于建立社区共识的方法。
+有时,可能需要做出无法通过协商达成共识的决定。 在这种情况下,发布经理有权要求 RFC 流程删除决策。 This should not occur regularly (unless required as discussed below), and its use should be discouraged in favor of the more communal consensus building strategy.
-由于并非所有的项目都有相同的要求,所以管理项目发布经理的细节应在本公约的附录或项目贡献指南中规定。
+Since not all projects have the same requirements, the specifics governing release managers on a project shall be set forth in an Appendix to this Policy, or in the project’s contribution guidelines.
-如有必要或出于其他正当理由,指导委员会有权撤换失职的发布经理。
+发布管理团队的主要职责:
### 指导委员会(Steering Council)
-指导委员会是由被确定为 “项目所有人” 并控制 SCO 资源和资产的个人组成的管理组织。他们的最终目标是通过消除障碍,并根据需要帮助成员,以确保项目的顺利进行。预计他们将成为社区的常客。
+指导委员会是由被确定为 “项目所有人” 并控制 SCO 资源和资产的个人组成的管理组织。 他们的最终目标是通过消除障碍,并根据需要帮助成员,以确保项目的顺利进行。 预计他们将成为社区的常客。
_指导委员会能做什么?_
-指导委员会的成员 **没有** 比其他任何核心开发者更多的权力,也没有任何额外的权利对项目进行决策、提交、合并等。
+由于并非所有的项目都有相同的要求,所以管理项目发布经理的细节应在本公约的附录或项目贡献指南中规定。
-但是,指导委员会具有以下职能:
+如有必要或出于其他正当理由,指导委员会有权撤换失职的发布经理。
-* 同意、搁置和拒绝所有的 RFC 建议
-* 强制执行社区行为准则
-* 管理社区资产,如存储库、服务器、论坛、集成服务等(或者将这些权限委托给其他人)
-* 在适当的情况下,将核心开发者置于不活跃状态,并采取本政策中规定的任何其他强制措施。包括在极端情况下,移除核心开发者
-* 从社区保护伞下采纳或移除项目
+* 同意、搁置和拒绝所有的 RFC 建议
+* 强制执行社区行为准则
+* 管理社区资产,如存储库、服务器、论坛、集成服务等(或者将这些权限委托给其他人)
+* 在适当的情况下,将核心开发者置于不活跃状态,并采取本政策中规定的任何其他强制措施。
+* 从社区保护伞下采纳或移除项目
我们强烈建议指导委员会尽可能将其权力授予其他有意愿的社区成员。
@@ -165,31 +162,39 @@ _指导委员会能做什么?_
_指导委员会有多少成员?_
+但是,指导委员会具有以下职能:
+
+虽然只拥有 4 票的委员会可能会陷入僵局,无法打破多数票,但指导委员应该尽可能少地投票。 相反,它应该努力以协商一致的方式工作。 在有必要就一个问题进行表决时,需要三票同意。
+
+_指导委员是如何选出的?_
+
+单个任期应为两年,从 1 月开始。 任期应错开,以便于每年有两名成员从上一年的理事会延续下来。
+
4 个。
-虽然只拥有 4 票的委员会可能会陷入僵局,无法打破多数票,但指导委员应该尽可能少地投票。相反,它应该努力以协商一致的方式工作。在有必要就一个问题进行表决时,需要三票同意。
+There are no limits to the number of terms that can be served, and it is possible for an individual to serve consecutive terms.
_指导委员的任期是多久?_
-单个任期应为两年,从 1 月开始。任期应错开,以便于每年有两名成员从上一年的理事会延续下来。
-
-因此,选举投票将有两个任期为两年的职位,两个任期为一年的职位。
+指导委员会选出后,小组应集体决策由一人担任主席。 主席的权力和其他委员完全相同,没有任何额外的权力。
-可以任职的任期没有限制,个人有可能连续任职。
+主席的作用仅仅是作为协调者和推动者。 主席应确保遵守所有治理规则。 该职位更多的是行政和文书工作,预计主席将制定议程并协调小组讨论。
_指导委员会如何运作?_
-指导委员会选出后,小组应集体决策由一人担任主席。主席的权力和其他委员完全相同,没有任何额外的权力。
+指导委员会的成员 **没有** 比其他任何核心开发者更多的权力,也没有任何额外的权利对项目进行决策、提交、合并等。
-主席的作用仅仅是作为协调者和推动者。主席应确保遵守所有治理规则。该职位更多的是行政和文书工作,预计主席将制定议程并协调小组讨论。
+选举提名从 9 月 1 日开始,9 月 30 日截止。 投票于 10 月 1 日开始,10 月 31 日结束。 每个在 6 月份发布该年度版本时活跃的核心开发者都能够参与选举和投票,每一位核心开发者都能获得相当于空缺的指导委员数量的选票。 为了公平起见,核心开发者 **不需要** 是 Sanic Framework 的核心开发者,而是在各自的项目中处于活跃状态的核心开发者。
-_指导委员是如何选出的?_
+获得票数最多的核心开发者将被宣布成为指导委员会委员。 如果有任何平票,强烈建议平票的被提名者自己解决争议,然后再随机做出决定。
+
+因此,选举投票将有两个任期为两年的职位,两个任期为一年的职位。
每年一次,**所有核心开发者** 都有权选举指导委员会委员。
-选举提名从 9 月 1 日开始,9 月 30 日截止。投票于 10 月 1 日开始,10 月 31 日结束。每个在 6 月份发布该年度版本时活跃的核心开发者都能够参与选举和投票,每一位核心开发者都能获得相当于空缺的指导委员数量的选票。为了公平起见,核心开发者 **不需要** 是 Sanic Framework 的核心开发者,而是在各自的项目中处于活跃状态的核心开发者。
+_What if there is a vacancy?_
-获得票数最多的核心开发者将被宣布成为指导委员会委员。如果有任何平票,强烈建议平票的被提名者自己解决争议,然后再随机做出决定。
+如果指导委员会在某个任期内存在空缺,则应提供上一次选举中得票次高的候选人来完成剩余任期。 如果找不到合适的人选,指导委员会可以决定最合适的人选(通过任命、投票或其他方式)。
关于指导委员会的创始投票,得票最多的两位当选者任期两年,之后两位当选者将获得一年的任期。
@@ -197,39 +202,31 @@ _指导委员是如何选出的?_
_如果空缺怎么办?_
-如果指导委员会在某个任期内存在空缺,则应提供上一次选举中得票次高的候选人来完成剩余任期。如果找不到合适的人选,指导委员会可以决定最合适的人选(通过任命、投票或其他方式)。
-
-如果指导委员会的一名成员处于不活跃状态,则该成员应立即从指导委员会中除名,该席位将空缺。
+指导委员会应尽可能公开开展工作和讨论。 社区的任何成员都可以和他们进行对话。 当然,有时私下讨论可能是必要的或适当的。 选择合适的谈话地点是主席管理职责的一部分。
-在极端情况下,所有的核心开发者团队有权以投票的方式表决罢免指导委员会委员(需要超过三分之二的核心开发者赞同)
+虽然如何操作的细节超出了本公约的范围,但我们鼓励指导委员会尝试每季度至少召开一次“实时”讨论会议。 这可以通过视频会议、实时聊天或其他适当的方式来实现。
-_指导委员会应如何展开工作?_
+支持(Support)
+-------
-指导委员会应尽可能公开开展工作和讨论。社区的任何成员都可以和他们进行对话。当然,有时私下讨论可能是必要的或适当的。选择合适的谈话地点是主席管理职责的一部分。
+鼓励社区中的所有参与者在项目管理基础架构中为用户提供技术支持。 这种支持是作为社区发展的一种方式提供的。 寻求支持的人应该意识到,项目中的所有技术支持都是自愿的,是在时间允许的情况下提供的。 因此,要求保证响应时间或结果的用户应该寻求从社区成员处购买支持。 当然,对于那些愿意以自己的方式参与项目,并愿意帮助支持其他用户的人来说,社区支持渠道是最理想的。
-虽然如何操作的细节超出了本公约的范围,但我们鼓励指导委员会尝试每季度至少召开一次“实时”讨论会议。这可以通过视频会议、实时聊天或其他适当的方式来实现。
+决策过程(Decision making process)
+-----------------------
-## 支持(Support)
+从最新用户到最有经验的成员,通过与社区所有成员的讨论来决定项目的未来。 每个人都具有发言权。
-鼓励社区中的所有参与者在项目管理基础架构中为用户提供技术支持。这种支持是作为社区发展的一种方式提供的。寻求支持的人应该意识到,项目中的所有技术支持都是自愿的,是在时间允许的情况下提供的。因此,要求保证响应时间或结果的用户应该寻求从社区成员处购买支持。当然,对于那些愿意以自己的方式参与项目,并愿意帮助支持其他用户的人来说,社区支持渠道是最理想的。
+所有非敏感项目管理讨论都在社区论坛或其他指定渠道进行。 偶尔,敏感的讨论可能会私下进行。
-## 决策过程(Decision making process)
-
-从最新用户到最有经验的成员,通过与社区所有成员的讨论来决定项目的未来。每个人都具有发言权。
-
-所有非敏感项目管理讨论都在社区论坛或其他指定渠道进行。偶尔,敏感的讨论可能会私下进行。
-
-为了确保项目不会因无休止的讨论和持续的投票导致停滞不前,该项目采取了 **惰性共识** 政策。这使得大多数决策无需正式投票即可做出。对于任何 **重大决策** (定义如下),都有单独的征求意见(RFC)流程。
+为了确保项目不会因无休止的讨论和持续的投票导致停滞不前,该项目采取了 **惰性共识** 政策。 这使得大多数决策无需正式投票即可做出。 对于任何 **重大决策** (定义如下),都有单独的征求意见(RFC)流程。
### 技术决策(Technical decisions)
技术决策通常应分为以下几类:
-* **常规决策**:文档修复,用于清理或附加测试代码的更改。功能没有变化。
-
-* **次要决策**:对代码库的修改,修复一个错误或引入一个无关紧要的特性。没有突破性的变化。
-
-* **重要决策**: 对代码库的任何更改都会中断或弃用现有的应用接口,以一种非同寻常的方式改变操作,或者增加一个重要的特性。
+* **常规决策**:文档修复,用于清理或附加测试代码的更改。 功能没有变化。
+* **次要决策**:对代码库的修改,修复一个错误或引入一个无关紧要的特性。 没有突破性的变化。
+* **重要决策**: 对代码库的任何更改都会中断或弃用现有的应用接口,以一种非同寻常的方式改变操作,或者增加一个重要的特性。
发布经理通常有责任确保对存储库的更改在合并之前得到适当的授权。
@@ -239,29 +236,29 @@ _指导委员会应如何展开工作?_
决策(无论是由社区还是指导委员会)通常包括以下步骤:
-* 提议
-* 讨论
-* 投票(如果讨论未达成共识)
-* 决策
+* 提议
+* 讨论
+* 投票(如果讨论未达成共识)
+* 决策
-任何社区成员都可以提出建议供社区考虑。为了发起关于一个新想法的讨论,他们应该在社区论坛的适当渠道上发布一条消息,或者在 GitHub 上提交一个实现该想法的请求。这将促进对这一想法进行审查,并在必要时进行讨论。
+任何社区成员都可以提出建议供社区考虑。 为了发起关于一个新想法的讨论,他们应该在社区论坛的适当渠道上发布一条消息,或者在 GitHub 上提交一个实现该想法的请求。 这将促进对这一想法进行审查,并在必要时进行讨论。
-本次评审和讨论的目的是获得对贡献的认可。由于项目社区中的大多数人都有一个共同的愿景,因此通常很少需要讨论来达成共识。
+本次评审和讨论的目的是获得对贡献的认可。 由于项目社区中的大多数人都有一个共同的愿景,因此通常很少需要讨论来达成共识。
-一般来说,只要没有人明确反对一个提案或补丁,它就被认为得到了社区的支持。这叫惰性共识;也就是说,那些没有明确表示意见的人已经含蓄地同意了执行这项建议。
+一般来说,只要没有人明确反对一个提案或补丁,它就被认为得到了社区的支持。 这叫惰性共识;也就是说,那些没有明确表示意见的人已经含蓄地同意了执行这项建议。
-惰性共识是 SCO 内一个非常重要的概念。正是这一过程使一大群人能够有效地达成共识,因为对一项提议没有异议的人不需要花时间阐述他们的立场,其他人也不需要花时间阅读这些信息。
+惰性共识是 SCO 内一个非常重要的概念。 正是这一过程使一大群人能够有效地达成共识,因为对一项提议没有异议的人不需要花时间阐述他们的立场,其他人也不需要花时间阅读这些信息。
-为了使惰性共识有效,有必要在假设没有人反对该提案之前留出适当的时间。这在一定程度上取决于具体情况,但一般认为 72 小时是合理的。这一要求确保每个人都有足够的时间阅读、消化和回应提案。选择该时间段是为了尽可能包容所有参与者,无论他们的位置和时间如何。讨论主持人(无论是主席还是发布经理)应负责确定达成此类共识的适当时间长度。
+为了使惰性共识有效,有必要在假设没有人反对该提案之前留出适当的时间。 这在一定程度上取决于具体情况,但一般认为 72 小时是合理的。 这一要求确保每个人都有足够的时间阅读、消化和回应提案。 选择该时间段是为了尽可能包容所有参与者,无论他们的位置和时间如何。 讨论主持人(无论是主席还是发布经理)应负责确定达成此类共识的适当时间长度。
-如上所述,关于所谓的常规决策,发布经理有权在较短的时间内做出决策。在这种情况下,应暗示惰性共识。
+如上所述,关于所谓的常规决策,发布经理有权在较短的时间内做出决策。 在这种情况下,应暗示惰性共识。
### 意见征求(Request for Comment)(RFC)
-指导委员会应负责监督意见征求的过程。这将是一个向社区所有成员开放的辩论过程,并应留出充足的时间来审议一项提案,让成员做出回应并参与有意义的讨论。
+指导委员会应负责监督意见征求的过程。 这将是一个向社区所有成员开放的辩论过程,并应留出充足的时间来审议一项提案,让成员做出回应并参与有意义的讨论。
-最终决定权属于指导委员会。但是,强烈建议指导委员会不要通过与社区中可能存在的任何共识相悖的决定。有时可能会发生共识与整体项目和社区目标之间存在冲突的情况。
+最终决定权属于指导委员会。 但是,强烈建议指导委员会不要通过与社区中可能存在的任何共识相悖的决定。 有时可能会发生共识与整体项目和社区目标之间存在冲突的情况。
-应该按照指导委员会的规定,以公开的方式向指导委员会提交建议书,从而启动征求建议书。辩论应继续进行,并由指导委员会,特别是主席提供便利。
+应该按照指导委员会的规定,以公开的方式向指导委员会提交建议书,从而启动征求建议书。 辩论应继续进行,并由指导委员会,特别是主席提供便利。
在指导委员会认为合适的情况下,可以放弃征求建议书程序,达成惰性共识。
From 6614fed2588f16dffd912a89f039feb084d82db9 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:28 +0300
Subject: [PATCH 181/776] New translations scope.md (Portuguese, Brazilian)
---
src/pt/org/scope.md | 264 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 264 insertions(+)
create mode 100644 src/pt/org/scope.md
diff --git a/src/pt/org/scope.md b/src/pt/org/scope.md
new file mode 100644
index 0000000000..1af529361a
--- /dev/null
+++ b/src/pt/org/scope.md
@@ -0,0 +1,264 @@
+---
+title: S.C.O.P.E
+---
+
+
+Sanic Community Organization Policy E-manual
+============================================
+
+December 2019, version 1
+
+Goals
+-----
+
+To create a sustainable, community-driven organization around the Sanic projects that promote: (1) stability and predictability, (2) quick iteration and enhancement cycles, (3) engagement from outside contributors, (4) overall reliable software, and (5) a safe, rewarding environment for the community members.
+
+Overview
+--------
+
+This Policy is the governance model for the Sanic Community Organization (“SCO”). The SCO is a meritocratic, consensus-based community organization responsible for all projects adopted by it. Anyone with an interest in one of the projects can join the community, contribute to the community or projects, and participate in the decision making process. This document describes how that participation takes place and how to set about earning merit within the project community.
+
+Structure
+---------
+
+The SCO has multiple **projects**. Each project is represented by a single GitHub repository under the Sanic community umbrella. These projects are used by **users**, developed by **contributors**, governed by **core developers**, released by **release managers**, and ultimately overseen by a **steering council**. If this sounds similar to the Python project and PEP 8016 that is because it is intentionally designed that way.
+
+Roles and responsibilities
+--------------------------
+
+### Users
+
+Users are community members who have a need for the projects. They are the developers and personnel that download and install the packages. Users are the **most important** members of the community and without them the projects would have no purpose. Anyone can be a user and the licenses adopted by the projects shall be appropriate open source licenses.
+
+_The SCO asks its users to participate in the project and community as much as possible._
+
+User contributions enable the project team to ensure that they are satisfying the needs of those users. Common user contributions include (but are not limited to):
+
+* evangelizing about the project (e.g. a link on a website and word-of-mouth awareness raising)
+* informing developers of strengths and weaknesses from a new user perspective
+* providing moral support (a ‘thank you’ goes a long way)
+* providing financial support (the software is open source, but its developers need to eat)
+
+Users who continue to engage with the SCO, its projects, and its community will often become more and more involved. Such users may find themselves becoming contributors, as described in the next section.
+
+### Contributors
+
+Contributors are community members who contribute in concrete ways to one or more of the projects. Anyone can become a contributor and contributions can take many forms. Contributions and requirements are governed by each project separately by a contribution policy.
+
+There is **no expectation** of commitment to the project, **no specific skill requirements** and **no selection process**.
+
+In addition to their actions as users, contributors may also find themselves doing one or more of the following:
+
+* supporting new users (existing users are often the best people to support new users)
+* reporting bugs
+* identifying requirements
+* providing graphics and web design
+* Programming
+* example use cases
+* assisting with project infrastructure
+* writing documentation
+* fixing bugs
+* adding features
+* providing constructive opinions and engaging in community discourse
+
+Contributors engage with the projects through GitHub and the Community Forums. They submit changes to the projects itself via pull requests, which will be considered for inclusion in the project by the community at large. The Community Forums are the most appropriate place to ask for help when making that first contribution.
+
+Indeed one of the most important roles of a contributor may be to **simply engage in the community conversation**. Most decisions about the direction of a project are made by consensus. This is discussed in more detail below. In general, however, it is helpful for the health and direction of the projects for the contributors to **speak freely** (within the confines of the code of conduct) and **express their opinions and experiences** to help drive the consensus building.
+
+As contributors gain experience and familiarity with a project, their profile within, and commitment to, the community will increase. At some stage, they may find themselves being nominated for a core developer team.
+
+### Core Developer
+
+Each project under the SCO umbrella has its own team of core developers. They are the people in charge of that project.
+
+_What is a core developer?_
+
+Core developers are community members who have shown that they are committed to the continued development of the project through ongoing engagement with the community. Being a core developer allows contributors to more easily carry on with their project related activities by giving them direct access to the project’s resources. They can make changes directly to the project repository without having to submit changes via pull requests from a fork.
+
+This does not mean that a core developer is free to do what they want. In fact, core developers have no more direct authority over the final release of a package than do contributors. While this honor does indicate a valued member of the community who has demonstrated a healthy respect for the project’s aims and objectives, their work continues to be reviewed by the community before acceptance in an official release.
+
+_What can a core developer do on a project?_
+
+Each project might define this role slightly differently. However, the general usage of this designation is that an individual has risen to a level of trust within the community such that they now are given some control. This comes in the form of push rights to non-protected branches, and the ability to have a voice in the approval of pull requests.
+
+The projects employ various communication mechanisms to ensure that all contributions are reviewed by the community as a whole. This includes tools provided by GitHub, as well as the Community Forums. By the time a contributor is invited to become a core developer, they should be familiar with the various tools and workflows as a user and then as a contributor.
+
+_How to become a core developer?_
+
+Anyone can become a core developer; there are no special requirements, other than to have shown a willingness and ability to positively participate in the project as a team player.
+
+Typically, a potential core developer will need to show that they have an understanding of the project, its objectives and its strategy. They will also have provided valuable contributions to the project over a period of time. However, there is **no technical or other skill** requirement for eligibility.
+
+New core developers can be **nominated by any existing core developer** at any time. At least twice a year (April and October) there will be a ballot process run by the Steering Council. Voting should be done by secret ballot. Each existing core developer for that project receives a number of votes equivalent to the number of nominees on the ballot. For example, if there are four nominees, then each existing core developer has four votes. The core developer may cast those votes however they choose, but may not vote for a single nominee more than once. A nominee must receive two-thirds approval from the number of cast ballots (not the number of eligible ballots). Once accepted by the core developers, it is the responsibility of the Steering Council to approve and finalize the nomination. The Steering Council does not have the right to determine whether a nominee is meritorious enough to receive the core developer title. However, they do retain the right to override a vote in cases where the health of the community would so require.
+
+Once the vote has been held, the aggregated voting results are published on the Community Forums. The nominee is entitled to request an explanation of any override against them. A nominee that fails to be admitted as a core developer may be nominated again in the future.
+
+It is important to recognize that being a core developer is a privilege, not a right. That privilege must be earned and once earned it can be removed by the Steering Council (see next section) in extreme circumstances. However, under normal circumstances the core developer title exists for as long as the individual wishes to continue engaging with the project and community.
+
+A committer who shows an above-average level of contribution to the project, particularly with respect to its strategic direction and long-term health, may be nominated to become a member of the Steering Council, or a Release Manager. This role is described below.
+
+_What are the rights and responsibilities of core developers?_
+
+As discussed, the majority of decisions to be made are by consensus building. In certain circumstances where an issue has become more contentious, or a major decision needs to be made, the Release Manager or Steering Council may decide (or be required) to implement the RFC process, which is outlined in more detail below.
+
+It is also incumbent upon core developers to have a voice in the governance of the community. All core developers for all of the projects have the ability to be nominated to be on the Steering Council and vote in their elections.
+
+This Policy (the “SCOPE”) may only be changed under the authority of two-thirds of active core developers, except that in the first six (6) months after adoption, the core developers reserve the right to make changes under the authority of a simple majority of active core developers.
+
+_What if a core developer becomes inactive?_
+
+It is hoped that all core developers participate and remain active on a regular basis in their projects. However, it is also understood that such commitments may not be realistic or possible from time to time.
+
+Therefore, the Steering Council has the duty to encourage participation and the responsibility to place core developers into an inactive status if they are no longer willing or capable to participate. The main purpose of this is **not to punish** a person for behavior, but to help the development process to continue for those that do remain active.
+
+To this end, a core developer that becomes “inactive” shall not have commit rights to a repository, and shall not participate in any votes. To be eligible to vote in an election, a core developer **must have been active** at the time of the previous scheduled project release.
+
+Inactive members may ask the Steering Council to reinstate their status at any time, and upon such request the Steering Council shall make the core developer active again.
+
+Individuals that know they will be unable to maintain their active status for a period are asked to be in communication with the Steering Council and declare themselves inactive if necessary.
+
+An “active” core developer is an individual that has participated in a meaningful way during the previous six months. Any further definition is within the discretion of the Steering Council.
+
+### Release Manager
+
+Core developers shall have access only to make commits and merges on non-protected branches. The “master” branch and other protected branches are controlled by the release management team for that project. Release managers shall be elected from the core development team by the core development team, and shall serve for a full release cycle.
+
+Each core developer team may decide how many release managers to have for each release cycle. It is highly encouraged that there be at least two release managers for a release cycle to help divide the responsibilities and not force too much effort upon a single person. However, there also should not be so many managers that their efforts are impeded.
+
+The main responsibilities of the release management team include:
+
+* push the development cycle forward by monitoring and facilitating technical discussions
+* establish a release calendar and perform actions required to release packages
+* approve pull requests to the master branch and other protected branches
+* merge pull requests to the master branch and other protected branches
+
+The release managers **do not have the authority to veto or withhold a merge** of a pull request that otherwise meets contribution criteria and has been accepted by the community. It is not their responsibility to decide what should be developed, but rather that the decisions of the community are carried out and that the project is being moved forward.
+
+From time to time, a decision may need to be made that cannot be achieved through consensus. In that case, the release managers have the authority to call upon the removal of the decision to the RFC process. This should not occur regularly (unless required as discussed below), and its use should be discouraged in favor of the more communal consensus building strategy.
+
+Since not all projects have the same requirements, the specifics governing release managers on a project shall be set forth in an Appendix to this Policy, or in the project’s contribution guidelines.
+
+If necessary, the Steering Council has the right to remove a release manager that is derelict in their duties, or for other good cause.
+
+### Steering Council
+
+The Steering Council is the governing body consisting of those individuals identified as the “project owner” and having control of the resources and assets of the SCO. Their ultimate goal is to ensure the smooth operation of the projects by removing impediments, and assisting the members as needed. It is expected that they will be regular voices in the community.
+
+_What can the Steering Council do?_
+
+The members of the Steering Council **do not individually have any more authority than any other core developer**, and shall not have any additional rights to make decisions, commits, merges, or the like on a project.
+
+However, as a body, the Steering Council has the following capacity:
+
+* accept, remand, and reject all RFCs
+* enforce the community code of conduct
+* administer community assets such as repositories, servers, forums, integration services, and the like (or, to delegate such authority to someone else)
+* place core developers into inactive status where appropriate take any other enforcement measures afforded to it in this Policy, including, in extreme cases, removing core developers
+* adopt or remove projects from the community umbrella
+
+It is highly encouraged that the Steering Council delegate its authority as much as possible, and where appropriate, to other willing community members.
+
+The Steering Council **does not have the authority** to change this Policy.
+
+_How many members are on the Steering Council?_
+
+Four.
+
+While it seems like a committee with four votes may potentially end in a deadlock with no way to break a majority vote, the Steering Council is discouraged from voting as much as possible. Instead, it should try to work by consensus, and requires three consenting votes when it is necessary to vote on a matter.
+
+_How long do members serve on the Steering Council?_
+
+A single term shall be for two calendar years starting in January. Terms shall be staggered so that each year there are two members continuing from the previous year’s council.
+
+Therefore, the inaugural vote shall have two positions available for a two year term, and two positions available for a one year term.
+
+There are no limits to the number of terms that can be served, and it is possible for an individual to serve consecutive terms.
+
+_Who runs the Steering Council?_
+
+After the Steering Council is elected, the group shall collectively decide upon one person to act as the Chair. The Chair does not have any additional rights or authority over any other member of the Steering Council.
+
+The role of the Chair is merely as a coordinator and facilitator. The Chair is expected to ensure that all governance processes are adhered to. The position is more administrative and clerical, and is expected that the Chair sets agendas and coordinates discussion of the group.
+
+_How are council members elected?_
+
+Once a year, **all eligible core developers** for each of the projects shall have the right to elect members to the Steering Council.
+
+Nominations shall be open from September 1 and shall close on September 30. After that, voting shall begin on October 1 and shall close on October 31. Every core developer active on the date of the June release of the Sanic Framework for that year shall be eligible to receive one vote per vacant seat on the Steering Council. For the sake of clarity, to be eligible to vote, a core developer **does not** need to be a core developer on Sanic Framework, but rather just have been active within their respective project on that date.
+
+The top recipients of votes shall be declared the winners. If there is any tie, it is highly encouraged that the tied nominees themselves resolve the dispute before a decision is made at random.
+
+In regards to the inaugural vote of the Steering Council, the top two vote-recipients shall serve for two years, and the next two vote-recipients shall assume the one-year seats.
+
+To be an eligible candidate for the Steering Council, the individual must have been a core developer in active status on at least one project for the previous twelve months.
+
+_What if there is a vacancy?_
+
+If a vacancy on the Steering Council exists during a term, then the next highest vote-recipient in the previous election shall be offered to complete the remainder of the term. If one cannot be found this way, the Steering Council may decide the most appropriate course of action to fill the seat (whether by appointment, vote, or other means).
+
+If a member of the Steering Council becomes inactive, then that individual shall be removed from the Steering Council immediately and the seat shall become vacant.
+
+In extreme cases, the body of all core developers has the right to bring a vote to remove a member of the Steering Council for cause by a two-thirds majority of all eligible voting core developers.
+
+_How shall the Steering Council conduct its business?_
+
+As much as possible, the Steering Council shall conduct its business and discussions in the open. Any member of the community should be allowed to enter the conversation with them. However, at times it may be necessary or appropriate for discussions to be held privately. Selecting the proper venue for conversations is part of the administrative duties of the Chair.
+
+While the specifics of how to operate are beyond the scope of the Policy, it is encouraged that the Steering Council attempt to meet at least one time per quarter in a “real-time” discussion. This could be achieved via video conferencing, live chatting, or other appropriate means.
+
+Support
+-------
+
+All participants in the community are encouraged to provide support for users within the project management infrastructure. This support is provided as a way of growing the community. Those seeking support should recognize that all support activity within the project is voluntary and is therefore provided as and when time allows. A user requiring guaranteed response times or results should therefore seek to purchase a support contract from a community member. However, for those willing to engage with the project on its own terms, and willing to help support other users, the community support channels are ideal.
+
+Decision making process
+-----------------------
+
+Decisions about the future of the projects are made through discussion with all members of the community, from the newest user to the most experienced member. Everyone has a voice.
+
+All non-sensitive project management discussion takes place on the community forums, or other designated channels. Occasionally, sensitive discussions may occur in private.
+
+In order to ensure that the project is not bogged down by endless discussion and continual voting, the project operates a policy of **lazy consensus**. This allows the majority of decisions to be made without resorting to a formal vote. For any **major decision** (as defined below), there is a separate Request for Comment (RFC) process.
+
+### Technical decisions
+
+Pull requests and technical decisions should generally fall into the following categories.
+
+* **Routine**: Documentation fixes, code changes that are for cleanup or additional testing. No functionality changes.
+* **Minor**: Changes to the code base that either fix a bug, or introduce a trivial feature. No breaking changes.
+* **Major**: Any change to the code base that breaks or deprecates existing API, alters operation in a non-trivial manner, or adds a significant feature.
+
+It is generally the responsibility of the release managers to make sure that changes to the repositories receive the proper authorization before merge.
+
+The release managers retain the authority to individually review and accept routine decisions that meet standards for code quality without additional input.
+
+### Lazy consensus
+
+Decision making (whether by the community or Steering Council) typically involves the following steps:
+
+* proposal
+* discussion
+* vote (if consensus is not reached through discussion)
+* decision
+
+Any community member can make a proposal for consideration by the community. In order to initiate a discussion about a new idea, they should post a message on the appropriate channel on the Community forums, or submit a pull request implementing the idea on GitHub. This will prompt a review and, if necessary, a discussion of the idea.
+
+The goal of this review and discussion is to gain approval for the contribution. Since most people in the project community have a shared vision, there is often little need for discussion in order to reach consensus.
+
+In general, as long as nobody explicitly opposes a proposal or patch, it is recognized as having the support of the community. This is called lazy consensus; that is, those who have not stated their opinion explicitly have implicitly agreed to the implementation of the proposal.
+
+Lazy consensus is a very important concept within the SCO. It is this process that allows a large group of people to efficiently reach consensus, as someone with no objections to a proposal need not spend time stating their position, and others need not spend time reading such messages.
+
+For lazy consensus to be effective, it is necessary to allow an appropriate amount of time before assuming that there are no objections to the proposal. This is somewhat dependent upon the circumstances, but it is generally assumed that 72 hours is reasonable. This requirement ensures that everyone is given enough time to read, digest and respond to the proposal. This time period is chosen so as to be as inclusive as possible of all participants, regardless of their location and time commitments. The facilitators of discussion (whether it be the Chair or the Release Managers, where applicable) shall be charged with determining the proper length of time for such consensus to be reached.
+
+As discussed above regarding so-called routine decisions, the release managers have the right to make decisions within a shorter period of time. In such cases, lazy consensus shall be implied.
+
+### Request for Comment (RFC)
+
+The Steering Council shall be in charge of overseeing the RFC process. It shall be a process that remains open to debate to all members of the community, and shall allow for ample time to consider a proposal and for members to respond and engage in meaningful discussion.
+
+The final decision is vested with the Steering Council. However, it is strongly discouraged that the Steering Council adopt a decision that is contrary to any consensus that may exist in the community. From time to time this may happen if there is a conflict between consensus and the overall project and community goals.
+
+An RFC shall be initiated by submission to the Steering Council in the public manner as set forth by the Steering Council. Debate shall continue and be facilitated by the Steering Council in general, and the Chair specifically.
+
+In circumstances that the Steering Council feels it is appropriate, the RFC process may be waived in favor of lazy consensus.
From 15e27d0b2cc021f6c52b68ebc24d9cfebcba14fc Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:30 +0300
Subject: [PATCH 182/776] New translations cors.md (Japanese)
---
src/ja/plugins/sanic-ext/http/cors.md | 38 +++++++++++++--------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/src/ja/plugins/sanic-ext/http/cors.md b/src/ja/plugins/sanic-ext/http/cors.md
index 493b522369..0da7e2aab7 100644
--- a/src/ja/plugins/sanic-ext/http/cors.md
+++ b/src/ja/plugins/sanic-ext/http/cors.md
@@ -1,16 +1,16 @@
# CORSの保護
-Cross-Origin Resource Sharing(別名:CORS)は、それだけで*巨大な*トピックです。この文書では、それが何であるかについて十分に詳しく説明することはできません。セキュリティ上の問題や解決策の背景にある理論について理解するために、ご自身で調査されることを強くお勧めします。[MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)が最初の一歩として最適です。
+Cross-Origin Resource Sharing(別名:CORS)は、それだけで*巨大な*トピックです。 この文書では、それが何であるかについて十分に詳しく説明することはできません。 セキュリティ上の問題や解決策の背景にある理論について理解するために、ご自身で調査されることを強くお勧めします。 [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)が最初の一歩として最適です。
-超簡単に説明すると、CORS 保護は、Web ページが別のドメインから情報にアクセスする方法とタイミングを容易にするために、ブラウザが使用するフレームワークです。これは、単一ページのアプリケーションを構築している人に非常に関連性の高いものです。フロントエンドは `https://portal.myapp.com` のようなドメインにありますが、バックエンドには `https://api.myapp.com` からアクセスする必要があることがよくあります。
+超簡単に説明すると、CORS 保護は、Web ページが別のドメインから情報にアクセスする方法とタイミングを容易にするために、ブラウザが使用するフレームワークです。 これは、単一ページのアプリケーションを構築している人に非常に関連性の高いものです。 フロントエンドは `https://portal.myapp.com` のようなドメインにありますが、バックエンドには `https://api.myapp.com` からアクセスする必要があることがよくあります。
-この実装は[`sanic-cors`](https://github.com/ashleysommer/sanic-cors)に強く影響を受けており、さらに[`flask-cors`](https://github.com/corydolphin/flask-cors) がベースになっています。したがって、`sanic-cors`を`sanic-ext`でほぼ完全に置き換えることができるでしょう。
+この実装は[`sanic-cors`](https://github.com/ashleysommer/sanic-cors)に強く影響を受けており、さらに[`flask-cors`](https://github.com/corydolphin/flask-cors) がベースになっています。 したがって、`sanic-cors`を`sanic-ext`でほぼ完全に置き換えることができるでしょう。
## 基本的な実装
---:1
-[自動エンドポイントの例](methods.md#options) にあるように、Sanic Extensions は特に何もしなくても自動的に CORS 保護を有効にします。しかし、それは箱から出してもあまり多くのものを提供しません。
+[自動エンドポイントの例](methods.md#options) にあるように、Sanic Extensions は特に何もしなくても自動的に CORS 保護を有効にします。 しかし、それは箱から出してもあまり多くのものを提供しません。
最低でも、`config.CORS_ORIGINS` をアプリケーションにアクセスする意図されたオリジンに設定することを **強く** お勧めします。
@@ -39,28 +39,28 @@ connection: keep-alive
## コンフィグレーション
-CORS 対策の真の威力は、設定を開始してから発揮されます。以下は、すべてのオプションの表です。
+CORS 対策の真の威力は、設定を開始してから発揮されます。 以下は、すべてのオプションの表です。
-| キー | タイプ | デフォルト | 説明 |
-|--|--|--|--|
-| `CORS_ALLOW_HEADERS` | `str` または `List[str]` | `"*"` | `access-control-allow-headers` に表示されるヘッダのリストです。 |
-| `CORS_ALWAYS_SEND` | `bool` | `True` | `True` の場合、常に `access-control-allow-origin` に値を設定します。`False` の場合、 `Origin` ヘッダがある場合にのみ設定されます。 |
-| `CORS_AUTOMATIC_OPTIONS` | `bool` | `True` | 受信したプリフライトリクエストに対して、 `access-control-allow-headers`, `access-control-max-age`, `access-control-allow-methods` へ自動的に値を設定するかどうかを指定することができます。`False` の場合、これらの値は `@cors` デコレーターでデコレートされたルートにのみ設定されます。 |
-| `CORS_EXPOSE_HEADERS` | `str` または `List[str]` | `""` | `access-control-expose-headers` ヘッダに設定するヘッダの指定リストです。 |
-| `CORS_MAX_AGE` | `str`, `int`, `timedelta` | `0` | `access-control-max-age` ヘッダーを使用してプリフライトリマインダーをキャッシュできる最大秒数です。虚偽の値を指定すると、このヘッダは設定されません。 |
-| `CORS_METHODS` | `str` または `List[str]` | `""` | 許可されたオリジンがアクセスできる HTTP メソッド (`access-control-allow-methods`ヘッダーで設定)。 |
-| `CORS_ORIGINS` | `str`, `List[str]`, `re.Pattern` | `"*"` | `access-control-allow-origin` ヘッダーで設定した、リソースへのアクセスを許可するオリジンを指定します。 |
-| `CORS_SEND_WILDCARD` | `bool` | `False` | `True` の場合、 `origin` リクエストヘッダの代わりにワイルドカード `*` オリジンを送信します。 |
-| `CORS_SUPPORTS_CREDENTIALS` | `bool` | `False` | `access-control-allow-credentials` ヘッダを設定するかどうか。 |
-| `CORS_VARY_HEADER` | `bool` | `True` | 適切な場合に `vary` ヘッダーを追加するかどうか。 |
+| キー | タイプ | デフォルト | 説明 |
+| --------------------------- | -------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `CORS_ALLOW_HEADERS` | `str` または `List[str]` | `"*"` | `access-control-allow-headers` に表示されるヘッダのリストです。 |
+| `CORS_ALWAYS_SEND` | `bool` | `True` | `True` の場合、常に `access-control-allow-origin` に値を設定します。 `False` の場合、 `Origin` ヘッダがある場合にのみ設定されます。 |
+| `CORS_AUTOMATIC_OPTIONS` | `bool` | `True` | 受信したプリフライトリクエストに対して、 `access-control-allow-headers`, `access-control-max-age`, `access-control-allow-methods` へ自動的に値を設定するかどうかを指定することができます。 `False` の場合、これらの値は `@cors` デコレーターでデコレートされたルートにのみ設定されます。 |
+| `CORS_EXPOSE_HEADERS` | `str` または `List[str]` | `""` | `access-control-expose-headers` ヘッダに設定するヘッダの指定リストです。 |
+| `CORS_MAX_AGE` | `str`, `int`, `timedelta` | `0` | `access-control-max-age` ヘッダーを使用してプリフライトリマインダーをキャッシュできる最大秒数です。 虚偽の値を指定すると、このヘッダは設定されません。 |
+| `CORS_METHODS` | `str` または `List[str]` | `""` | 許可されたオリジンがアクセスできる HTTP メソッド (`access-control-allow-methods`ヘッダーで設定)。 |
+| `CORS_ORIGINS` | `str`, `List[str]`, `re.Pattern` | `"*"` | `access-control-allow-origin` ヘッダーで設定した、リソースへのアクセスを許可するオリジンを指定します。 |
+| `CORS_SEND_WILDCARD` | `bool` | `False` | `True` の場合、 `origin` リクエストヘッダの代わりにワイルドカード `*` オリジンを送信します。 |
+| `CORS_SUPPORTS_CREDENTIALS` | `bool` | `False` | `access-control-allow-credentials` ヘッダを設定するかどうか。 |
+| `CORS_VARY_HEADER` | `bool` | `True` | 適切な場合に `vary` ヘッダーを追加するかどうか。 |
-*簡潔にするために、上記で `List[str]` と記述している場合は、 `list`, `set`, `frozenset`, または `tuple` のインスタンスであれば、何でも構いません。また、値が `str` の場合は、カンマで区切られたリストでも構いません*。
+**簡潔にするために、上記で `List[str]` と記述している場合は、 `list`, `set`, `frozenset`, または `tuple` のインスタンスであれば、何でも構いません。 また、値が `str` の場合は、カンマで区切られたリストでも構いません*。*
## ルートレベル・オーバーライド
---:1
-特定のルートに対して、アプリ全体の設定を上書きすることが必要な場合があります。これを可能にするために、`@sanic_ext.cors()` デコレーターを使用して、異なるルート固有の値を設定することができます。
+特定のルートに対して、アプリ全体の設定を上書きすることが必要な場合があります。 これを可能にするために、`@sanic_ext.cors()` デコレーターを使用して、異なるルート固有の値を設定することができます。
このデコレータでオーバーライドできる値は、以下のとおりです。
From 58c5c55006ab8468ae2cb3914673ac245042d95f Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:31 +0300
Subject: [PATCH 183/776] New translations cors.md (Korean)
---
src/ko/plugins/sanic-ext/http/cors.md | 86 +++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100644 src/ko/plugins/sanic-ext/http/cors.md
diff --git a/src/ko/plugins/sanic-ext/http/cors.md b/src/ko/plugins/sanic-ext/http/cors.md
new file mode 100644
index 0000000000..1149c04d0e
--- /dev/null
+++ b/src/ko/plugins/sanic-ext/http/cors.md
@@ -0,0 +1,86 @@
+# CORS protection
+
+Cross-Origin Resource Sharing (aka CORS) is a *huge* topic by itself. The documentation here cannot go into enough detail about *what* it is. You are highly encouraged to do some research on your own to understand the security problem presented by it, and the theory behind the solutions. [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) are a great first step.
+
+In super brief terms, CORS protection is a framework that browsers use to facilitate how and when a web page can access information from another domain. It is extremely relevant to anyone building a single-page application. Often times your frontend might be on a domain like `https://portal.myapp.com`, but it needs to access the backend from `https://api.myapp.com`.
+
+The implementation here is heavily inspired by [`sanic-cors`](https://github.com/ashleysommer/sanic-cors), which is in turn based upon [`flask-cors`](https://github.com/corydolphin/flask-cors). It is therefore very likely that you can achieve a near drop-in replacement of `sanic-cors` with `sanic-ext`.
+
+## Basic implementation
+
+---:1
+
+As shown in the example in the [auto-endpoints example](methods.md#options), Sanic Extensions will automatically enable CORS protection without further action. But, it does not offer too much out of the box.
+
+At a *bare minimum*, it is **highly** recommended that you set `config.CORS_ORIGINS` to the intended origin(s) that will be accessing the application.
+
+:--:1
+```python
+from sanic import Sanic, text
+from sanic_ext import Extend
+
+app = Sanic(__name__)
+app.config.CORS_ORIGINS = "http://foobar.com,http://bar.com"
+Extend(app)
+
+@app.get("/")
+async def hello_world(request):
+ return text("Hello, world.")
+```
+
+```
+$ curl localhost:8000 -X OPTIONS -i
+HTTP/1.1 204 No Content
+allow: GET,HEAD,OPTIONS
+access-control-allow-origin: http://foobar.com
+connection: keep-alive
+```
+:---
+
+## Configuration
+
+The true power of CORS protection, however, comes into play once you start configuring it. Here is a table of all of the options.
+
+| Key | Type | Default | Description |
+| --------------------------- | -------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `CORS_ALLOW_HEADERS` | `str` or `List[str]` | `"*"` | The list of headers that will appear in `access-control-allow-headers`. |
+| `CORS_ALWAYS_SEND` | `bool` | `True` | When `True`, will always set a value for `access-control-allow-origin`. When `False`, will only set it if there is an `Origin` header. |
+| `CORS_AUTOMATIC_OPTIONS` | `bool` | `True` | When the incoming preflight request is received, whether to automatically set values for `access-control-allow-headers`, `access-control-max-age`, and `access-control-allow-methods` headers. If `False` these values will only be set on routes that are decorated with the `@cors` decorator. |
+| `CORS_EXPOSE_HEADERS` | `str` or `List[str]` | `""` | Specific list of headers to be set in `access-control-expose-headers` header. |
+| `CORS_MAX_AGE` | `str`, `int`, `timedelta` | `0` | The maximum number of seconds the preflight response may be cached using the `access-control-max-age` header. A falsey value will cause the header to not be set. |
+| `CORS_METHODS` | `str` or `List[str]` | `""` | The HTTP methods that the allowed origins can access, as set on the `access-control-allow-methods` header. |
+| `CORS_ORIGINS` | `str`, `List[str]`, `re.Pattern` | `"*"` | The origins that are allowed to access the resource, as set on the `access-control-allow-origin` header. |
+| `CORS_SEND_WILDCARD` | `bool` | `False` | If `True`, will send the wildcard `*` origin instead of the `origin` request header. |
+| `CORS_SUPPORTS_CREDENTIALS` | `bool` | `False` | Whether to set the `access-control-allow-credentials` header. |
+| `CORS_VARY_HEADER` | `bool` | `True` | Whether to add `vary` header, when appropriate. |
+
+*For the sake of brevity, where the above says `List[str]` any instance of a `list`, `set`, `frozenset`, or `tuple` will be acceptable. Alternatively, if the value is a `str`, it can be a comma delimited list.*
+
+## Route level overrides
+
+---:1
+
+It may sometimes be necessary to override app-wide settings for a specific route. To allow for this, you can use the `@sanic_ext.cors()` decorator to set different route-specific values.
+
+The values that can be overridden with this decorator are:
+
+- `origins`
+- `expose_headers`
+- `allow_headers`
+- `allow_methods`
+- `supports_credentials`
+- `max_age`
+
+:--:1
+```python
+from sanic_ext import cors
+
+app.config.CORS_ORIGINS = "https://foo.com"
+
+
+@app.get("/", host="bar.com")
+@cors(origins="https://bar.com")
+async def hello_world(request):
+ return text("Hello, world.")
+```
+:---
From daf2901e2d444cb21a3d50d2c6250e075231d7da Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:32 +0300
Subject: [PATCH 184/776] New translations cors.md (Chinese Simplified)
---
src/zh/plugins/sanic-ext/http/cors.md | 47 ++++++++++++---------------
1 file changed, 20 insertions(+), 27 deletions(-)
diff --git a/src/zh/plugins/sanic-ext/http/cors.md b/src/zh/plugins/sanic-ext/http/cors.md
index b0662f92ee..3d5affdf19 100644
--- a/src/zh/plugins/sanic-ext/http/cors.md
+++ b/src/zh/plugins/sanic-ext/http/cors.md
@@ -1,24 +1,20 @@
# 跨域保护(CORS protection)
-跨域资源共享(aka CORS)本身就是一个 *巨大* 的话题,这里的文档再多也不为过,至于它究竟是什么,建议您自行进行一些研究,以了解其存在的安全问题以及背后的理论解决方案。
-[MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 是很好的入门文章。
+跨域资源共享(aka CORS)本身就是一个 *巨大* 的话题,这里的文档再多也不为过,至于它究竟是什么,建议您自行进行一些研究,以了解其存在的安全问题以及背后的理论解决方案。 The documentation here cannot go into enough detail about *what* it is. You are highly encouraged to do some research on your own to understand the security problem presented by it, and the theory behind the solutions. [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 是很好的入门文章。
-简而言之,CORS保护是一个框架,浏览器使用它来访问来自其他域的信息的时候能够有效地提升访问效率和缩短访问时间。它与任何构建单页应用程序的人都息息相关。 尤其是在您的前端页面位于类似 `https://portal.myapp.com`
-但它需要访问位于 `https://api.myapp.com` 的后端的时候。
+简而言之,CORS保护是一个框架,浏览器使用它来访问来自其他域的信息的时候能够有效地提升访问效率和缩短访问时间。 它与任何构建单页应用程序的人都息息相关。 尤其是在您的前端页面位于类似 `https://portal.myapp.com` 但它需要访问位于 `https://api.myapp.com` 的后端的时候。
-这一部分功能的实现深受 [sanic-cors](https://github.com/ashleysommer/sanic-cors)
-的启发,它基于 [flask-cors](https://github.com/corydolphin/flask-cors) 因此,您几乎可以直接使用 `sanic-ext` 替换 `sanic-cors`。
+这一部分功能的实现深受 [sanic-cors](https://github.com/ashleysommer/sanic-cors) 的启发,它基于 [flask-cors](https://github.com/corydolphin/flask-cors) 因此,您几乎可以直接使用 `sanic-ext` 替换 `sanic-cors`。 It is therefore very likely that you can achieve a near drop-in replacement of `sanic-cors` with `sanic-ext`.
## 基本实现(Basic implementation)
---:1
-就如 [自动创建响应程序示例](methods.md#options) 中所示例的那样,Sanic 拓展将会自动地启用跨域保护而不需要太多的操作,但是它也没有提供太多开箱即用的方法。
+就如 [自动创建响应程序示例](methods.md#options) 中所示例的那样,Sanic 拓展将会自动地启用跨域保护而不需要太多的操作,但是它也没有提供太多开箱即用的方法。 But, it does not offer too much out of the box.
强烈建议您设置 `config.CORS_ORIGINS` 至少将需要访问的应用程序的域名添加到其中。
:--:1
-
```python
from sanic import Sanic, text
from sanic_ext import Extend
@@ -33,40 +29,39 @@ async def hello_world(request):
return text("Hello, world.")
```
-```text
+```
$ curl localhost:8000 -X OPTIONS -i
HTTP/1.1 204 No Content
allow: GET,HEAD,OPTIONS
access-control-allow-origin: http://foobar.com
connection: keep-alive
```
-
:---
## 配置(Configuration)
-只有您合理地配置跨域保护,它才能发挥出真正的力量。下面是一张配置选项清单:
+The true power of CORS protection, however, comes into play once you start configuring it. Here is a table of all of the options.
-| 配置名称 | 数据类型 | 默认值 | 说明
-|:----------------------------|:---------------------------------|:-------|:-------------------------------------------------------------
-| `CORS_ALLOW_HEADERS` | `str`, `List[str]` | `"*"` | 被添加的值会在 `access-control-allow-headers` 中的请求头列表中出现
-| `CORS_ALWAYS_SEND` | `bool` | `True` | 当 `True` 时,将总是为 `access-control-allow-headers` 设置一个值。当 `False` 时,仅当有 `Origin` 请求头时才会设置值。
-| `CORS_AUTOMATIC_OPTIONS` | `bool` | `True` | 当收到传入的预检请求时,是否自动设置 `access-control-allow-headers`、`access-control-max-age` 和 `access-control-allow-methods` 请求头的值。如果 `False` 这些值将只应用在使用了 `@cors` 装饰器装饰的路由上。
-| `CORS_EXPOSE_HEADERS` | `str`, `List[str]` | `""` | 在`access-control-expose-headers` 请求头中设置的特定请求头列表。
-| `CORS_MAX_AGE` | `str`, `int`, `timedelta` | `0` | 使用 `access-control-max-age` 请求头可以缓存预检响应的最大秒数。 一个错误值将导致不设置请求头。
-| `CORS_METHODS` | `str`, `List[str]` | `""` | 允许的来源可以使用的 HTTP 访问方法,将设置在 `access-control-allow-methods` 请求头中。
-| `CORS_ORIGINS` | `str`, `List[str]`, `re.Pattern` | `"*"` | 允许访问资源的来源,将设置在 `access-control-allow-origin` 请求头中。
-| `CORS_SEND_WILDCARD` | `bool` | `False`| 如果为 `True`,将发送通配符 `*` 源而不是 `Origin` 请求头。
-| `CORS_SUPPORTS_CREDENTIALS` | `bool` | `False`| 是否设置 `access-control-allow-credentials` 请求头。
-| `CORS_VARY_HEADER` | `bool` | `True` | 是否在适当的时候添加 `vary` 请求头。
+| 配置名称 | 数据类型 | 默认值 | 说明 |
+| --------------------------- | -------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `CORS_ALLOW_HEADERS` | `str`, `List[str]` | `"*"` | 被添加的值会在 `access-control-allow-headers` 中的请求头列表中出现 |
+| `CORS_ALWAYS_SEND` | `bool` | `True` | 当 `True` 时,将总是为 `access-control-allow-headers` 设置一个值。 当 `False` 时,仅当有 `Origin` 请求头时才会设置值。 |
+| `CORS_AUTOMATIC_OPTIONS` | `bool` | `True` | 当收到传入的预检请求时,是否自动设置 `access-control-allow-headers`、`access-control-max-age` 和 `access-control-allow-methods` 请求头的值。 如果 `False` 这些值将只应用在使用了 `@cors` 装饰器装饰的路由上。 |
+| `CORS_EXPOSE_HEADERS` | `str`, `List[str]` | `""` | 在`access-control-expose-headers` 请求头中设置的特定请求头列表。 |
+| `CORS_MAX_AGE` | `str`, `int`, `timedelta` | `0` | 使用 `access-control-max-age` 请求头可以缓存预检响应的最大秒数。 一个错误值将导致不设置请求头。 |
+| `CORS_METHODS` | `str`, `List[str]` | `""` | 允许的来源可以使用的 HTTP 访问方法,将设置在 `access-control-allow-methods` 请求头中。 |
+| `CORS_ORIGINS` | `str`, `List[str]`, `re.Pattern` | `"*"` | 允许访问资源的来源,将设置在 `access-control-allow-origin` 请求头中。 |
+| `CORS_SEND_WILDCARD` | `bool` | `False` | 如果为 `True`,将发送通配符 `*` 源而不是 `Origin` 请求头。 |
+| `CORS_SUPPORTS_CREDENTIALS` | `bool` | `False` | 是否设置 `access-control-allow-credentials` 请求头。 |
+| `CORS_VARY_HEADER` | `bool` | `True` | 是否在适当的时候添加 `vary` 请求头。 |
-*为了提高易用性,上面提到的 `List[str]` 任何一个 `list`、`set`、`frozenset` 或 `tuple` 的实例都将可用。或者,如果值是一个 `str`,它可以是一个逗号分隔的列表。*
+*为了提高易用性,上面提到的 `List[str]` 任何一个 `list`、`set`、`frozenset` 或 `tuple` 的实例都将可用。 或者,如果值是一个 `str`,它可以是一个逗号分隔的列表。*
## 路由级别覆盖(Route level overrides)
---:1
-有些时候我们需要对特定的路由进行跨域保护设置,为此,您可以使用 `@sanic_ext.cors()` 装饰器来为不同的路由设置不同的跨域保护配置。
+It may sometimes be necessary to override app-wide settings for a specific route. 有些时候我们需要对特定的路由进行跨域保护设置,为此,您可以使用 `@sanic_ext.cors()` 装饰器来为不同的路由设置不同的跨域保护配置。
可以被此装饰器设置的值包括:
@@ -78,7 +73,6 @@ connection: keep-alive
- `max_age`
:--:1
-
```python
from sanic_ext import cors
@@ -90,5 +84,4 @@ app.config.CORS_ORIGINS = "https://foo.com"
async def hello_world(request):
return text("Hello, world.")
```
-
:---
From 96d9e913b1b89a916ef8094400962746d6052a74 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:33 +0300
Subject: [PATCH 185/776] New translations cors.md (Portuguese, Brazilian)
---
src/pt/plugins/sanic-ext/http/cors.md | 86 +++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100644 src/pt/plugins/sanic-ext/http/cors.md
diff --git a/src/pt/plugins/sanic-ext/http/cors.md b/src/pt/plugins/sanic-ext/http/cors.md
new file mode 100644
index 0000000000..1149c04d0e
--- /dev/null
+++ b/src/pt/plugins/sanic-ext/http/cors.md
@@ -0,0 +1,86 @@
+# CORS protection
+
+Cross-Origin Resource Sharing (aka CORS) is a *huge* topic by itself. The documentation here cannot go into enough detail about *what* it is. You are highly encouraged to do some research on your own to understand the security problem presented by it, and the theory behind the solutions. [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) are a great first step.
+
+In super brief terms, CORS protection is a framework that browsers use to facilitate how and when a web page can access information from another domain. It is extremely relevant to anyone building a single-page application. Often times your frontend might be on a domain like `https://portal.myapp.com`, but it needs to access the backend from `https://api.myapp.com`.
+
+The implementation here is heavily inspired by [`sanic-cors`](https://github.com/ashleysommer/sanic-cors), which is in turn based upon [`flask-cors`](https://github.com/corydolphin/flask-cors). It is therefore very likely that you can achieve a near drop-in replacement of `sanic-cors` with `sanic-ext`.
+
+## Basic implementation
+
+---:1
+
+As shown in the example in the [auto-endpoints example](methods.md#options), Sanic Extensions will automatically enable CORS protection without further action. But, it does not offer too much out of the box.
+
+At a *bare minimum*, it is **highly** recommended that you set `config.CORS_ORIGINS` to the intended origin(s) that will be accessing the application.
+
+:--:1
+```python
+from sanic import Sanic, text
+from sanic_ext import Extend
+
+app = Sanic(__name__)
+app.config.CORS_ORIGINS = "http://foobar.com,http://bar.com"
+Extend(app)
+
+@app.get("/")
+async def hello_world(request):
+ return text("Hello, world.")
+```
+
+```
+$ curl localhost:8000 -X OPTIONS -i
+HTTP/1.1 204 No Content
+allow: GET,HEAD,OPTIONS
+access-control-allow-origin: http://foobar.com
+connection: keep-alive
+```
+:---
+
+## Configuration
+
+The true power of CORS protection, however, comes into play once you start configuring it. Here is a table of all of the options.
+
+| Key | Type | Default | Description |
+| --------------------------- | -------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `CORS_ALLOW_HEADERS` | `str` or `List[str]` | `"*"` | The list of headers that will appear in `access-control-allow-headers`. |
+| `CORS_ALWAYS_SEND` | `bool` | `True` | When `True`, will always set a value for `access-control-allow-origin`. When `False`, will only set it if there is an `Origin` header. |
+| `CORS_AUTOMATIC_OPTIONS` | `bool` | `True` | When the incoming preflight request is received, whether to automatically set values for `access-control-allow-headers`, `access-control-max-age`, and `access-control-allow-methods` headers. If `False` these values will only be set on routes that are decorated with the `@cors` decorator. |
+| `CORS_EXPOSE_HEADERS` | `str` or `List[str]` | `""` | Specific list of headers to be set in `access-control-expose-headers` header. |
+| `CORS_MAX_AGE` | `str`, `int`, `timedelta` | `0` | The maximum number of seconds the preflight response may be cached using the `access-control-max-age` header. A falsey value will cause the header to not be set. |
+| `CORS_METHODS` | `str` or `List[str]` | `""` | The HTTP methods that the allowed origins can access, as set on the `access-control-allow-methods` header. |
+| `CORS_ORIGINS` | `str`, `List[str]`, `re.Pattern` | `"*"` | The origins that are allowed to access the resource, as set on the `access-control-allow-origin` header. |
+| `CORS_SEND_WILDCARD` | `bool` | `False` | If `True`, will send the wildcard `*` origin instead of the `origin` request header. |
+| `CORS_SUPPORTS_CREDENTIALS` | `bool` | `False` | Whether to set the `access-control-allow-credentials` header. |
+| `CORS_VARY_HEADER` | `bool` | `True` | Whether to add `vary` header, when appropriate. |
+
+*For the sake of brevity, where the above says `List[str]` any instance of a `list`, `set`, `frozenset`, or `tuple` will be acceptable. Alternatively, if the value is a `str`, it can be a comma delimited list.*
+
+## Route level overrides
+
+---:1
+
+It may sometimes be necessary to override app-wide settings for a specific route. To allow for this, you can use the `@sanic_ext.cors()` decorator to set different route-specific values.
+
+The values that can be overridden with this decorator are:
+
+- `origins`
+- `expose_headers`
+- `allow_headers`
+- `allow_methods`
+- `supports_credentials`
+- `max_age`
+
+:--:1
+```python
+from sanic_ext import cors
+
+app.config.CORS_ORIGINS = "https://foo.com"
+
+
+@app.get("/", host="bar.com")
+@cors(origins="https://bar.com")
+async def hello_world(request):
+ return text("Hello, world.")
+```
+:---
From 3e2c8462a066e3b62e74c47c7a7ee0bf62604558 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:34 +0300
Subject: [PATCH 186/776] New translations methods.md (Japanese)
---
src/ja/plugins/sanic-ext/http/methods.md | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/src/ja/plugins/sanic-ext/http/methods.md b/src/ja/plugins/sanic-ext/http/methods.md
index f9d246c5e8..7b84331f67 100644
--- a/src/ja/plugins/sanic-ext/http/methods.md
+++ b/src/ja/plugins/sanic-ext/http/methods.md
@@ -2,8 +2,7 @@
## 自動エンドポイント
-デフォルトの動作は、すべての`GET`ルートに`HEAD`エンドポイントを、そして全ルートに`OPTIONS`エンドポイントを自動的に生成することです。
-さらに、`TRACE`エンドポイントを自動的に生成するオプションもあります。しかし、これらは初期状態では有効ではありません。
+デフォルトの動作は、すべての`GET`ルートに`HEAD`エンドポイントを、そして全ルートに`OPTIONS`エンドポイントを自動的に生成することです。 さらに、`TRACE`エンドポイントを自動的に生成するオプションもあります。 Additionally, there is the option to automatically generate `TRACE` endpoints. しかし、これらは初期状態では有効ではありません。
::::tabs
@@ -12,8 +11,7 @@
- **Configuration**: `AUTO_HEAD` (default `True`)
- **MDN**: [Read more](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD)
-`HEAD` リクエストはヘッダーを提供し、それ以外は `GET` リクエストが提供するものと同じレスポンスを提供します。
-しかし、実際にはボディを返しません。
+`HEAD` リクエストはヘッダーを提供し、それ以外は `GET` リクエストが提供するものと同じレスポンスを提供します。 しかし、実際にはボディを返しません。 However, it does not actually return the body.
```python
@app.get("/")
@@ -49,8 +47,7 @@ async def hello_world(request):
上記のルート定義があれば、Sanic Extensionsはここで見られるように`HEAD`レスポンスを有効にします。
-この例では、`access-control-allow-origins`も表示されていることに注意することが重要です。
-これは、[CORS保護](cors.md)がデフォルトで有効になっているためです。
+この例では、`access-control-allow-origins`も表示されていることに注意することが重要です。 これは、[CORS保護](cors.md)がデフォルトで有効になっているためです。 This is because the [CORS protection](cors.md) is enabled by default.
```
$ curl localhost:8000 -X OPTIONS -i
@@ -60,7 +57,7 @@ access-control-allow-origin: *
connection: keep-alive
```
-::: tip Sanic Extensionsがこれらのルートを自動的にセットアップしてくれるとしても、手動で `@app.options` ルートを作成することにした場合、それは オーバーライド**されません**。
+::: tip Sanic Extensionsがこれらのルートを自動的にセットアップしてくれるとしても、手動で `@app.options` ルートを作成することにした場合、それは オーバーライド**されません**。 :::
:::
:::tab TRACE
@@ -68,7 +65,7 @@ connection: keep-alive
- **Configuration**: `AUTO_TRACE` (default `False`)
- **MDN**: [Read more](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE)
-デフォルトでは、`TRACE`エンドポイントは自動的に作成**されません**。しかし、Sanic Extensions では、必要であれば作成することができます。これはバニラSanicでは許可されていないことである。
+デフォルトでは、`TRACE`エンドポイントは自動的に作成**されません**。 しかし、Sanic Extensions では、必要であれば作成することができます。 これはバニラSanicでは許可されていないことである。
```python
@app.route("/", methods=["trace"])
@@ -94,8 +91,7 @@ User-Agent: curl/7.76.1
Accept: */*
```
-::: tip `AUTO_TRACE` を設定すると、特にアプリケーションがプロキシの後ろに配置されている場合、非常に便利です。
-は、プロキシがどのように動作しているかを判断するのに役立ちます。
+::: tip `AUTO_TRACE` を設定すると、特にアプリケーションがプロキシの後ろに配置されている場合、非常に便利です。 は、プロキシがどのように動作しているかを判断するのに役立ちます。 :::
:::
::::
@@ -116,11 +112,9 @@ Accept: */*
---:1
-しかし、さらに2つの「標準的な」HTTPメソッドがあります: `TRACE` と `CONNECT` です。
-Sanic Extensions は、これらのメソッドを使用したエンドポイントの構築を可能にするもので、他の方法では許可されません。
+しかし、さらに2つの「標準的な」HTTPメソッドがあります: `TRACE` と `CONNECT` です。 Sanic Extensions は、これらのメソッドを使用したエンドポイントの構築を可能にするもので、他の方法では許可されません。 Sanic Extensions will allow you to build endpoints using these methods, which would otherwise not be allowed.
-これは便利なメソッドである `@app.trace` や `@app.connect` を有効にするものではないことに注意してください。
-この例で示されているように、`@app.route`を使用する必要があります。
+これは便利なメソッドである `@app.trace` や `@app.connect` を有効にするものではないことに注意してください。 この例で示されているように、`@app.route`を使用する必要があります。 You need to use `@app.route` as shown in the example here.
:--:1
From 6a01e20e63b4bc211ae8cf19b7dd8cbf75648088 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:35 +0300
Subject: [PATCH 187/776] New translations getting-started.md (Portuguese,
Brazilian)
---
src/pt/guide/getting-started.md | 86 +++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100644 src/pt/guide/getting-started.md
diff --git a/src/pt/guide/getting-started.md b/src/pt/guide/getting-started.md
new file mode 100644
index 0000000000..3f85c259ad
--- /dev/null
+++ b/src/pt/guide/getting-started.md
@@ -0,0 +1,86 @@
+# Getting Started
+
+Before we begin, make sure you are running Python 3.7 or higher. Currently, is known to work with Python versions 3.7, 3.8 and 3.9.
+
+## Install
+
+```bash
+pip install sanic
+```
+
+## Hello, world application
+
+---:1
+
+If you have ever used one of the many decorator based frameworks, this probably looks somewhat familiar to you.
+
+::: tip
+If you are coming from Flask or another framework, there are a few important things to point out. Remember, Sanic aims for performance, flexibility, and ease of use. These guiding principles have tangible impact on the API and how it works.
+:::
+
+
+
+:--:1
+
+```python
+from sanic import Sanic
+from sanic.response import text
+
+app = Sanic("MyHelloWorldApp")
+
+@app.get("/")
+async def hello_world(request):
+ return text("Hello, world.")
+```
+
+:---
+
+### Important to note
+
+- Every request handler can either be sync (`def hello_world`) or async (`async def hello_world`). Unless you have a clear reason for it, always go with `async`.
+- The `request` object is always the first argument of your handler. Other frameworks pass this around in a context variable to be imported. In the `async` world, this would not work so well and it is far easier (not to mention cleaner and more performant) to be explicit about it.
+- You **must** use a response type. MANY other frameworks allow you to have a return value like this: `return "Hello, world."` or this: `return {"foo": "bar"}`. But, in order to do this implicit calling, somewhere in the chain needs to spend valuable time trying to determine what you meant. So, at the expense of this ease, Sanic has decided to require an explicit call.
+
+### Running
+
+---:1 Let's save the above file as `server.py`. And launch it. :--:1
+```bash
+sanic server.app
+```
+:---
+
+::: tip This **another** important distinction. Other frameworks come with a built in development server and explicitly say that it is _only_ intended for development use. The opposite is true with Sanic.
+
+**The packaged server is production ready.** :::
+
+## Sanic Extensions
+
+Sanic intentionally aims for a clean and unopinionated feature list. The project does not want to require you to build your application in a certain way, and tries to avoid prescribing specific development patterns. There are a number of third-party plugins that are built and maintained by the community to add additional features that do not otherwise meet the requirements of the core repository.
+
+However, in order **to help API developers**, the Sanic organization maintains an official plugin called [Sanic Extensions](../plugins/sanic-ext/getting-started.md) to provide all sorts of goodies, including:
+
+- **OpenAPI** documentation with Redoc and/or Swagger
+- **CORS** protection
+- **Dependency injection** into route handlers
+- Request query arguments and body input **validation**
+- Auto create `HEAD`, `OPTIONS`, and `TRACE` endpoints
+- Predefined, endpoint-specific response serializers
+
+The preferred method to set it up is to install it along with Sanic, but you can also install the packages on their own.
+
+---:1
+```
+$ pip install sanic[ext]
+```
+:--:1
+```
+$ pip install sanic sanic-ext
+```
+:---
+
+Starting in v21.12, Sanic will automatically setup Sanic Extensions if it is in the same environment. You will also have access to two additional application properties:
+
+- `app.extend()` - used to configure Sanic Extensions
+- `app.ext` - the `Extend` instance attached to the application
+
+See [the plugin documenataion](../plugins/sanic-ext/getting-started.md) for more information about how to use and work with the plugin
From dce4230ae9b87ea5dd78e98c6e21dce623e95d94 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:36 +0300
Subject: [PATCH 188/776] New translations getting-started.md (Korean)
---
src/ko/guide/getting-started.md | 44 +++++++++++++++++++++++++++------
1 file changed, 36 insertions(+), 8 deletions(-)
diff --git a/src/ko/guide/getting-started.md b/src/ko/guide/getting-started.md
index 3c67beaa0c..dc7400455c 100644
--- a/src/ko/guide/getting-started.md
+++ b/src/ko/guide/getting-started.md
@@ -18,6 +18,8 @@ pip install sanic
Flask 또는 다른 프레임워크를 사용하다 온 경우 몇 가지 짚고 넘어가야 할 중요한 것들이 있습니다. 기억하세요, Sanic은 성능, 유연성 및 사용 편의성을 목표로 합니다. 이러한 지침 원칙은 API 및 작동 방식에 실질적인 영향을 미칩니다.
:::
+
+
:--:1
```python
@@ -41,18 +43,44 @@ async def hello_world(request):
### 실행(Running)
----:1
-위에서 작성한 파일을 `server.py`로 저장하고 실행해 보겠습니다.
-:--:1
-
+---:1 위에서 작성한 파일을 `server.py`로 저장하고 실행해 보겠습니다. And launch it. :--:1
```bash
sanic server.app
```
+:---
+
+::: tip **또 다른** 중요한 차이점입니다. 다른 프레임워크는 개발 서버가 내장되어 있으며 개발 전용이라고 _명시적_ 으로 말합니다. Sanic은 그 반대입니다.
+
+**프로덕션 환경에서 사용할 수 있는 서버가 준비되있습니다.** :::
+
+## Sanic Extensions
+
+Sanic intentionally aims for a clean and unopinionated feature list. The project does not want to require you to build your application in a certain way, and tries to avoid prescribing specific development patterns. There are a number of third-party plugins that are built and maintained by the community to add additional features that do not otherwise meet the requirements of the core repository.
+
+However, in order **to help API developers**, the Sanic organization maintains an official plugin called [Sanic Extensions](../plugins/sanic-ext/getting-started.md) to provide all sorts of goodies, including:
+- **OpenAPI** documentation with Redoc and/or Swagger
+- **CORS** protection
+- **Dependency injection** into route handlers
+- Request query arguments and body input **validation**
+- Auto create `HEAD`, `OPTIONS`, and `TRACE` endpoints
+- Predefined, endpoint-specific response serializers
+
+The preferred method to set it up is to install it along with Sanic, but you can also install the packages on their own.
+
+---:1
+```
+$ pip install sanic[ext]
+```
+:--:1
+```
+$ pip install sanic sanic-ext
+```
:---
-::: tip
-**또 다른** 중요한 차이점입니다. 다른 프레임워크는 개발 서버가 내장되어 있으며 개발 전용이라고 _명시적_ 으로 말합니다. Sanic은 그 반대입니다.
+Starting in v21.12, Sanic will automatically setup Sanic Extensions if it is in the same environment. You will also have access to two additional application properties:
-**프로덕션 환경에서 사용할 수 있는 서버가 준비되있습니다.**
-:::
+- `app.extend()` - used to configure Sanic Extensions
+- `app.ext` - the `Extend` instance attached to the application
+
+See [the plugin documenataion](../plugins/sanic-ext/getting-started.md) for more information about how to use and work with the plugin
From cf1b7cd2e6b550b19dbba565b9cf8b6652cb43fa Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:37 +0300
Subject: [PATCH 189/776] New translations v21.3.md (Korean)
---
src/ko/guide/release-notes/v21.3.md | 262 ++++++++++++++++++++++++++++
1 file changed, 262 insertions(+)
create mode 100644 src/ko/guide/release-notes/v21.3.md
diff --git a/src/ko/guide/release-notes/v21.3.md b/src/ko/guide/release-notes/v21.3.md
new file mode 100644
index 0000000000..bca0729af6
--- /dev/null
+++ b/src/ko/guide/release-notes/v21.3.md
@@ -0,0 +1,262 @@
+# Version 21.3
+
+[[toc]]
+
+## Introduction
+
+Sanic is now faster.
+
+Well, it already was fast. But with the first iteration of the v21 release, we incorporated a few major milestones that have made some tangible improvements. These encompass some ideas that have been in the works for years, and have finally made it into the released version.
+
+::: warning Breaking changes Version 21.3 introduces a lot of new features. But, it also includes some breaking changes. This is why these changes were introduced after the last LTS. If you rely upon something that has been removed, you should continue to use v20.12LTS until you are able to upgrade.
+
+```bash
+pip install "sanic>=20.12,<20.13"
+pip freeze > requirements.txt
+```
+
+For most typical installations, you should be able to upgrade without a problem. :::
+
+## What to know
+
+Notable new or breaking features, and what to upgrade...
+
+### Python 3.7+ Only
+
+This version drops Python 3.6 support. Version 20.12LTS will continue to support Python 3.6 until its EOL in December, 2022, and version 19.12LTS will support it until its EOL in December, 2021.
+
+Read more about our [LTS policy](../project/policies.md#long-term-support-v-interim-releases).
+
+### Streaming as first class citizen
+
+The biggest speed improvement came from unifying the request/response cycle into a single flow. Previously, there was a difference between regular cycles, and streaming cycles. This has been simplified under the hood, even though the API is staying the same right now for compatibility. The net benefit is that **all** requests now should see a new benefit.
+
+Read more about [streaming changes](../advanced/streaming.md#response-streaming).
+
+### Router overhaul
+
+The old Sanic router was based upon regular expressions. In addition it suffered from a number of quirks that made it hard to modify at run time, and resulted in some performance issues. This change has been years in the making and now [converts the router to a compiled tree at startup](https://community.sanicframework.org/t/a-fast-new-router/649/41). Look for additional improvements throughout the year.
+
+The outward facing API has kept backwards compatibility. However, if you were accessing anything inside the router specifically, you many notice some changes. For example:
+
+1. `Router.get()` has a new return value
+2. `Route` is now a proper class object and not a `namedtuple`
+3. If building the router manually, you will need to call `Router.finalize()` before it is usable
+4. There is a new `` pattern that can be matched in your routes
+5. You cannot startup an application without at least one route defined
+
+The router is now located in its own repository: [sanic-org/sanic-router](https://github.com/sanic-org/sanic-router) and is also its own [standalone package on PyPI](https://pypi.org/project/sanic-routing/).
+
+### Signals API ⭐️
+
+_BETA Feature: API to be finalized in v21.6_
+
+A side benefit of the new router is that it can do double duty also powering the [new signals API](https://github.com/sanic-org/sanic/issues/1630). This feature is being released for public usage now, and likely the public API will not change in its final form.
+
+The core ideas of this feature are:
+
+1. to allow the developer greater control and access to plugging into the server and request lifecycles,
+2. to provide new tools to synchronize and send messages through your application, and
+3. to ultimately further increase performance.
+
+The API introduces three new methods:
+
+- `@app.signal(...)` - For defining a signal handler. It looks and operates very much like a route. Whenever that signal is dispatched, this handler will be executed.
+- `app.event(...)` - An awaitable that can be used anywhere in your application to pause execution until the event is triggered.
+- `app.dispatch(...)` - Trigger an event and cause the signal handlers to execute.
+
+```python
+@app.signal("foo.bar.")
+async def signal_handler(thing, **kwargs):
+ print(f"[signal_handler] {thing=}", kwargs)
+
+async def wait_for_event(app):
+ while True:
+ print("> waiting")
+ await app.event("foo.bar.*")
+ print("> event found\n")
+
+@app.after_server_start
+async def after_server_start(app, loop):
+ app.add_task(wait_for_event(app))
+
+@app.get("/")
+async def trigger(request):
+ await app.dispatch("foo.bar.baz")
+ return response.text("Done.")
+```
+
+### Route naming
+
+Routes used to be referenced by both `route.name` and `route.endpoint`. While similar, they were slightly different. Now, all routes will be **consistently** namespaced and referenced.
+
+```
+.[optional:.]
+```
+
+This new "name" is assigned to the property `route.name`. We are deprecating `route.endpoint`, and will remove that property in v21.9. Until then, it will be an alias for `route.name`.
+
+In addition, naming prefixes that had been in use for things like static, websocket, and blueprint routes have been removed.
+
+### New decorators
+
+Several new convenience decorators to help IDEs with autocomplete.
+
+```python
+# Alias to @app.listener("...")
+@app.before_server_start
+@app.after_server_stop
+@app.before_server_start
+@app.after_server_stop
+
+# Alias to @app.middleware("...")
+@app.on_request
+@app.on_response
+```
+
+### Unquote in route
+
+If you have a route that uses non-ascii characters, Sanic will no longer `unquote` the text for you. You will need to specifically tell the route definition that it should do so.
+
+```python
+@app.route("/overload/", methods=["GET"], unquote=True)
+async def handler2(request, param):
+ return text("OK2 " + param)
+
+request, response = app.test_client.get("/overload/您好")
+assert response.text == "OK2 您好"
+```
+
+If you forget to do so, your text will remain encoded.
+
+### Alter `Request.match_info`
+
+The `match_info` has always provided the data for the matched path parameters. You now have access to modify that, for example in middleware.
+
+```python
+@app.on_request
+def convert_to_snake_case(request):
+ request.match_info = to_snake(request.match_info)
+```
+
+### Version types in routes
+
+The `version` argument in routes can now be:
+
+- `str`
+- `int`
+- `float`
+
+```python
+@app.route("/foo", version="2.1.1")
+@app.route("/foo", version=2)
+@app.route("/foo", version=2.1)
+```
+### Safe method handling with body
+
+Route handlers for `GET`, `HEAD`, `OPTIONS` and `DELETE` will not decode any HTTP body passed to it. You can override this:
+
+```python
+@app.delete(..., ignore_body=False)
+```
+
+### Application, Blueprint and Blueprint Group parity
+
+The `Sanic` and `Blueprint` classes share a common base. Previously they duplicated a lot of functionality, that lead to slightly different implementations between them. Now that they both inherit the same base class, developers and plugins should have a more consistent API to work with.
+
+Also, Blueprint Groups now also support common URL extensions like the `version` and `strict_slashes` keyword arguments.
+
+### Dropped `httpx` from dependencies
+
+There is no longer a dependency on `httpx`.
+
+### Removed `testing` library
+
+Sanic internal testing client has been removed. It is now located in its own repository: [sanic-org/sanic-testing](https://github.com/sanic-org/sanic-testing) and is also its own [standalone package on PyPI](https://pypi.org/project/sanic-testing/).
+
+If you have `sanic-testing` installed, it will be available and usable on your `Sanic()` application instances as before. So, the **only** change you will need to make is to add `sanic-testing` to your test suite requirements.
+
+### Application and connection level context (`ctx`) objects
+
+Version 19.9 [added ](https://github.com/sanic-org/sanic/pull/1666/files) the `request.ctx` API. This helpful construct easily allows for attaching properties and data to a request object (for example, in middleware), and reusing the information elsewhere int he application.
+
+Similarly, this concept is being extended in two places:
+
+1. the application instance, and
+2. a transport connection.
+
+#### Application context
+
+A common use case is to attach properties to the app instance. For the sake of consistency, and to avoid the issue of name collision with Sanic properties, the `ctx` object now exists on `Sanic` instances.
+
+```python
+@app.before_server_startup
+async def startup_db(app, _):
+ # WRONG
+ app.db = await connect_to_db()
+
+ # CORRECT
+ app.ctx.db = await connect_to_db()
+```
+
+#### Connection context
+
+When a client sends a keep alive header, Sanic will attempt to keep the transport socket [open for a period of time](../deployment/configuration.md#keep-alive-timeout). That transport object now has a `ctx` object available on it. This effectively means that multiple requests from a single client (where the transport layer is being reused) may share state.
+
+```python
+@app.on_request
+async def increment_foo(request):
+ if not hasattr(request.conn_info.ctx, "foo"):
+ request.conn_info.ctx.foo = 0
+ request.conn_info.ctx.foo += 1
+
+@app.get("/")
+async def count_foo(request):
+ return text(f"request.conn_info.ctx.foo={request.conn_info.ctx.foo}")
+```
+
+```bash
+$ curl localhost:8000 localhost:8000 localhost:8000
+request.conn_info.ctx.foo=1
+request.conn_info.ctx.foo=2
+request.conn_info.ctx.foo=3
+```
+
+::: warning
+Connection level context is an experimental feature, and should be finalized in v21.6.
+:::
+
+## News
+
+
+### A NEW frontpage 🎉
+
+We have split the documentation into two. The docstrings inside the codebase will still continue to build sphinx docs to ReadTheDocs. However, it will be limited to API documentation. The new frontpage will house the "Sanic User Guide".
+
+The new site runs on Vuepress. Contributions are welcome. We also invite help in translating the documents.
+
+As a part of this, we also freshened up the RTD documentation and changed it to API docs only.
+
+### Chat has moved to Discord
+
+The Gitter chatroom has taken one step closer to being phased out. In its place we opened a [Discord server](https://discord.gg/FARQzAEMAA).
+
+### Open Collective
+
+The Sanic Community Organization has [opened a page on Open Collective](https://opencollective.com/sanic-org) to enable anyone that would like to financially support the development of Sanic.
+
+### 2021 Release Managers
+
+Thank you to @sjsadowski and @yunstanford for acting as release managers for both 2019 and 2020. This year's release managers are @ahopkins and @vltr.
+
+## Thank you
+
+Thank you to everyone that participated in this release: :clap:
+
+[@ahopkins](https://github.com/ahopkins) [@akshgpt7](https://github.com/akshgpt7) [@artcg](https://github.com/artcg) [@ashleysommer](https://github.com/ashleysommer) [@elis-k](https://github.com/elis-k) [@harshanarayana](https://github.com/harshanarayana) [@sjsadowski](https://github.com/sjsadowski) [@tronic](https://github.com/tronic) [@vltr](https://github.com/vltr),
+
+To [@ConnorZhang](https://github.com/miss85246) and [@ZinkLu](https://github.com/ZinkLu) for translating our documents into Chinese,
+
+---
+
+Make sure to checkout the changelog to get links to all the PRs, etc.
From b6f85c1f1ce52996cd19d5f3db4e3585829c572c Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:38 +0300
Subject: [PATCH 190/776] New translations v22.3.md (Japanese)
---
src/ja/guide/release-notes/v22.3.md | 321 ++++++++++++++++++++++++++++
1 file changed, 321 insertions(+)
create mode 100644 src/ja/guide/release-notes/v22.3.md
diff --git a/src/ja/guide/release-notes/v22.3.md b/src/ja/guide/release-notes/v22.3.md
new file mode 100644
index 0000000000..9222b48985
--- /dev/null
+++ b/src/ja/guide/release-notes/v22.3.md
@@ -0,0 +1,321 @@
+# Version 22.3
+
+[[toc]]
+
+## Introduction
+
+This is the first release of the version 22 [release cycle](../../org/policies.md#release-schedule). All of the standard SCO libraries are now entering the same release cycle and will follow the same versioning pattern. Those packages are:
+
+- [`sanic-routing`](https://github.com/sanic-org/sanic-routing)
+- [`sanic-testing`](https://github.com/sanic-org/sanic-testing)
+- [`sanic-ext`](https://github.com/sanic-org/sanic-ext)
+
+## What to know
+
+More details in the [Changelog](https://sanic.readthedocs.io/en/stable/sanic/changelog.html). Notable new or breaking features, and what to upgrade...
+
+### Application multi-serve
+
+The Sanic server now has an API to allow you to run multiple applications side-by-side in the same process. This is done by calling `app.prepare(...)` on one or more application instances, one or many times. Each time it should be bound to a unique host/port combination. Then, you begin serving the applications by calling `Sanic.serve()`.
+
+```python
+app = Sanic("One")
+app2 = Sanic("Two")
+
+app.prepare(port=9999)
+app.prepare(port=9998)
+app.prepare(port=9997)
+app2.prepare(port=8888)
+app2.prepare(port=8887)
+
+Sanic.serve()
+```
+
+In the above snippet, there are two applications that will be run concurrently and bound to multiple ports. This feature is *not* supported in the CLI.
+
+This pattern is meant to be an alternative to running `app.run(...)`. It should be noted that `app.run` is now just a shorthand for the above pattern and is still fully supported.
+
+### 👶 *BETA FEATURE* - New path parameter type: file extensions
+
+A very common pattern is to create a route that dynamically generates a file. The endpoint is meant to match on a file with an extension. There is a new path parameter to match files: ``.
+
+```python
+@app.get("/path/to/")
+async def handler(request, filename, ext):
+ ...
+```
+
+This will catch any pattern that ends with a file extension. You may, however want to expand this by specifying which extensions, and also by using other path parameter types for the file name.
+
+For example, if you want to catch a `.jpg` file that is only numbers:
+
+```python
+@app.get("/path/to/")
+async def handler(request, filename, ext):
+ ...
+```
+
+Some potential examples:
+
+
+
+
+ definition
+
+
+
+ example
+
+
+
+ filename
+
+
+
+ extension
+
+
+
+
+
+ \
+
+
+
+ page.txt
+
+
+
+ "page"
+
+
+
+ "txt"
+
+
+
+
+
+ \
+
+
+
+ cat.jpg
+
+
+
+ "cat"
+
+
+
+ "jpg"
+
+
+
+
+
+ \
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | cat.jpg | "cat" | "jpg"
+
+
+
+
+
+
+
+
+
+ 123.txt
+
+
+
+ 123
+
+
+
+ "txt"
+
+
+
+
+
+
+
+
+ png\
+
+
+
+ gif\
+
+
+
+ svg> | 123.svg | 123 | "svg"
+
+
+
+
+
+
+
+
+
+ 3.14.tar.gz
+
+
+
+ 3.14
+
+
+
+ "tar.gz"
+
+
+
+
+### 🚨 *BREAKING CHANGE* - Path parameter matching of non-empty strings
+
+A dynamic path parameter will only match on a non-empty string.
+
+Previously a route with a dynamic string parameter (`/` or `/`) would match on any string, including empty strings. It will now only match a non-empty string. To retain the old behavior, you should use the new parameter type: `/`.
+
+```python
+@app.get("/path/to/")
+async def handler(request, foo)
+ ...
+```
+
+### 🚨 *BREAKING CHANGE* - `sanic.worker.GunicornWorker` has been removed
+
+Departing from our normal deprecation policy, the `GunicornWorker` was removed as a part of the process of upgrading the Sanic server to include multi-serve. This decision was made largely in part because even while it existed it was not an optimal strategy for deploying Sanic.
+
+If you want to deploy Sanic using `gunicorn`, then you are advised to do it using [the strategy implemented by `uvicorn`](https://www.uvicorn.org/#running-with-gunicorn). This will effectively run Sanic as an ASGI application through `uvicorn`. You can upgrade to this pattern by installing `uvicorn`:
+
+```
+pip install uvicorn
+```
+
+Then, you should be able to run it with a pattern like this:
+
+```
+gunicorn path.to.sanic:app -k uvicorn.workers.UvicornWorker
+```
+
+### Authorization header parsing
+
+The `Authorization` header has been partially parseable for some time now. You have been able to use `request.token` to gain access to a header that was in one of the following two forms:
+
+```
+Authorization: Token
+Authorization: Bearer
+```
+
+Sanic can now parse more credential types like `BASIC`:
+
+```
+Authorization: Basic Z2lsLWJhdGVzOnBhc3N3b3JkMTIz
+```
+
+This can be accessed now as `request.credentials`:
+
+```python
+print(request.credentials)
+# Credentials(auth_type='Basic', token='Z2lsLWJhdGVzOnBhc3N3b3JkMTIz', _username='gil-bates', _password='password123')
+```
+
+### CLI arguments optionally injected into application factory
+
+Sanic will now attempt to inject the parsed CLI arguments into your factory if you are using one.
+
+```python
+def create_app(args):
+ app = Sanic("MyApp")
+ print(args)
+ return app
+```
+```
+$sanic p:create_app --factory
+Namespace(module='p:create_app', factory=True, simple=False, host='127.0.0.1', port=8000, unix='', cert=None, key=None, tls=None, tlshost=False, workers=1, fast=False, access_log=False, debug=False, auto_reload=False, path=None, dev=False, motd=True, verbosity=None, noisy_exceptions=False)
+```
+
+If you are running the CLI with `--factory`, you also have the option of passing arbitrary arguments to the command, which will be injected into the argument `Namespace`.
+
+```
+sanic p:create_app --factory --foo=bar
+Namespace(module='p:create_app', factory=True, simple=False, host='127.0.0.1', port=8000, unix='', cert=None, key=None, tls=None, tlshost=False, workers=1, fast=False, access_log=False, debug=False, auto_reload=False, path=None, dev=False, motd=True, verbosity=None, noisy_exceptions=False, foo='bar')
+```
+
+### New reloader process listener events
+
+When running Sanic server with auto-reload, there are two new events that trigger a listener *only* on the reloader process:
+
+- `reload_process_start`
+- `reload_process_stop`
+
+These are only triggered if the reloader is running.
+
+```python
+@app.reload_process_start
+async def reload_start(*_):
+ print(">>>>>> reload_start <<<<<<")
+
+
+@app.reload_process_stop
+async def reload_stop(*_):
+ print(">>>>>> reload_stop <<<<<<")
+```
+
+### The event loop is no longer a required argument of a listener
+
+You can leave out the `loop` argument of a listener. Both of these examples work as expected:
+
+```python
+@app.before_server_start
+async def without(app):
+ ...
+
+@app.before_server_start
+async def with(app, loop):
+ ...
+```
+
+### Removal - Debug mode does not automatically start the reloader
+
+When running with `--debug` or `debug=True`, the Sanic server will not automatically start the auto-reloader. This feature of doing both on debug was deprecated in v21 and removed in this release. If you would like to have *both* debug mode and auto-reload, you can use `--dev` or `dev=True`.
+
+**dev = debug mode + auto reloader**
+
+### Deprecation - Loading of lower case environment variables
+
+Sanic loads prefixed environment variables as configuration values. It has not distinguished between uppercase and lowercase as long as the prefix matches. However, it has always been the convention that the keys should be uppercase. This is deprecated and you will receive a warning if the value is not uppercase. In v22.9 only uppercase and prefixed keys will be loaded.
+
+## News
+
+### Packt publishes new book on Sanic web development
+
+---:1 There is a new book on **Python Web Development with Sanic** by [@ahopkins](https://github.com/ahopkins). The book is endorsed by the SCO and part of the proceeds of all sales go directly to the SCO for further development of Sanic.
+
+You can learn more at [sanicbook.com](https://sanicbook.com/) :--:1  :---
+
+## Thank you
+
+Thank you to everyone that participated in this release: :clap:
+
+[@aericson](https://github.com/aericson) [@ahankinson](https://github.com/ahankinson) [@ahopkins](https://github.com/ahopkins) [@ariebovenberg](https://github.com/ariebovenberg) [@ashleysommer](https://github.com/ashleysommer) [@Bluenix2](https://github.com/Bluenix2) [@ChihweiLHBird](https://github.com/ChihweiLHBird) [@dotlambda](https://github.com/dotlambda) [@eric-spitler](https://github.com/eric-spitler) [@howzitcdf](https://github.com/howzitcdf) [@jonra1993](https://github.com/jonra1993) [@prryplatypus](https://github.com/prryplatypus) [@raphaelauv](https://github.com/raphaelauv) [@SaidBySolo](https://github.com/SaidBySolo) [@SerGeRybakov](https://github.com/SerGeRybakov) [@Tronic](https://github.com/Tronic)
+
+
+---
+
+If you enjoy the project, please consider contributing. Of course we love code contributions, but we also love contributions in any form. Consider writing some documentation, showing off use cases, joining conversations and making your voice known, and if you are able: [financial contributions](https://opencollective.com/sanic-org/).
From 464f5d91768a06724d30ffbad03d66c2f15228fb Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:39 +0300
Subject: [PATCH 191/776] New translations v21.3.md (Chinese Simplified)
---
src/zh/guide/release-notes/v21.3.md | 93 ++++++++++++++---------------
1 file changed, 44 insertions(+), 49 deletions(-)
diff --git a/src/zh/guide/release-notes/v21.3.md b/src/zh/guide/release-notes/v21.3.md
index f0eee7245e..c2e3aab998 100644
--- a/src/zh/guide/release-notes/v21.3.md
+++ b/src/zh/guide/release-notes/v21.3.md
@@ -6,42 +6,38 @@
Sanic 现在变得更快了。
-嗯,已经很快了。但是随着 v21 版本的第一次迭代更新,我们整合了一些重大的里程碑式的变化,并做出了一些切实的改进。这包含了一些已经酝酿多年的想法,并最终成为发行版。
+嗯,已经很快了。 但是随着 v21 版本的第一次迭代更新,我们整合了一些重大的里程碑式的变化,并做出了一些切实的改进。 这包含了一些已经酝酿多年的想法,并最终成为发行版。
-::: warning 突破性变化
-
-21.3 版本引入了很多新特性。同时也带来了一些突破性变化。这就是为什么这些变化要在上一个长期支持版(LTS)发布后引入的原因。如果您依赖已经被删除的内容,那么您应该继续使用 v20.12LTS 直到您可以对其进行升级。
+21.3 版本引入了很多新特性。 同时也带来了一些突破性变化。 这就是为什么这些变化要在上一个长期支持版(LTS)发布后引入的原因。 如果您依赖已经被删除的内容,那么您应该继续使用 v20.12LTS 直到您可以对其进行升级。
```bash
pip install "sanic>=20.12,<20.13"
pip freeze > requirements.txt
```
-对于大多数的安装,您可以非常轻松的升级。
-
-:::
+For most typical installations, you should be able to upgrade without a problem. :::
## 更新内容(What to know)
-值得注意的新功能或突破性变化,以及更新内容...
+对于大多数的安装,您可以非常轻松的升级。
### 仅支持 Python3.7 及以上版本(Python 3.7+ Only)
-新版本放弃了对 Python3.6 的支持,20.12LTS 将是最后一个支持 Python3.6 的长期支持版,直到2022 年 12 月停止维护。19.12LTS 将继续支持 Python3.6,直到 2021 年 12 月停止维护。
+新版本放弃了对 Python3.6 的支持,20.12LTS 将是最后一个支持 Python3.6 的长期支持版,直到2022 年 12 月停止维护。 19.12LTS 将继续支持 Python3.6,直到 2021 年 12 月停止维护。
-阅读我们的 [发行安排](../project/policies.html#发行安排-release-schedule) 以了解更多内容。
+值得注意的新功能或突破性变化,以及更新内容...
### 流式传输合并为单个流(Streaming as first class citizen)
-将请求/响应周期统一为单个流极大的提升了速度。以前,常规周期和流式传输周期之间存在差异。这已经简化在底层代码中, 即 Api 现在保持不变, 以兼容性的方式进行更新。令人高兴的是,现在 **所有** 的流式请求都合并到了单个流中。
+将请求/响应周期统一为单个流极大的提升了速度。 以前,常规周期和流式传输周期之间存在差异。 这已经简化在底层代码中, 即 Api 现在保持不变, 以兼容性的方式进行更新。 令人高兴的是,现在 **所有** 的流式请求都合并到了单个流中。
-阅读 [流式传输更新的内容](../advanced/streaming.md#response-streaming) 以了解更多
+阅读我们的 [发行安排](../project/policies.html#发行安排-release-schedule) 以了解更多内容。
### 全新的路由器(Router overhaul)
-旧的 Sanic 路由器是基于正则表达式的。此外,它还存在一些缺陷,使得在运行时很难修改,并导致一些性能问题。此次变化已经酝酿多年,现在在[启动时将路由器转换为编译树](https://community.sanicframework.org/t/a-fast-new-router/649/41)。我们也期待今年会有更多性能上的改进。
+旧的 Sanic 路由器是基于正则表达式的。 此外,它还存在一些缺陷,使得在运行时很难修改,并导致一些性能问题。 此次变化已经酝酿多年,现在在[启动时将路由器转换为编译树](https://community.sanicframework.org/t/a-fast-new-router/649/41)。 我们也期待今年会有更多性能上的改进。
-对外的 API 保持了向后的兼容性。然而,如果您之前调用过路由器内部的方法,您应该注意以下一些变化。比如:
+对外的 API 保持了向后的兼容性。 然而,如果您之前调用过路由器内部的方法,您应该注意以下一些变化。 比如:
1. `Router.get()` 有了一个全新的返回值
2. `Router` 现在不是 `namedtuple`,而是一个普通的对象
@@ -53,11 +49,11 @@ pip freeze > requirements.txt
### 信号 API(Signals API) ⭐️
-当前为 *测试功能*,该 API *将于 v21.6 版本正式发布*。
+_BETA Feature: API to be finalized in v21.6_
-新的 Sanic 路由器的一个好处是,它可以同时为 [新的信号 API](https://github.com/sanic-org/sanic/issues/1630) 提供支持。这个特性现在被发布给公众使用,正式发布时,该接口可能保持现有用法。
+新的 Sanic 路由器的一个好处是,它可以同时为 [新的信号 API](https://github.com/sanic-org/sanic/issues/1630) 提供支持。 这个特性现在被发布给公众使用,正式发布时,该接口可能保持现有用法。
-该功能的核心思想是:
+当前为 *测试功能*,该 API *将于 v21.6 版本正式发布*。
1. 为了允许开发者更好地控制和访问请求的生命周期
2. 提供一个工具来使您的响应函数协调和发送信息
@@ -65,11 +61,9 @@ pip freeze > requirements.txt
该功能提供了三种新的使用方法:
-| 用法 | 说明 |
-| :---------------: | :-----------------------------------------------------------------------------------: |
-| @app.signal(...) | 用于定义一个信号处理程序,它的用法和 `route` 十分相似,无论在何处收到信号,该程序都将被执行。 |
-| app.event(...) | 一个可在应用程序中的任何地方使用的变量,用于暂停执行,直到事件被触发。 |
-| app.dispatch(...) | 触发事件,并运行信号处理程序 |
+- `@app.signal(...)` - For defining a signal handler. It looks and operates very much like a route. Whenever that signal is dispatched, this handler will be executed.
+- 一个可在应用程序中的任何地方使用的变量,用于暂停执行,直到事件被触发。
+- 触发事件,并运行信号处理程序
```python
@app.signal("foo.bar.")
@@ -94,21 +88,22 @@ async def trigger(request):
### 路由名称(Route naming)
-曾经,路由可以通过 `route.name` 和 `route.endpoint` 进行引用。虽然看起来几乎一样,但是还是存在有细微的差别。现在,所有的路由都将统一命名和使用。
+曾经,路由可以通过 `route.name` 和 `route.endpoint` 进行引用。 虽然看起来几乎一样,但是还是存在有细微的差别。 现在,所有的路由都将统一命名和使用。
```
.[optional:.]
```
-这个新的 “name” 将会被分配该属性 `route.name`。我们取消了 `route.enpoint` 属性,并将在 v21.9 版本中正式停用。在此之前,它的别名仍将是 `route.name`。
+这个新的 “name” 将会被分配该属性 `route.name`。 我们取消了 `route.enpoint` 属性,并将在 v21.9 版本中正式停用。 在此之前,它的别名仍将是 `route.name`。
除此之外,以前用于静态文件,websocket 和蓝图的命名前缀也将被移除。
### 全新的装饰器(New decorators)
-新增数种装饰器,取代原有的装饰器,方便 IDE 进行自动补全
+Several new convenience decorators to help IDEs with autocomplete.
```python
+@app.signal(...)
# Alias to @app.listener("...")
@app.before_server_start
@app.after_server_stop
@@ -118,11 +113,13 @@ async def trigger(request):
# Alias to @app.middleware("...")
@app.on_request
@app.on_response
+@app.on_request
+@app.on_response
```
### 路由解码(Unquote in route)
-如果您的路由参数使用了非 ascii 码的字符,Sanic 将不再为您进行解码,您需要显式传参来告诉路由它应该为您解码。
+如果您的路由参数使用了非 ascii 码的字符,Sanic 将不再为您进行解码,您需要显式传参来告诉路由它应该为您解码。 You will need to specifically tell the route definition that it should do so.
```python
@app.route("/overload/", methods=["GET"], unquote=True)
@@ -133,11 +130,11 @@ request, response = app.test_client.get("/overload/您好")
assert response.text == "OK2 您好"
```
-如果您忘了这样做,您的响应文本将是保持编码状态的文本。
+新增数种装饰器,取代原有的装饰器,方便 IDE 进行自动补全
### 可修改的 `Request.match_info`(Alter `Request.match_info`)
-`match_info` 始终为匹配的路径参数提供数据。您现在可以修改它,例如在中间件中。
+`match_info` 始终为匹配的路径参数提供数据。 您现在可以修改它,例如在中间件中。
```python
@app.on_request
@@ -147,7 +144,7 @@ def convert_to_snake_case(request):
### 路由版本(Version types in routes)
-现在,路由中的 `version` 参数可以使用:
+如果您忘了这样做,您的响应文本将是保持编码状态的文本。
- `str`
- `int`
@@ -158,10 +155,9 @@ def convert_to_snake_case(request):
@app.route("/foo", version=2)
@app.route("/foo", version=2.1)
```
-
### 安全的 Body 处理方式(Safe method handling with body)
-默认情况下, `GET`,`HEAD`,`OPTIONS` 和 `DELETE` 方法将不再对请求体进行解码,您可以通过以下的方式取消这一特性:
+Route handlers for `GET`, `HEAD`, `OPTIONS` and `DELETE` will not decode any HTTP body passed to it. You can override this:
```python
@app.delete(..., ignore_body=False)
@@ -169,9 +165,9 @@ def convert_to_snake_case(request):
### 应用,蓝图和蓝图组的奇偶校验(Application, Blueprint and Blueprint Group parity)
-`Sanic` 和 `Blueprint` 类 具有很多类似的方法,在以前,由于他们的实现策略略有不同,他们使用了很多具有重复功能的代码。既然他们都继承自同一个基类,开发者和插件应该有一个统一的 API 来进行工作。
+The `Sanic` and `Blueprint` classes share a common base. Previously they duplicated a lot of functionality, that lead to slightly different implementations between them. 既然他们都继承自同一个基类,开发者和插件应该有一个统一的 API 来进行工作。
-此外,蓝图组也支持常见的 URL 拓展参数了,例如:`version` 和 `strict_slashes`。
+默认情况下, `GET`,`HEAD`,`OPTIONS` 和 `DELETE` 方法将不再对请求体进行解码,您可以通过以下的方式取消这一特性:
### 放弃对 `httpx` 的依赖(Dropped `httpx` from dependencies)
@@ -179,13 +175,13 @@ def convert_to_snake_case(request):
### 移除测试库(Removed `testing` library)
-Sanic 原本自带的测试客户端已经被移除。该测试客户端现在拥有了独立的仓库:[sanic-org/sanic-testing](https://github.com/sanic-org/sanic-testing) 自己的 [PyPI 项目](https://pypi.org/project/sanic-testing/)。
+Sanic 原本自带的测试客户端已经被移除。 该测试客户端现在拥有了独立的仓库:[sanic-org/sanic-testing](https://github.com/sanic-org/sanic-testing) 自己的 [PyPI 项目](https://pypi.org/project/sanic-testing/)。
-如果您已经安装了 `sanic-testing` ,那么当您创建了 `Sanic()` 应用时测试客户端也同时可用。所以 **唯一** 的变化就是您需要添加 `sanic-testing` 到您测试工具的依赖中。
+如果您已经安装了 `sanic-testing` ,那么当您创建了 `Sanic()` 应用时测试客户端也同时可用。 所以 **唯一** 的变化就是您需要添加 `sanic-testing` 到您测试工具的依赖中。
### 应用和连接级别的上下文对象(Application and connection level context (`ctx`) objects)
-19.9 版本 [添加](https://github.com/sanic-org/sanic/pull/1666/files) 了 `request.ctx` 的 API。这个对象可以轻松地将属性和数据附加到请求对象上(比如在中间件中),并在应用程序的其他地方重复使用这些信息。
+19.9 版本 [添加](https://github.com/sanic-org/sanic/pull/1666/files) 了 `request.ctx` 的 API。 这个对象可以轻松地将属性和数据附加到请求对象上(比如在中间件中),并在应用程序的其他地方重复使用这些信息。
同样的,这个概念也被拓展到了下面两处:
@@ -194,7 +190,7 @@ Sanic 原本自带的测试客户端已经被移除。该测试客户端现在
#### 应用上下文(Application context)
-一个常见的使用场景是将属性附加到应用程序实例上。为了保持一致性,并避免与 Sanic 自身属性的名称冲突,`ctx` 对象现在存在于 `Sanic` 实例上。
+一个常见的使用场景是将属性附加到应用程序实例上。 为了保持一致性,并避免与 Sanic 自身属性的名称冲突,`ctx` 对象现在存在于 `Sanic` 实例上。
```python
@app.before_server_startup
@@ -208,7 +204,7 @@ async def startup_db(app, _):
#### 连接上下文(Connection context)
-当一个客户端发送了一个包含 keep-alive 头的请求,Sanic 将尝试保持这个传输套接字 [一段时间](../deployment/configuration.md#keep-alive-timeout)。现在这个传输对象也有一个可用的 `ctx` 对象了。这实际上意味着来自同一个客户端的多个请求(就在这里传输层被复用)可以共享状态。
+当一个客户端发送了一个包含 keep-alive 头的请求,Sanic 将尝试保持这个传输套接字 [一段时间](../deployment/configuration.md#keep-alive-timeout)。 现在这个传输对象也有一个可用的 `ctx` 对象了。 这实际上意味着来自同一个客户端的多个请求(就在这里传输层被复用)可以共享状态。
```python
@app.on_request
@@ -230,40 +226,39 @@ request.conn_info.ctx.foo=3
```
::: warning
-
-连接级别的上下文是一个实验性的功能,并且应该会在 v21.6 版本中被完善。
-
+Connection level context is an experimental feature, and should be finalized in v21.6.
:::
## 新闻(News)
+
### 一个新的前端(A NEW frontpage) 🎉
-我们把文档分成了两部分,储存库中的文档将仍旧使用 ReadTheDocs 进行构建,但仅限于 API 文档。新的前端页面将使用 “Sanic 用户指南”。
+We have split the documentation into two. The docstrings inside the codebase will still continue to build sphinx docs to ReadTheDocs. However, it will be limited to API documentation. 新的前端页面将使用 “Sanic 用户指南”。
-新的站点基于 vuepress 构建,欢迎投稿,我们也会请人对文档进行翻译。
+The new site runs on Vuepress. Contributions are welcome. We also invite help in translating the documents.
-作为文档的一部分,我们同样更新了 ReadTheDocs 上的文档,但仅限于 API 接口文档。
+连接级别的上下文是一个实验性的功能,并且应该会在 v21.6 版本中被完善。
### 聊天室移至 Discord(Chat has moved to Discord)
-Gitter 聊天室向着淘汰又迈进了一步。取而代之的将是我们新开放的 [Discord 聊天室](https://discord.gg/FARQzAEMAA)。
+Gitter 聊天室向着淘汰又迈进了一步。 取而代之的将是我们新开放的 [Discord 聊天室](https://discord.gg/FARQzAEMAA)。
### 资助 Sanic(Open Collective)
-Sanic 社区组织在 Open Collective 上申请了捐献项目,任何愿意为 Sanic 发展提供资金支持的人可以 [点此](https://opencollective.com/sanic-org) 参与。
+The Sanic Community Organization has [opened a page on Open Collective](https://opencollective.com/sanic-org) to enable anyone that would like to financially support the development of Sanic.
### 2021 发布经理(2021 Release Managers)
-感谢 @sjsadowski 和 @yunstanford 担任 2019 年和 2020 年的发布经理。今年的发布经理是 @ahopkins 和 @vltr。
+感谢 @sjsadowski 和 @yunstanford 担任 2019 年和 2020 年的发布经理。 今年的发布经理是 @ahopkins 和 @vltr。
## 鸣谢(Thank you)
-感谢所有参与此次发布的人::clap:
+作为文档的一部分,我们同样更新了 ReadTheDocs 上的文档,但仅限于 API 接口文档。
[@ahopkins](https://github.com/ahopkins) [@akshgpt7](https://github.com/akshgpt7) [@artcg](https://github.com/artcg) [@ashleysommer](https://github.com/ashleysommer) [@elis-k](https://github.com/elis-k) [@harshanarayana](https://github.com/harshanarayana) [@sjsadowski](https://github.com/sjsadowski) [@tronic](https://github.com/tronic) [@vltr](https://github.com/vltr)
-感谢 [@ConnorZhang](https://github.com/miss85246) 和 [@ZinkLu](https://github.com/ZinkLu) 将文档翻译成中文。
+Sanic 社区组织在 Open Collective 上申请了捐献项目,任何愿意为 Sanic 发展提供资金支持的人可以 [点此](https://opencollective.com/sanic-org) 参与。
---
From 9a90465796e0c696c03fae7f40a40cb83a985a82 Mon Sep 17 00:00:00 2001
From: Adam Hopkins
Date: Mon, 29 Aug 2022 23:46:40 +0300
Subject: [PATCH 192/776] New translations v21.3.md (Portuguese, Brazilian)
---
src/pt/guide/release-notes/v21.3.md | 262 ++++++++++++++++++++++++++++
1 file changed, 262 insertions(+)
create mode 100644 src/pt/guide/release-notes/v21.3.md
diff --git a/src/pt/guide/release-notes/v21.3.md b/src/pt/guide/release-notes/v21.3.md
new file mode 100644
index 0000000000..bca0729af6
--- /dev/null
+++ b/src/pt/guide/release-notes/v21.3.md
@@ -0,0 +1,262 @@
+# Version 21.3
+
+[[toc]]
+
+## Introduction
+
+Sanic is now faster.
+
+Well, it already was fast. But with the first iteration of the v21 release, we incorporated a few major milestones that have made some tangible improvements. These encompass some ideas that have been in the works for years, and have finally made it into the released version.
+
+::: warning Breaking changes Version 21.3 introduces a lot of new features. But, it also includes some breaking changes. This is why these changes were introduced after the last LTS. If you rely upon something that has been removed, you should continue to use v20.12LTS until you are able to upgrade.
+
+```bash
+pip install "sanic>=20.12,<20.13"
+pip freeze > requirements.txt
+```
+
+For most typical installations, you should be able to upgrade without a problem. :::
+
+## What to know
+
+Notable new or breaking features, and what to upgrade...
+
+### Python 3.7+ Only
+
+This version drops Python 3.6 support. Version 20.12LTS will continue to support Python 3.6 until its EOL in December, 2022, and version 19.12LTS will support it until its EOL in December, 2021.
+
+Read more about our [LTS policy](../project/policies.md#long-term-support-v-interim-releases).
+
+### Streaming as first class citizen
+
+The biggest speed improvement came from unifying the request/response cycle into a single flow. Previously, there was a difference between regular cycles, and streaming cycles. This has been simplified under the hood, even though the API is staying the same right now for compatibility. The net benefit is that **all** requests now should see a new benefit.
+
+Read more about [streaming changes](../advanced/streaming.md#response-streaming).
+
+### Router overhaul
+
+The old Sanic router was based upon regular expressions. In addition it suffered from a number of quirks that made it hard to modify at run time, and resulted in some performance issues. This change has been years in the making and now [converts the router to a compiled tree at startup](https://community.sanicframework.org/t/a-fast-new-router/649/41). Look for additional improvements throughout the year.
+
+The outward facing API has kept backwards compatibility. However, if you were accessing anything inside the router specifically, you many notice some changes. For example:
+
+1. `Router.get()` has a new return value
+2. `Route` is now a proper class object and not a `namedtuple`
+3. If building the router manually, you will need to call `Router.finalize()` before it is usable
+4. There is a new `` pattern that can be matched in your routes
+5. You cannot startup an application without at least one route defined
+
+The router is now located in its own repository: [sanic-org/sanic-router](https://github.com/sanic-org/sanic-router) and is also its own [standalone package on PyPI](https://pypi.org/project/sanic-routing/).
+
+### Signals API ⭐️
+
+_BETA Feature: API to be finalized in v21.6_
+
+A side benefit of the new router is that it can do double duty also powering the [new signals API](https://github.com/sanic-org/sanic/issues/1630). This feature is being released for public usage now, and likely the public API will not change in its final form.
+
+The core ideas of this feature are:
+
+1. to allow the developer greater control and access to plugging into the server and request lifecycles,
+2. to provide new tools to synchronize and send messages through your application, and
+3. to ultimately further increase performance.
+
+The API introduces three new methods:
+
+- `@app.signal(...)` - For defining a signal handler. It looks and operates very much like a route. Whenever that signal is dispatched, this handler will be executed.
+- `app.event(...)` - An awaitable that can be used anywhere in your application to pause execution until the event is triggered.
+- `app.dispatch(...)` - Trigger an event and cause the signal handlers to execute.
+
+```python
+@app.signal("foo.bar.