Conversion of User Guide to the SHH stack (#2781)
This commit is contained in:
389
guide/content/en/release-notes/2023/v23.3.md
Normal file
389
guide/content/en/release-notes/2023/v23.3.md
Normal file
@@ -0,0 +1,389 @@
|
||||
# Version 23.3
|
||||
|
||||
.. toc::
|
||||
|
||||
## Introduction
|
||||
|
||||
This is the first release of the version 23 [release cycle](../../org/policies.md#release-schedule). As such contains some deprecations and hopefully some *small* breaking changes. If you run into any issues, please raise a concern on [GitHub](https://github.com/sanic-org/sanic/issues/new/choose).
|
||||
|
||||
## 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...
|
||||
|
||||
### Nicer traceback formatting
|
||||
|
||||
The SCO adopted two projects into the Sanic namespace on GitHub: [tracerite](https://github.com/sanic-org/tracerite) and [html5tagger](https://github.com/sanic-org/html5tagger). These projects team up to provide and incredible new error page with more details to help the debugging process.
|
||||
|
||||
This is provided out of the box, and will adjust to display only relevant information whether in DEBUG more or PROD mode.
|
||||
|
||||
.. column::
|
||||
|
||||
**Using PROD mode**
|
||||

|
||||
|
||||
.. column::
|
||||
|
||||
**Using DEBUG mode**
|
||||

|
||||
|
||||
Light and dark mode HTML pages are available and will be used implicitly.
|
||||
|
||||
### Basic file browser on directories
|
||||
|
||||
When serving a directory from a static handler, Sanic can be configured to show a basic file browser instead using `directory_view=True`.
|
||||
|
||||
.. column::
|
||||
|
||||
```python
|
||||
app.static("/uploads/", "/path/to/dir/", directory_view=True)
|
||||
```
|
||||
|
||||
.. column::
|
||||
|
||||

|
||||
|
||||
Light and dark mode HTML pages are available and will be used implicitly.
|
||||
|
||||
### HTML templating with Python
|
||||
|
||||
Because Sanic is using [html5tagger](https://github.com/sanic-org/html5tagger) under the hood to render the [new error pages](#nicer-traceback-formatting), you now have the package available to you to easily generate HTML pages in Python code:
|
||||
|
||||
.. column::
|
||||
|
||||
```python
|
||||
from html5tagger import Document
|
||||
from sanic import Request, Sanic, html
|
||||
|
||||
app = Sanic("TestApp")
|
||||
|
||||
@app.get("/")
|
||||
async def handler(request: Request):
|
||||
doc = Document("My Website")
|
||||
doc.h1("Hello, world.")
|
||||
with doc.table(id="data"):
|
||||
doc.tr.th("First").th("Second").th("Third")
|
||||
doc.tr.td(1).td(2).td(3)
|
||||
doc.p(class_="text")("A paragraph with ")
|
||||
doc.a(href="/files")("a link")(" and ").em("formatting")
|
||||
return html(doc)
|
||||
```
|
||||
|
||||
.. column::
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>My Website</title>
|
||||
<h1>Hello, world.</h1>
|
||||
<table id=data>
|
||||
<tr>
|
||||
<th>First
|
||||
<th>Second
|
||||
<th>Third
|
||||
<tr>
|
||||
<td>1
|
||||
<td>2
|
||||
<td>3
|
||||
</table>
|
||||
<p class=text>
|
||||
A paragraph with <a href="/files">a link</a> and <em>formatting</em>
|
||||
```
|
||||
|
||||
### Auto-index serving is available on static handlers
|
||||
|
||||
Sanic can now be configured to serve an index file when serving a static directory.
|
||||
|
||||
```python
|
||||
app.static("/assets/", "/path/to/some/dir", index="index.html")
|
||||
```
|
||||
|
||||
When using the above, requests to `http://example.com/assets/` will automatically serve the `index.html` file located in that directory.
|
||||
|
||||
### Simpler CLI targets
|
||||
|
||||
It is common practice for Sanic applications to use the variable `app` as the application instance. Because of this, the CLI application target (the second value of the `sanic` CLI command) now tries to infer the application instance based upon what the target is. If the target is a module that contains an `app` variable, it will use that.
|
||||
|
||||
There are now four possible ways to launch a Sanic application from the CLI.
|
||||
|
||||
#### 1. Application instance
|
||||
|
||||
As normal, providing a path to a module and an application instance will work as expected.
|
||||
|
||||
```sh
|
||||
sanic path.to.module:app # global app instance
|
||||
```
|
||||
|
||||
#### 2. Application factory
|
||||
|
||||
Previously, to serve the factory pattern, you would need to use the `--factory` flag. This can be omitted now.
|
||||
|
||||
```sh
|
||||
sanic path.to.module:create_app # factory pattern
|
||||
```
|
||||
|
||||
#### 3. Path to launch Sanic Simple Server
|
||||
|
||||
Similarly, to launch the Sanic simple server (serve static directory), you previously needed to use the `--simple` flag. This can be omitted now, and instead simply provide the path to the directory.
|
||||
|
||||
```sh
|
||||
sanic ./path/to/directory/ # simple serve
|
||||
```
|
||||
|
||||
#### 4. Python module containing an `app` variable
|
||||
|
||||
As stated above, if the target is a module that contains an `app` variable, it will use that (assuming that `app` variable is a `Sanic` instance).
|
||||
|
||||
```sh
|
||||
sanic path.to.module # module with app instance
|
||||
```
|
||||
|
||||
### More convenient methods for setting and deleting cookies
|
||||
|
||||
The old cookie pattern was awkward and clunky. It didn't look like regular Python because of the "magic" going on under the hood.
|
||||
|
||||
.. column::
|
||||
|
||||
😱 This is not intuitive and is confusing for newcomers.
|
||||
|
||||
.. column::
|
||||
|
||||
```python
|
||||
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
|
||||
```
|
||||
|
||||
There are now new methods (and completely overhauled `Cookie` and `CookieJar` objects) to make this process more convenient.
|
||||
|
||||
.. column::
|
||||
|
||||
😌 Ahh... Much nicer.
|
||||
|
||||
.. column::
|
||||
|
||||
```python
|
||||
response = text("There's a cookie up in this response")
|
||||
response.add_cookie(
|
||||
"test",
|
||||
"It worked!",
|
||||
domain=".yummy-yummy-cookie.com",
|
||||
httponly=True
|
||||
)
|
||||
```
|
||||
|
||||
### Better cookie compatibility
|
||||
|
||||
Sanic has added support for [cookie prefixes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#cookie_prefixes), making it seemless and easy to read and write cookies with the values.
|
||||
|
||||
While setting the cookie...
|
||||
|
||||
```py
|
||||
response.cookies.add_cookie("foo", "bar", host_prefix=True)
|
||||
```
|
||||
|
||||
This will create the prefixed cookie: `__Host-foo`. However, when accessing the cookie on an incoming request, you can do so without knowing about the existence of the header.
|
||||
|
||||
```py
|
||||
request.cookies.get("foo")
|
||||
```
|
||||
|
||||
It should also be noted, cookies can be accessed as properties just like [headers](#access-any-header-as-a-property).
|
||||
|
||||
```python
|
||||
request.cookies.foo
|
||||
```
|
||||
|
||||
And, cookies are similar to the `request.args` and `request.form` objects in that multiple values can be retrieved using `getlist`.
|
||||
|
||||
```py
|
||||
request.cookies.getlist("foo")
|
||||
```
|
||||
|
||||
Also added is support for creating [partitioned cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#partitioned_cookie).
|
||||
|
||||
```py
|
||||
response.cookies.add_cookie(..., partitioned=True)
|
||||
```
|
||||
|
||||
### 🚨 *BREAKING CHANGE* - More consistent and powerful `SanicException`
|
||||
|
||||
Sanic has for a while included the `SanicException` as a base class exception. This could be extended to add `status_code`, etc. [See more details](http://localhost:8080/en/guide/best-practices/exceptions.html).
|
||||
|
||||
**NOW**, using all of the various exceptions has become easier. The commonly used exceptions can be imported directly from the root level module.
|
||||
|
||||
```python
|
||||
from sanic import NotFound, Unauthorized, BadRequest, ServerError
|
||||
```
|
||||
|
||||
In addition, all of these arguments are available as keyword arguments on every exception type:
|
||||
|
||||
| argument | type | description |
|
||||
|--|--|--|
|
||||
| `quiet` | `bool` | Suppress the traceback from the logs |
|
||||
| `context` | `dict` | Additional information shown in error pages *always* |
|
||||
| `extra` | `dict` | Additional information shown in error pages in *DEBUG* mode |
|
||||
| `headers` | `dict` | Additional headers sent in the response |
|
||||
|
||||
None of these are themselves new features. However, they are more consistent in how you can use them, thus creating a powerful way to control error responses directly.
|
||||
|
||||
```py
|
||||
raise ServerError(headers={"foo": "bar"})
|
||||
```
|
||||
|
||||
The part of this that is a breaking change is that some formerly positional arguments are now keyword only.
|
||||
|
||||
You are encouraged to look at the specific implementations for each error in the [API documents](https://sanic.readthedocs.io/en/stable/sanic/api/exceptions.html#module-sanic.exceptions).
|
||||
|
||||
### 🚨 *BREAKING CHANGE* - Refresh `Request.accept` functionality to be more performant and spec-compliant
|
||||
|
||||
Parsing od the `Accept` headers into the `Request.accept` accessor has been improved. If you were using this property and relying upon its equality operation, this has changed. You should probably transition to using the `request.accept.match()` method.
|
||||
|
||||
### Access any header as a property
|
||||
|
||||
To simplify access to headers, you can access a raw (unparsed) version of the header as a property. The name of the header is the name of the property in all lowercase letters, and switching any hyphens (`-`) to underscores (`_`).
|
||||
|
||||
For example:
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
GET /foo/bar HTTP/1.1
|
||||
Host: localhost
|
||||
User-Agent: curl/7.88.1
|
||||
X-Request-ID: 123ABC
|
||||
```
|
||||
|
||||
.. column::
|
||||
|
||||
```py
|
||||
request.headers.host
|
||||
request.headers.user_agent
|
||||
request.headers.x_request_id
|
||||
```
|
||||
|
||||
### Consume `DELETE` body by default
|
||||
|
||||
By default, the body of a `DELETE` request will now be consumed and read onto the `Request` object. This will make `body` available like on `POST`, `PUT`, and `PATCH` requests without any further action.
|
||||
|
||||
### Custom `CertLoader` for direct control of creating `SSLContext`
|
||||
|
||||
Sometimes you may want to create your own `SSLContext` object. To do this, you can create your own subclass of `CertLoader` that will generate your desired context object.
|
||||
|
||||
```python
|
||||
from sanic.worker.loader import CertLoader
|
||||
|
||||
class MyCertLoader(CertLoader):
|
||||
def load(self, app: Sanic) -> SSLContext:
|
||||
...
|
||||
|
||||
app = Sanic(..., certloader_class=MyCertLoader)
|
||||
```
|
||||
|
||||
### Deprecations and Removals
|
||||
|
||||
1. *DEPRECATED* - Dict-style cookie setting
|
||||
1. *DEPRECATED* - Using existence of JSON data on the request for one factor in using JSON error formatter
|
||||
1. *REMOVED* - Remove deprecated `__blueprintname__` property
|
||||
1. *REMOVED* - duplicate route names
|
||||
1. *REMOVED* - duplicate exception handler definitions
|
||||
1. *REMOVED* - inspector CLI with flags
|
||||
1. *REMOVED* - legacy server (including `sanic.server.serve_single` and `sanic.server.serve_multiple`)
|
||||
1. *REMOVED* - serving directory with bytes string
|
||||
1. *REMOVED* - `Request.request_middleware_started`
|
||||
1. *REMOVED* - `Websocket.connection`
|
||||
|
||||
#### Duplicated route names are no longer allowed
|
||||
|
||||
In version 22.9, Sanic announced that v23.3 would deprecate allowing routes to be registered with duplicate names. If you see the following error, it is because of that change:
|
||||
|
||||
> sanic.exceptions.ServerError: Duplicate route names detected: SomeApp.some_handler. You should rename one or more of them explicitly by using the `name` param, or changing the implicit name derived from the class and function name. For more details, please see https://sanic.dev/en/guide/release-notes/v23.3.html#duplicated-route-names-are-no-longer-allowed
|
||||
|
||||
If you are seeing this, you should opt-in to using explicit names for your routes.
|
||||
|
||||
.. column::
|
||||
|
||||
**BAD**
|
||||
```python
|
||||
app = Sanic("SomeApp")
|
||||
|
||||
@app.get("/")
|
||||
@app.get("/foo")
|
||||
async def handler(request: Request):
|
||||
```
|
||||
|
||||
.. column::
|
||||
|
||||
**GOOD**
|
||||
```python
|
||||
app = Sanic("SomeApp")
|
||||
|
||||
@app.get("/", name="root")
|
||||
@app.get("/foo", name="foo")
|
||||
async def handler(request: Request):
|
||||
```
|
||||
|
||||
#### Response cookies
|
||||
|
||||
Response cookies act as a `dict` for compatibility purposes only. In version 24.3, all `dict` methods will be removed and response cookies will be objects only.
|
||||
|
||||
Therefore, if you are using this pattern to set cookie properties, you will need to upgrade it before version 24.3.
|
||||
|
||||
```python
|
||||
resp = HTTPResponse()
|
||||
resp.cookies["foo"] = "bar"
|
||||
resp.cookies["foo"]["httponly"] = True
|
||||
```
|
||||
|
||||
Instead, you should be using the `add_cookie` method:
|
||||
|
||||
```python
|
||||
resp = HTTPResponse()
|
||||
resp.add_cookie("foo", "bar", httponly=True)
|
||||
```
|
||||
|
||||
#### Request cookies
|
||||
|
||||
Sanic has added support for reading duplicated cookie keys to be more in compliance with RFC specifications. To retain backwards compatibility, accessing a cookie value using `__getitem__` will continue to work to fetch the first value sent. Therefore, in version 23.3 and prior versions this will be `True`.
|
||||
|
||||
```python
|
||||
assert request.cookies["foo"] == "bar"
|
||||
assert request.cookies.get("foo") == "bar"
|
||||
```
|
||||
|
||||
Version 23.3 added `getlist`
|
||||
|
||||
```python
|
||||
assert request.cookies.getlist("foo") == ["bar"]
|
||||
```
|
||||
|
||||
As stated above, the `get` and `getlist` methods are available similar to how they exist on other request properties (`request.args`, `request.form`, etc). Starting in v24.3, the `__getitem__` method for cookies will work exactly like those properties. This means that `__getitem__` will return a list of values.
|
||||
|
||||
Therefore, if you are relying upon this functionality to return only one value, you should upgrade to the following pattern before v24.3.
|
||||
|
||||
```python
|
||||
assert request.cookies["foo"] == ["bar"]
|
||||
assert request.cookies.get("foo") == "bar"
|
||||
assert request.cookies.getlist("foo") == ["bar"]
|
||||
```
|
||||
|
||||
## Thank you
|
||||
|
||||
Thank you to everyone that participated in this release: :clap:
|
||||
|
||||
[@ahopkins](https://github.com/ahopkins)
|
||||
[@ChihweiLHBird](https://github.com/ChihweiLHBird)
|
||||
[@deounix](https://github.com/deounix)
|
||||
[@Kludex](https://github.com/Kludex)
|
||||
[@mbendiksen](https://github.com/mbendiksen)
|
||||
[@prryplatypus](https://github.com/prryplatypus)
|
||||
[@r0x0d](https://github.com/r0x0d)
|
||||
[@SaidBySolo](https://github.com/SaidBySolo)
|
||||
[@sjsadowski](https://github.com/sjsadowski)
|
||||
[@stricaud](https://github.com/stricaud)
|
||||
[@Tracyca209](https://github.com/Tracyca209)
|
||||
[@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/).
|
||||
195
guide/content/en/release-notes/2023/v23.6.md
Normal file
195
guide/content/en/release-notes/2023/v23.6.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# Version 23.6
|
||||
|
||||
.. toc::
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
This is the second release of the version 23 [release cycle](../../org/policies.md#release-schedule). If you run into any issues, please raise a concern on [GitHub](https://github.com/sanic-org/sanic/issues/new/choose).
|
||||
|
||||
## 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...
|
||||
|
||||
### Remove Python 3.7 support
|
||||
|
||||
Python 3.7 is due to reach its scheduled upstream end-of-life on 2023-06-27. Sanic is now dropping support for Python 3.7, and requires Python 3.8 or newer.
|
||||
|
||||
See [#2777](https://github.com/sanic-org/sanic/pull/2777).
|
||||
|
||||
### Resolve pypy compatibility issues
|
||||
|
||||
A small patch was added to the `os` module to once again allow for Sanic to run with PyPy. This workaround replaces the missing `readlink` function (missing in PyPy `os` module) with the function `os.path.realpath`, which serves to the same purpose.
|
||||
|
||||
See [#2782](https://github.com/sanic-org/sanic/pull/2782).
|
||||
|
||||
### Add custom typing to config and ctx objects
|
||||
|
||||
The `sanic.Sanic` and `sanic.Request` object have become generic types that will make it more convenient to have fully typed `config` and `ctx` objects.
|
||||
|
||||
In the most simple form, the `Sanic` object is typed as:
|
||||
|
||||
```python
|
||||
from sanic import Sanic
|
||||
app = Sanic("test")
|
||||
reveal_type(app) # N: Revealed type is "sanic.app.Sanic[sanic.config.Config, types.SimpleNamespace]"
|
||||
```
|
||||
|
||||
|
||||
.. tip:: Note
|
||||
|
||||
It should be noted, there is *no* requirement to use the generic types. The default types are `sanic.config.Config` and `types.SimpleNamespace`. This new feature is just an option for those that want to use it and existing types of `app: Sanic` and `request: Request` should work just fine.
|
||||
|
||||
|
||||
Now it is possible to have a fully-type `app.config`, `app.ctx`, and `request.ctx` objects though generics. This allows for better integration with auto completion tools in IDEs improving the developer experience.
|
||||
|
||||
```python
|
||||
from sanic import Request, Sanic
|
||||
from sanic.config import Config
|
||||
|
||||
class CustomConfig(Config):
|
||||
pass
|
||||
|
||||
class Foo:
|
||||
pass
|
||||
|
||||
class RequestContext:
|
||||
foo: Foo
|
||||
|
||||
class CustomRequest(Request[Sanic[CustomConfig, Foo], RequestContext]):
|
||||
@staticmethod
|
||||
def make_context() -> RequestContext:
|
||||
ctx = RequestContext()
|
||||
ctx.foo = Foo()
|
||||
return ctx
|
||||
|
||||
app = Sanic(
|
||||
"test", config=CustomConfig(), ctx=Foo(), request_class=CustomRequest
|
||||
)
|
||||
|
||||
@app.get("/")
|
||||
async def handler(request: CustomRequest):
|
||||
...
|
||||
```
|
||||
|
||||
As a side effect, now `request.ctx` is lazy initialized, which should reduce some overhead when the `request.ctx` is unused.
|
||||
|
||||
One further change you may have noticed in the above snippet is the `make_context` method. This new method can be used by custom `Request` types to inject an object different from a `SimpleNamespace` similar to how Sanic has allowed custom application context objects for a while.
|
||||
|
||||
For a more thorough discussion, see [custom typed application](../basics/app.md#custom-typed-application) and [custom typed request](../basics/app.md#custom-typed-request).
|
||||
|
||||
See [#2785](https://github.com/sanic-org/sanic/pull/2785).
|
||||
|
||||
### Universal exception signal
|
||||
|
||||
A new exception signal added for **ALL** exceptions raised while the server is running: `"server.exception.reporting"`. This is a universal signal that will be emitted for any exception raised, and dispatched as its own task. This means that it will *not* block the request handler, and will *not* be affected by any middleware.
|
||||
|
||||
This is useful for catching exceptions that may occur outside of the request handler (for example in signals, or in a background task), and it intended for use to create a consistent error handling experience for the user.
|
||||
|
||||
```python
|
||||
from sanic.signals import Event
|
||||
|
||||
@app.signal(Event.SERVER_LIFECYCLE_EXCEPTION)
|
||||
async def catch_any_exception(app: Sanic, exception: Exception):
|
||||
app.ctx.my_error_reporter_utility.error(exception)
|
||||
```
|
||||
|
||||
This pattern can be simplified with a new decorator `@app.report_exception`:
|
||||
|
||||
```python
|
||||
@app.report_exception
|
||||
async def catch_any_exception(app: Sanic, exception: Exception):
|
||||
print("Caught exception:", exception)
|
||||
```
|
||||
|
||||
It should be pointed out that this happens in a background task and is **NOT** for manipulation of an error response. It is only for reporting, logging, or other purposes that should be triggered when an application error occurs.
|
||||
|
||||
See [#2724](https://github.com/sanic-org/sanic/pull/2724) and [#2792](https://github.com/sanic-org/sanic/pull/2792).
|
||||
|
||||
### Add name prefixing to BP groups
|
||||
|
||||
Sanic had been raising a warning on duplicate route names for a while, and started to enforce route name uniqueness in [v23.3](https://sanic.dev/en/guide/release-notes/v23.3.html#deprecations-and-removals). This created a complication for blueprint composition.
|
||||
|
||||
New name prefixing parameter for blueprints groups has been added to alleviate this issue. It allows nesting of blueprints and groups to make them composable.
|
||||
|
||||
The addition is the new `name_prefix` parameter as shown in this snippet.
|
||||
|
||||
```python
|
||||
bp1 = Blueprint("bp1", url_prefix="/bp1")
|
||||
bp2 = Blueprint("bp2", url_prefix="/bp2")
|
||||
|
||||
bp1.add_route(lambda _: ..., "/", name="route1")
|
||||
bp2.add_route(lambda _: ..., "/", name="route2")
|
||||
|
||||
group_a = Blueprint.group(
|
||||
bp1, bp2, url_prefix="/group-a", name_prefix="group-a"
|
||||
)
|
||||
group_b = Blueprint.group(
|
||||
bp1, bp2, url_prefix="/group-b", name_prefix="group-b"
|
||||
)
|
||||
|
||||
app = Sanic("TestApp")
|
||||
app.blueprint(group_a)
|
||||
app.blueprint(group_b)
|
||||
```
|
||||
|
||||
The routes built will be named as follows:
|
||||
- `TestApp.group-a_bp1.route1`
|
||||
- `TestApp.group-a_bp2.route2`
|
||||
- `TestApp.group-b_bp1.route1`
|
||||
- `TestApp.group-b_bp2.route2`
|
||||
|
||||
See [#2727](https://github.com/sanic-org/sanic/pull/2727).
|
||||
|
||||
### Add `request.client_ip`
|
||||
|
||||
Sanic has introduced `request.client_ip`, a new accessor that provides client's IP address from both local and proxy data. It allows running the application directly on Internet or behind a proxy. This is equivalent to `request.remote_addr or request.ip`, providing the client IP regardless of how the application is deployed.
|
||||
|
||||
See [#2790](https://github.com/sanic-org/sanic/pull/2790).
|
||||
|
||||
### Increase of `KEEP_ALIVE_TIMEOUT` default to 120 seconds
|
||||
|
||||
The default `KEEP_ALIVE_TIMEOUT` value changed from 5 seconds to 120 seconds. It is of course still configurable, but this change should improve performance on long latency connections, where reconnecting is expensive, and better fits typical user flow browsing pages with longer-than-5-second intervals.
|
||||
|
||||
Sanic has historically used 5 second timeouts to quickly close idle connections. The chosen value of **120 seconds** is indeed larger than Nginx default of 75, and is the same value that Caddy server has by default.
|
||||
|
||||
Related to [#2531](https://github.com/sanic-org/sanic/issues/2531) and
|
||||
[#2681](https://github.com/sanic-org/sanic/issues/2681).
|
||||
|
||||
See [#2670](https://github.com/sanic-org/sanic/pull/2670).
|
||||
|
||||
### Set multiprocessing start method early
|
||||
|
||||
Due to how Python handles `multiprocessing`, it may be confusing to some users how to properly create synchronization primitives. This is due to how Sanic creates the `multiprocessing` context. This change sets the start method early so that any primitives created will properly attach to the correct context.
|
||||
|
||||
For most users, this should not be noticeable or impactful. But, it should make creation of something like this easier and work as expected.
|
||||
|
||||
```python
|
||||
from multiprocessing import Queue
|
||||
|
||||
@app.main_process_start
|
||||
async def main_process_start(app):
|
||||
app.shared_ctx.queue = Queue()
|
||||
```
|
||||
|
||||
See [#2776](https://github.com/sanic-org/sanic/pull/2776).
|
||||
|
||||
## Thank you
|
||||
|
||||
Thank you to everyone that participated in this release: :clap:
|
||||
|
||||
[@ahopkins](https://github.com/ahopkins)
|
||||
[@ChihweiLHBird](https://github.com/ChihweiLHBird)
|
||||
[@chuckds](https://github.com/chuckds)
|
||||
[@deounix](https://github.com/deounix)
|
||||
[@guacs](https://github.com/guacs)
|
||||
[@liamcoatman](https://github.com/liamcoatman)
|
||||
[@moshe742](https://github.com/moshe742)
|
||||
[@prryplatypus](https://github.com/prryplatypus)
|
||||
[@SaidBySolo](https://github.com/SaidBySolo)
|
||||
[@Thirumalai](https://github.com/Thirumalai)
|
||||
[@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/).
|
||||
Reference in New Issue
Block a user