Conversion of User Guide to the SHH stack (#2781)
This commit is contained in:
185
guide/content/en/release-notes/2022/v22.12.md
Normal file
185
guide/content/en/release-notes/2022/v22.12.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# Version 22.12
|
||||
|
||||
.. toc::
|
||||
|
||||
## Introduction
|
||||
|
||||
This is the final release of the version 22 [release cycle](../../org/policies.md#release-schedule). As such it is a **long-term support** release, and will be supported as stated in the [policies](../../org/policies.md#long-term-support-v-interim-releases).
|
||||
|
||||
## 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...
|
||||
|
||||
### 🚨 *BREAKING CHANGE* - Sanic Inspector is now an HTTP server
|
||||
|
||||
Sanic v22.9 introduced the [Inspector](./v22.9.md#inspector) to allow live inspection of a running Sanic instance. This feature relied upon opening a TCP socket and communicating over a custom protocol. That basic TCP protocol has been dropped in favor of running a full HTTP service in its place. [Learn more about the Inspector](../deployment/inspector.md).
|
||||
|
||||
The current release introduces a new HTTP server and a refreshed CLI experience. This enables several new features highlighted here. Perhaps the most significant change, however, is to move all of the Inspector's commands to a subparser on the CLI instance.
|
||||
|
||||
```
|
||||
$ sanic inspect --help
|
||||
|
||||
▄███ █████ ██ ▄█▄ ██ █ █ ▄██████████
|
||||
██ █ █ █ ██ █ █ ██
|
||||
▀███████ ███▄ ▀ █ █ ██ ▄ █ ██
|
||||
██ █████████ █ ██ █ █ ▄▄
|
||||
████ ████████▀ █ █ █ ██ █ ▀██ ███████
|
||||
|
||||
Optional
|
||||
========
|
||||
General:
|
||||
-h, --help show this help message and exit
|
||||
--host HOST, -H HOST Inspector host address [default 127.0.0.1]
|
||||
--port PORT, -p PORT Inspector port [default 6457]
|
||||
--secure, -s Whether to access the Inspector via TLS encryption
|
||||
--api-key API_KEY, -k API_KEY Inspector authentication key
|
||||
--raw Whether to output the raw response information
|
||||
|
||||
Subcommands:
|
||||
Run one or none of the below subcommands. Using inspect without a subcommand will fetch general information about the state of the application instance.
|
||||
|
||||
Or, you can optionally follow inspect with a subcommand. If you have created a custom Inspector instance, then you can run custom commands. See https://sanic.dev/en/guide/deployment/inspector.html for more details.
|
||||
|
||||
{reload,shutdown,scale,<custom>}
|
||||
reload Trigger a reload of the server workers
|
||||
shutdown Shutdown the application and all processes
|
||||
scale Scale the number of workers
|
||||
<custom> Run a custom command
|
||||
```
|
||||
|
||||
#### CLI remote access now available
|
||||
|
||||
The `host` and `port` of the Inspector are now explicitly exposed on the CLI as shown above. Previously in v22.9, they were inferred by reference to the application instance. Because of this change, it will be more possible to expose the Inspector on live production instances and access from a remote installation of the CLI.
|
||||
|
||||
For example, you can check your running production deployment from your local development machine.
|
||||
|
||||
```
|
||||
$ sanic inspect --host=1.2.3.4
|
||||
```
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
For **production** instances, make sure you are _using TLS and authentication_ described below.
|
||||
|
||||
#### TLS encryption now available
|
||||
|
||||
You can secure your remote Inspector access by providing a TLS certificate to encrypt the web traffic.
|
||||
|
||||
```python
|
||||
app.config.INSPECTOR_TLS_CERT = "/path/to/cert.pem"
|
||||
app.config.INSPECTOR_TLS_KEY = "/path/to/key.pem"
|
||||
```
|
||||
|
||||
To access an encrypted installation via the CLI, use the `--secure` flag.
|
||||
|
||||
```
|
||||
$ sanic inspect --secure
|
||||
```
|
||||
|
||||
#### Authentication now available
|
||||
|
||||
To control access to the remote Inspector, you can protect the endpoints using an API key.
|
||||
|
||||
```python
|
||||
app.config.INSPECTOR_API_KEY = "Super-Secret-200"
|
||||
```
|
||||
|
||||
To access a protected installation via the CLI, use the `--api-key` flag.
|
||||
|
||||
```
|
||||
$ sanic inspect --api-key=Super-Secret-200
|
||||
```
|
||||
|
||||
This is equivalent to the header: `Authorization: Bearer <KEY>`.
|
||||
|
||||
```
|
||||
$ curl http://localhost:6457 -H "Authorization: Bearer Super-Secret-200"
|
||||
```
|
||||
|
||||
### Scale number of running server workers
|
||||
|
||||
The Inspector is now capable of scaling the number of worker processes. For example, to scale to 3 replicas, use the following command:
|
||||
|
||||
```
|
||||
$ sanic inspect scale 3
|
||||
```
|
||||
|
||||
### Extend Inspector with custom commands
|
||||
|
||||
The Inspector is now fully extendable to allow for adding custom commands to the CLI. For more information see [Custom Commands](../deployment/inspector.md#custom-commands).
|
||||
|
||||
```
|
||||
$ sanic inspect foo --bar
|
||||
```
|
||||
|
||||
### Early worker exit on failure
|
||||
|
||||
The process manager shipped with v22.9 had a very short startup timeout. This was to protect against deadlock. This was increased to 30s, and a new mechanism has been added to fail early if there is a crash in a worker process on startup.
|
||||
|
||||
### Introduce `JSONResponse` with convenience methods to update a JSON response body
|
||||
|
||||
The `sanic.response.json` convenience method now returns a new subclass of `HTTPResponse` appropriately named: `JSONResponse`. This new type has some convenient methods for handling changes to a response body after its creation.
|
||||
|
||||
```python
|
||||
resp = json({"foo": "bar"})
|
||||
resp.update({"another": "value"})
|
||||
```
|
||||
|
||||
See [Returning JSON Data](../basics/response.md#returning-json-data) for more information.
|
||||
|
||||
### Updates to downstream requirements: `uvloop` and `websockets`
|
||||
|
||||
Minimum `uvloop` was set to `0.15.0`. Changes were added to make Sanic compliant with `websockets` version `11.0`.
|
||||
|
||||
### Force exit on 2nd `ctrl+c`
|
||||
|
||||
On supporting operating systems, the existing behavior is for Sanic server to try to perform a graceful shutdown when hitting `ctrl+c`. This new release will perform an immediate shutdown on subsequent `ctrl+c` after the initial shutdown has begun.
|
||||
|
||||
### Deprecations and Removals
|
||||
|
||||
1. *DEPRECATED* - The `--inspect*` commands introduced in v22.9 have been replaced with a new subcommand parser available as `inspect`. The flag versions will continue to operate until v23.3. You are encouraged to use the replacements. While this short deprecation period is a deviation from the standard two-cycles, we hope this change will be minimally disruptive.
|
||||
```
|
||||
OLD sanic ... --inspect
|
||||
NEW sanic ... inspect
|
||||
|
||||
OLD sanic ... --inspect-raw
|
||||
NEW sanic ... inspect --raw
|
||||
|
||||
OLD sanic ... --inspect-reload
|
||||
NEW sanic ... inspect reload
|
||||
|
||||
OLD sanic ... --inspect-shutdown
|
||||
NEW sanic ... inspect shutdown
|
||||
```
|
||||
|
||||
## News
|
||||
|
||||
The Sanic Community Organization will be headed by a new Steering Council for 2023. There are two returning and two new members.
|
||||
|
||||
[@ahopkins](https://github.com/ahopkins) *returning* \
|
||||
[@prryplatypus](https://github.com/prryplatypus) *returning* \
|
||||
[@sjsadowski](https://github.com/sjsadowski) *NEW* \
|
||||
[@Tronic](https://github.com/Tronic) *NEW*
|
||||
|
||||
The 2023 release managers are [@ahopkins](https://github.com/ahopkins) and [@sjsadowski](https://github.com/sjsadowski).
|
||||
|
||||
If you are interested in getting more involved with Sanic, contact us on the [Discord server](https://discord.gg/FARQzAEMAA).
|
||||
|
||||
## Thank you
|
||||
|
||||
Thank you to everyone that participated in this release: :clap:
|
||||
|
||||
[@aaugustin](https://github.com/aaugustin)
|
||||
[@ahopkins](https://github.com/ahopkins)
|
||||
[@ChihweiLHBird](https://github.com/ChihweiLHBird)
|
||||
[@kijk2869](https://github.com/kijk2869)
|
||||
[@LiraNuna](https://github.com/LiraNuna)
|
||||
[@prryplatypus](https://github.com/prryplatypus)
|
||||
[@sjsadowski](https://github.com/sjsadowski)
|
||||
[@todddialpad](https://github.com/todddialpad)
|
||||
[@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/).
|
||||
221
guide/content/en/release-notes/2022/v22.3.md
Normal file
221
guide/content/en/release-notes/2022/v22.3.md
Normal file
@@ -0,0 +1,221 @@
|
||||
# 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: `<foo:ext>`.
|
||||
|
||||
```python
|
||||
@app.get("/path/to/<filename:ext>")
|
||||
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/<filename=int:ext=jpg>")
|
||||
async def handler(request, filename, ext):
|
||||
...
|
||||
```
|
||||
|
||||
Some potential examples:
|
||||
|
||||
| definition | example | filename | extension |
|
||||
| --------------------------------- | ----------- | ----------- | ---------- |
|
||||
| \<file:ext> | page.txt | `"page"` | `"txt"` |
|
||||
| \<file:ext=jpg> | cat.jpg | `"cat"` | `"jpg"` |
|
||||
| \<file:ext=jpg\|png\|gif\|svg> | cat.jpg | `"cat"` | `"jpg"` |
|
||||
| <file=int:ext> | 123.txt | `123` | `"txt"` |
|
||||
| <file=int:ext=jpg\|png\|gif\|svg> | 123.svg | `123` | `"svg"` |
|
||||
| <file=float:ext=tar.gz> | 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 (`/<foo>` or `/<foo:str>`) 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: `/<foo:strorempty>`.
|
||||
|
||||
```python
|
||||
@app.get("/path/to/<foo:strorempty>")
|
||||
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 <SOME TOKEN HERE>
|
||||
Authorization: Bearer <SOME TOKEN HERE>
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
.. column::
|
||||
|
||||
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/)
|
||||
|
||||
.. column::
|
||||
|
||||

|
||||
|
||||
## 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/).
|
||||
159
guide/content/en/release-notes/2022/v22.6.md
Normal file
159
guide/content/en/release-notes/2022/v22.6.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# Version 22.6
|
||||
|
||||
.. toc::
|
||||
|
||||
## Introduction
|
||||
|
||||
This is the second release of the version 22 [release cycle](../../org/policies.md#release-schedule). Version 22 will be "finalized" in the December long-term support version release.
|
||||
|
||||
## 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...
|
||||
|
||||
### Automatic TLS setup in `DEBUG` mode
|
||||
|
||||
The Sanic server can automatically setup a TLS certificate using either [mkcert](https://github.com/FiloSottile/mkcert) or [trustme](https://github.com/python-trio/trustme). This certificate will enable `https://localhost` (or another local address) for local development environments. You must install either `mkcert` or `trustme` on your own for this to work.
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
$ sanic path.to.server:app --auto-tls --debug
|
||||
```
|
||||
|
||||
.. column::
|
||||
|
||||
```python
|
||||
app.run(debug=True, auto_tls=True)
|
||||
```
|
||||
|
||||
This feature is not available when running in `ASGI` mode, or in `PRODUCTION` mode. When running Sanic in production, you should be using a real TLS certificate either purchased through a legitimate vendor, or using [Let's Encrypt](https://letsencrypt.org/).
|
||||
|
||||
### HTTP/3 Server 🚀
|
||||
|
||||
In June 2022, the IETF finalized and published [RFC 9114](https://www.rfc-editor.org/rfc/rfc9114.html), the specification for HTTP/3. In short, HTTP/3 is a **very** different protocol than HTTP/1.1 and HTTP/2 because it implements HTTP over UDP instead of TCP. The new HTTP protocol promises faster webpage load times and solving some of the problems of the older standards. You are encouraged to [read more about](https://http3-explained.haxx.se/) this new web technology. You likely will need to install a [capable client](https://curl.se/docs/http3.html) as traditional tooling will not work.
|
||||
|
||||
Sanic server offers HTTP/3 support using [aioquic](https://github.com/aiortc/aioquic). This **must** be installed:
|
||||
|
||||
```
|
||||
pip install sanic aioquic
|
||||
```
|
||||
|
||||
```
|
||||
pip install sanic[http3]
|
||||
```
|
||||
|
||||
To start HTTP/3, you must explicitly request it when running your application.
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
$ sanic path.to.server:app --http=3
|
||||
```
|
||||
|
||||
```
|
||||
$ sanic path.to.server:app -3
|
||||
```
|
||||
|
||||
.. column::
|
||||
|
||||
```python
|
||||
app.run(version=3)
|
||||
```
|
||||
|
||||
To run both an HTTP/3 and HTTP/1.1 server simultaneously, you can use [application multi-serve](./v22.3.html#application-multi-serve) introduced in v22.3.
|
||||
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
$ sanic path.to.server:app --http=3 --http=1
|
||||
```
|
||||
|
||||
```
|
||||
$ sanic path.to.server:app -3 -1
|
||||
```
|
||||
|
||||
.. column::
|
||||
|
||||
```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](../how-to/tls.html) or use `mkcert` if in `DEBUG` mode. Currently, automatic TLS setup for HTTP/3 is not compatible with `trustme`.
|
||||
|
||||
**👶 This feature is being released as an *EARLY RELEASE FEATURE*.** It is **not** yet fully compliant with the HTTP/3 specification, lacking some features like [websockets](https://websockets.spec.whatwg.org/), [webtransport](https://w3c.github.io/webtransport/), and [push responses](https://http3-explained.haxx.se/en/h3/h3-push). Instead the intent of this release is to bring the existing HTTP request/response cycle towards feature parity with HTTP/3. Over the next several releases, more HTTP/3 features will be added and the API for it finalized.
|
||||
|
||||
### Consistent exception naming
|
||||
|
||||
Some of the Sanic exceptions have been renamed to be more compliant with standard HTTP response names.
|
||||
|
||||
- `InvalidUsage` >> `BadRequest`
|
||||
- `MethodNotSupported` >> `MethodNotAllowed`
|
||||
- `ContentRangeError` >> `RangeNotSatisfiable`
|
||||
|
||||
All old names have been aliased and will remain backwards compatible.
|
||||
|
||||
### Current request getter
|
||||
|
||||
Similar to the API to access an application (`Sanic.get_app()`), there is a new method for retrieving the current request when outside of a request handler.
|
||||
|
||||
```python
|
||||
from sanic import Request
|
||||
|
||||
Request.get_current()
|
||||
```
|
||||
|
||||
### Improved API support for setting cache control headers
|
||||
|
||||
The `file` response helper has some added parameters to make it easier to handle setting of the [Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) header.
|
||||
|
||||
```python
|
||||
file(
|
||||
...,
|
||||
last_modified=...,
|
||||
max_age=...,
|
||||
no_store=...,
|
||||
)
|
||||
```
|
||||
|
||||
### Custom `loads` function
|
||||
|
||||
Just like Sanic supports globally setting a custom `dumps`, you can now set a global custom `loads`.
|
||||
|
||||
```python
|
||||
from orjson import loads
|
||||
|
||||
app = Sanic("Test", loads=loads)
|
||||
```
|
||||
|
||||
### Deprecations and Removals
|
||||
|
||||
1. *REMOVED* - Applications may no longer opt-out of the application registry
|
||||
1. *REMOVED* - Custom exception handlers will no longer run after some part of an exception has been sent
|
||||
1. *REMOVED* - Fallback error formats cannot be set on the `ErrorHandler` and must **only** be set in the `Config`
|
||||
1. *REMOVED* - Setting a custom `LOGO` for startup is no longer allowed
|
||||
1. *REMOVED* - The old `stream` response convenience method has been removed
|
||||
1. *REMOVED* - `AsyncServer.init` is removed and no longer an alias of `AsyncServer.app.state.is_started`
|
||||
|
||||
|
||||
## Thank you
|
||||
|
||||
Thank you to everyone that participated in this release: :clap:
|
||||
|
||||
[@ahopkins](https://github.com/ahopkins)
|
||||
[@amitay87](https://github.com/amitay87 )
|
||||
[@ashleysommer](https://github.com/ashleysommer)
|
||||
[@azimovMichael](https://github.com/azimovMichael)
|
||||
[@ChihweiLHBird](https://github.com/ChihweiLHBird)
|
||||
[@kijk2869](https://github.com/kijk2869)
|
||||
[@prryplatypus](https://github.com/prryplatypus)
|
||||
[@SaidBySolo](https://github.com/SaidBySolo)
|
||||
[@sjsadowski](https://github.com/sjsadowski)
|
||||
[@timmo001](https://github.com/timmo001)
|
||||
[@zozzz](https://github.com/zozzz)
|
||||
|
||||
---
|
||||
|
||||
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/).
|
||||
325
guide/content/en/release-notes/2022/v22.9.md
Normal file
325
guide/content/en/release-notes/2022/v22.9.md
Normal file
@@ -0,0 +1,325 @@
|
||||
# Version 22.9
|
||||
|
||||
.. toc::
|
||||
|
||||
## Introduction
|
||||
|
||||
This is the third release of the version 22 [release cycle](../../org/policies.md#release-schedule). Version 22 will be "finalized" in the December long-term support version release.
|
||||
|
||||
## 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...
|
||||
|
||||
### ⚠ *IMPORTANT* - New worker manager 🚀
|
||||
|
||||
Sanic server has been overhauled to provide more consistency and flexbility in how it operates. More details about the motivations are outlined in [PR #2499](https://github.com/sanic-org/sanic/pull/2499) and discussed in a live stream [discussion held on YouTube](https://youtu.be/m8HCO8NK7HE).
|
||||
|
||||
This **does NOT apply** to Sanic in ASGI mode
|
||||
|
||||
#### Overview of the changes
|
||||
|
||||
- The worker servers will **always** run in a child process.
|
||||
- Previously this could change depending upon one versus many workers, and the usage or not of the reloader. This should lead to much more predictable development environments that more closely match their production counterparts.
|
||||
- Multi-workers is **now supported on Windows**.
|
||||
- This was impossible because Sanic relied upon the `multiprocessing` module using `fork`, which is not available on Windows.
|
||||
- Now, Sanic will always use `spawn`. This does have some noticeable differences, particularly if you are running Sanic in the global scope with `app.run` (see below re: upgrade issues).
|
||||
- The application instance now has a new `multiplexer` object that can be used to restart one or many workers. This could, for example, be triggered by a request.
|
||||
- There is a new Inspector that can provide details on the state of your server.
|
||||
- Sanic worker manager can run arbitrary processes.
|
||||
- This allows developers to add any process they want from within Sanic.
|
||||
- Possible use cases:
|
||||
- Health monitor, see [Sanic Extensions]()
|
||||
- Logging queue, see [Sanic Extensions]()
|
||||
- Background worker queue in a seperate process
|
||||
- Running another application, like a bot
|
||||
- There is a new listener called: `main_process_ready`. It really should only be used for adding arbitrary processes to Sanic.
|
||||
- Passing shared objects between workers.
|
||||
- Python does allow some types of objects to share state between processes, whether through shared memory, pipes, etc.
|
||||
- Sanic will now allow these types of object to be shared on the `app.shared_ctx` object.
|
||||
- Since this feature relies upon Pythons `multiprocessing` library, it obviously will only work to share state between Sanic worker instances that are instantiated from the same execution. This is *not* meant to provide an API for horizontal scaling across multiple machines for example.
|
||||
|
||||
#### Adding a shared context object
|
||||
|
||||
To share an object between worker processes, it *MUST* be assigned inside of the `main_process_start` listener.
|
||||
|
||||
```python
|
||||
from multiprocessing import Queue
|
||||
|
||||
@app.main_process_start
|
||||
async def main_process_start(app):
|
||||
app.shared_ctx.queue = Queue()
|
||||
```
|
||||
|
||||
All objects on `shared_ctx` will be available now within each worker process.
|
||||
|
||||
```python
|
||||
@app.before_server_starts
|
||||
async def before_server_starts(app):
|
||||
assert isinstance(app.shared_ctx.queue, Queue)
|
||||
|
||||
@app.on_request
|
||||
async def on_request(request):
|
||||
assert isinstance(request.app.shared_ctx.queue, Queue)
|
||||
|
||||
@app.get("/")
|
||||
async def handler(request):
|
||||
assert isinstance(request.app.shared_ctx.queue, Queue)
|
||||
```
|
||||
|
||||
*NOTE: Sanic will not stop you from registering an unsafe object, but may warn you. Be careful not to just add a regular list object, for example, and expect it to work. You should have an understanding of how to share state between processes.*
|
||||
|
||||
#### Running arbitrary processes
|
||||
|
||||
Sanic can run any arbitrary process for you. It should be capable of being stopped by a `SIGINT` or `SIGTERM` OS signal.
|
||||
|
||||
These processes should be registered inside of the `main_process_ready` listener.
|
||||
|
||||
```python
|
||||
@app.main_process_ready
|
||||
async def ready(app: Sanic, _):
|
||||
app.manager.manage("MyProcess", my_process, {"foo": "bar"})
|
||||
# app.manager.manage(<name>, <callable>, <kwargs>)
|
||||
```
|
||||
|
||||
#### Inspector
|
||||
|
||||
Sanic ships with an optional Inspector, which is a special process that allows for the CLI to inspect the running state of an application and issue commands. It currently will only work if the CLI is being run on the same machine as the Sanic instance.
|
||||
|
||||
```
|
||||
sanic path.to:app --inspect
|
||||
```
|
||||
|
||||

|
||||
|
||||
The new CLI commands are:
|
||||
|
||||
```
|
||||
--inspect Inspect the state of a running instance, human readable
|
||||
--inspect-raw Inspect the state of a running instance, JSON output
|
||||
--trigger-reload Trigger worker processes to reload
|
||||
--trigger-shutdown Trigger all processes to shutdown
|
||||
```
|
||||
|
||||
This is not enabled by default. In order to have it available, you must opt in:
|
||||
|
||||
```python
|
||||
app.config.INSPECTOR = True
|
||||
```
|
||||
|
||||
*Note: [Sanic Extensions]() provides a [custom request](../basics/app.md#custom-requests) class that will add a request counter to the server state.
|
||||
|
||||
#### Application multiplexer
|
||||
|
||||
Many of the same information and functionality is available on the application instance itself. There is a new `multiplexer` object on the application instance that has the ability to restart one or more workers, and fetch information about the current state.
|
||||
|
||||
You can access it as `app.multiplexer`, or more likely by its short alias `app.m`.
|
||||
|
||||
```python
|
||||
@app.on_request
|
||||
async def print_state(request: Request):
|
||||
print(request.app.m.state)
|
||||
```
|
||||
|
||||
#### Potential upgrade issues
|
||||
|
||||
Because of the switch from `fork` to `spawn`, if you try running the server in the global scope you will receive an error. If you see something like this:
|
||||
|
||||
```
|
||||
sanic.exceptions.ServerError: Sanic server could not start: [Errno 98] Address already in use.
|
||||
This may have happened if you are running Sanic in the global scope and not inside of a `if __name__ == "__main__"` block.
|
||||
```
|
||||
|
||||
... then the change is simple. Make sure `app.run` is inside a block.
|
||||
|
||||
```python
|
||||
if __name__ == "__main__":
|
||||
app.run(port=9999, dev=True)
|
||||
```
|
||||
|
||||
#### Opting out of the new functionality
|
||||
|
||||
If you would like to run Sanic without the new process manager, you may easily use the legacy runners. Please note that support for them **will be removed** in the future. A date has not yet been set, but will likely be sometime in 2023.
|
||||
|
||||
To opt out of the new server and use the legacy, choose the appropriate method depending upon how you run Sanic:
|
||||
|
||||
.. column::
|
||||
|
||||
If you use the CLI...
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
sanic path.to:app --legacy
|
||||
```
|
||||
|
||||
|
||||
.. column::
|
||||
|
||||
If you use `app.run`...
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
app.run(..., legacy=True)
|
||||
```
|
||||
|
||||
|
||||
.. column::
|
||||
|
||||
If you `app.prepare`...
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
app.prepare(...)
|
||||
Sanic.serve_legacy()
|
||||
```
|
||||
|
||||
Similarly, you can force Sanic to run in a single process. This however means there will not be any access to the auto-reloader.
|
||||
|
||||
.. column::
|
||||
|
||||
If you use the CLI...
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
sanic path.to:app --single-process
|
||||
```
|
||||
|
||||
|
||||
.. column::
|
||||
|
||||
If you use `app.run`...
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
app.run(..., single_process=True)
|
||||
```
|
||||
|
||||
|
||||
.. column::
|
||||
|
||||
If you `app.prepare`...
|
||||
|
||||
.. column::
|
||||
|
||||
```
|
||||
app.prepare(...)
|
||||
Sanic.serve_single()
|
||||
```
|
||||
|
||||
### Middleware priority
|
||||
|
||||
Middleware is executed in an order based upon when it was defined. Request middleware are executed in sequence and response middleware in reverse. This could have an unfortunate impact if your ordering is strictly based upon import ordering with global variables for example.
|
||||
|
||||
A new addition is to break-out of the strict construct and allow a priority to be assigned to a middleware. The higher the number for a middleware definition, the earlier in the sequence it will be executed. This applies to **both** request and response middleware.
|
||||
|
||||
```python
|
||||
@app.on_request
|
||||
async def low_priority(_):
|
||||
...
|
||||
|
||||
@app.on_request(priority=10)
|
||||
async def high_priority(_):
|
||||
...
|
||||
```
|
||||
|
||||
In the above example, even though `low_priority` is defined first, `high_priority` will run first.
|
||||
|
||||
### Custom `loads` function
|
||||
|
||||
Sanic has supported the ability to add a [custom `dumps` function](https://sanic.readthedocs.io/en/stable/sanic/api/app.html#sanic.app.Sanic) when instantiating an app. The same functionality has been extended to `loads`, which will be used when deserializing.
|
||||
|
||||
```python
|
||||
from json import loads
|
||||
|
||||
Sanic("Test", loads=loads)
|
||||
```
|
||||
|
||||
### Websocket objects are now iterable
|
||||
|
||||
Rather than calling `recv` in a loop on a `Websocket` object, you can iterate on it in a `for` loop.
|
||||
|
||||
```python
|
||||
from sanic import Request, Websocket
|
||||
|
||||
@app.websocket("/ws")
|
||||
async def ws_echo_handler(request: Request, ws: Websocket):
|
||||
async for msg in ws:
|
||||
await ws.send(msg)
|
||||
```
|
||||
|
||||
### Appropriately respond with 304 on static files
|
||||
|
||||
When serving a static file, the Sanic server can respond appropriately to a request with `If-Modified-Since` using a `304` response instead of resending a file.
|
||||
|
||||
### Two new signals to wrap handler execution
|
||||
|
||||
Two new [signals](../advanced/signals.md) have been added that wrap the execution of a request handler.
|
||||
|
||||
- `http.handler.before` - runs after request middleware but before the route handler
|
||||
- `http.handler.after` - runs after the route handler
|
||||
- In *most* circumstances, this also means that it will run before response middleware. However, if you call `request.respond` from inside of a route handler, then your middleware will come first
|
||||
|
||||
### New Request properties for HTTP method information
|
||||
|
||||
The HTTP specification defines which HTTP methods are: safe, idempotent, and cacheable. New properties have been added that will respond with a boolean flag to help identify the request property based upon the method.
|
||||
|
||||
```python
|
||||
request.is_safe
|
||||
request.is_idempotent
|
||||
request.is_cacheable
|
||||
```
|
||||
|
||||
### 🚨 *BREAKING CHANGE* - Improved cancel request exception
|
||||
|
||||
In prior version of Sanic, if a `CancelledError` was caught it could bubble up and cause the server to respond with a `503`. This is not always the desired outcome, and it prevented the usage of that error in other circumstances. As a result, Sanic will now use a subclass of `CancelledError` called: `RequestCancelled` for this functionality. It likely should have little impact unless you were explicitly relying upon the old behavior.
|
||||
|
||||
For more details on the specifics of these properties, checkout the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods).
|
||||
|
||||
### New deprecation warning filter
|
||||
|
||||
You can control the level of deprecation warnings from Sanic using [standard library warning filter values](https://docs.python.org/3/library/warnings.html#the-warnings-filter). Default is `"once"`.
|
||||
|
||||
```python
|
||||
app.config.DEPRECATION_FILTER = "ignore"
|
||||
```
|
||||
|
||||
### Deprecations and Removals
|
||||
|
||||
1. *DEPRECATED* - Duplicate route names have been deprecated and will be removed in v23.3
|
||||
1. *DEPRECATED* - Registering duplicate exception handlers has been deprecated and will be removed in v23.3
|
||||
1. *REMOVED* - `route.ctx` not set by Sanic, and is a blank object for users, therefore ...
|
||||
- `route.ctx.ignore_body` >> `route.extra.ignore_body`
|
||||
- `route.ctx.stream` >> `route.extra.stream`
|
||||
- `route.ctx.hosts` >> `route.extra.hosts`
|
||||
- `route.ctx.static` >> `route.extra.static`
|
||||
- `route.ctx.error_format` >> `route.extra.error_format`
|
||||
- `route.ctx.websocket` >> `route.extra.websocket`
|
||||
1. *REMOVED* - `app.debug` is READ-ONLY
|
||||
1. *REMOVED* - `app.is_running` removed
|
||||
1. *REMOVED* - `app.is_stopping` removed
|
||||
1. *REMOVED* - `Sanic._uvloop_setting` removed
|
||||
1. *REMOVED* - Prefixed environment variables will be ignored if not uppercase
|
||||
|
||||
## Thank you
|
||||
|
||||
Thank you to everyone that participated in this release: :clap:
|
||||
|
||||
[@ahopkins](https://github.com/ahopkins)
|
||||
[@azimovMichael](https://github.com/azimovMichael)
|
||||
[@ChihweiLHBird](https://github.com/ChihweiLHBird)
|
||||
[@huntzhan](https://github.com/huntzhan)
|
||||
[@monosans](https://github.com/monosans)
|
||||
[@prryplatypus](https://github.com/prryplatypus)
|
||||
[@SaidBySolo](https://github.com/SaidBySolo)
|
||||
[@seemethere](https://github.com/seemethere)
|
||||
[@sjsadowski](https://github.com/sjsadowski)
|
||||
[@timgates42](https://github.com/timgates42)
|
||||
[@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