mirror of
https://github.com/actix/actix-website
synced 2024-11-27 10:02:57 +01:00
fmt
This commit is contained in:
parent
6b4fe2882b
commit
57e2b2bd62
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"singleQuote": true,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": ["*.md"],
|
|
||||||
"options": {
|
|
||||||
"proseWrap": "always",
|
|
||||||
"printWidth": 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
6
.prettierrc.yaml
Normal file
6
.prettierrc.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
singleQuote: true
|
||||||
|
tabWidth: 2
|
||||||
|
overrides:
|
||||||
|
- files: ["*.md"]
|
||||||
|
options:
|
||||||
|
proseWrap: never
|
12
README.md
12
README.md
@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
Building the website depends on [Hugo]. So, first make sure
|
Building the website depends on [Hugo]. So, first make sure that you have it installed. If on macOS and using [Homebrew], run the following:
|
||||||
that you have it installed. If on macOS and using [Homebrew], run the following:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew update
|
brew update
|
||||||
@ -36,11 +35,10 @@ mmdc -i connection_overview.mmd -o connection_overview.svg
|
|||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
Pretty murky. Right now a massive clone of the tokio website. Will get this
|
Pretty murky. Right now a massive clone of the tokio website. Will get this figured out as we go along.
|
||||||
figured out as we go along.
|
|
||||||
|
|
||||||
<!-- LINKS -->
|
<!-- LINKS -->
|
||||||
|
|
||||||
[Hugo]: https://gohugo.io
|
[hugo]: https://gohugo.io
|
||||||
[Homebrew]: https://brew.sh
|
[homebrew]: https://brew.sh
|
||||||
[Mermaid CLI]: https://github.com/mermaidjs/mermaid.cli
|
[mermaid cli]: https://github.com/mermaidjs/mermaid.cli
|
||||||
|
@ -7,8 +7,7 @@ description: Browse and download the sources
|
|||||||
|
|
||||||
The Actix ecosystem is fully open source on our GitHub organization [@actix](https://github.com/actix).
|
The Actix ecosystem is fully open source on our GitHub organization [@actix](https://github.com/actix).
|
||||||
|
|
||||||
Here are the most important projects and the link to their github repositories
|
Here are the most important projects and the link to their github repositories and related resources:
|
||||||
and related resources:
|
|
||||||
|
|
||||||
- [actix-web](https://github.com/actix/actix-web), ([API docs](https://docs.rs/actix-web))
|
- [actix-web](https://github.com/actix/actix-web), ([API docs](https://docs.rs/actix-web))
|
||||||
- [actix-extras crates](https://github.com/actix/actix-extras)
|
- [actix-extras crates](https://github.com/actix/actix-extras)
|
||||||
|
@ -5,12 +5,8 @@ description: The best things in life are to be shared
|
|||||||
|
|
||||||
# Join us
|
# Join us
|
||||||
|
|
||||||
Want to talk to others about questions? The Actix Web [Discord server](https://discord.gg/NWpN5mmg3x)
|
Want to talk to others about questions? The Actix Web [Discord server](https://discord.gg/NWpN5mmg3x) is the best starting point. We also have a [Gitter room](https://gitter.im/actix/actix-web).
|
||||||
is the best starting point. We also have a [Gitter room](https://gitter.im/actix/actix-web).
|
|
||||||
|
|
||||||
If you think you found a bug it's best to file an issue directly on the repo.
|
If you think you found a bug it's best to file an issue directly on the repo. [actix/actix-web](https://github.com/actix/actix-web) for the web framework. [actix/actix](https://github.com/actix/actix) for issues with the actor framework
|
||||||
[actix/actix-web](https://github.com/actix/actix-web) for the web framework.
|
|
||||||
[actix/actix](https://github.com/actix/actix) for issues with the actor framework
|
|
||||||
|
|
||||||
We're a welcoming community so don't be afraid to engage. Interactions are
|
We're a welcoming community so don't be afraid to engage. Interactions are [governed by our code of conduct](coc/).
|
||||||
[governed by our code of conduct](coc/).
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Contributor Covenant Code of Conduct
|
title: Contributor Covenant Code of Conduct
|
||||||
description:
|
description:
|
||||||
---
|
---
|
||||||
|
|
||||||
# Our Pledge
|
# Our Pledge
|
||||||
@ -11,19 +11,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
|
|||||||
|
|
||||||
Examples of behavior that contributes to creating a positive environment include:
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
- Using welcoming and inclusive language
|
||||||
* Being respectful of differing viewpoints and experiences
|
- Being respectful of differing viewpoints and experiences
|
||||||
* Gracefully accepting constructive criticism
|
- Gracefully accepting constructive criticism
|
||||||
* Focusing on what is best for the community
|
- Focusing on what is best for the community
|
||||||
* Showing empathy towards other community members
|
- Showing empathy towards other community members
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
- Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
# Our Responsibilities
|
# Our Responsibilities
|
||||||
|
|
||||||
|
@ -9,14 +9,9 @@ weight: 10
|
|||||||
|
|
||||||
# Welcome to Actix
|
# Welcome to Actix
|
||||||
|
|
||||||
Actix Web lets you quickly and confidently develop web services in Rust and this guide get you going
|
Actix Web lets you quickly and confidently develop web services in Rust and this guide will get you going in no time.
|
||||||
in no time.
|
|
||||||
|
|
||||||
The documentation on this website focusses primarily on the Actix Web framework. For information
|
The documentation on this website focusses primarily on the Actix Web framework. For information about the actor framework called Actix, check out the [Actix book][actix-book] (or the lower level [actix API docs][actix-docs]). Otherwise, head on to the [getting started guide][getting-started]. If you already know your way around and you need specific information you might want to read the [actix-web API docs][actix-web-docs].
|
||||||
about the actor framework called Actix, check out the [Actix book][actix-book] (or the lower level
|
|
||||||
[actix API docs][actix-docs]). Otherwise, head on to the [getting started guide][getting-started].
|
|
||||||
If you already know your way around and you need specific information you might want to read the
|
|
||||||
[actix-web API docs][actix-web-docs].
|
|
||||||
|
|
||||||
[getting-started]: ./getting-started
|
[getting-started]: ./getting-started
|
||||||
[actix-web-docs]: https://docs.rs/actix-web
|
[actix-web-docs]: https://docs.rs/actix-web
|
||||||
|
@ -6,33 +6,23 @@ weight: 140
|
|||||||
|
|
||||||
# Writing an Application
|
# Writing an Application
|
||||||
|
|
||||||
`actix-web` provides various primitives to build web servers and applications with Rust. It provides
|
`actix-web` provides various primitives to build web servers and applications with Rust. It provides routing, middleware, pre-processing of requests, post-processing of responses, etc.
|
||||||
routing, middleware, pre-processing of requests, post-processing of responses, etc.
|
|
||||||
|
|
||||||
All `actix-web` servers are built around the [`App`][app] instance. It is used for registering
|
All `actix-web` servers are built around the [`App`][app] instance. It is used for registering routes for resources and middleware. It also stores application state shared across all handlers within the same scope.
|
||||||
routes for resources and middleware. It also stores application state shared across all handlers
|
|
||||||
within the same scope.
|
|
||||||
|
|
||||||
An application's [`scope`][scope] acts as a namespace for all routes, i.e. all routes for a specific
|
An application's [`scope`][scope] acts as a namespace for all routes, i.e. all routes for a specific application scope have the same url path prefix. The application prefix always contains a leading "/" slash. If a supplied prefix does not contain leading slash, it is automatically inserted. The prefix should consist of value path segments.
|
||||||
application scope have the same url path prefix. The application prefix always contains a leading
|
|
||||||
"/" slash. If a supplied prefix does not contain leading slash, it is automatically inserted. The
|
|
||||||
prefix should consist of value path segments.
|
|
||||||
|
|
||||||
> For an application with scope `/app`, any request with the paths `/app`, `/app/`, or `/app/test`
|
> For an application with scope `/app`, any request with the paths `/app`, `/app/`, or `/app/test` would match; however, the path `/application` would not match.
|
||||||
> would match; however, the path `/application` would not match.
|
|
||||||
|
|
||||||
{{< include-example example="application" file="app.rs" section="setup" >}}
|
{{< include-example example="application" file="app.rs" section="setup" >}}
|
||||||
|
|
||||||
In this example, an application with the `/app` prefix and an `index.html` resource is created. This
|
In this example, an application with the `/app` prefix and an `index.html` resource is created. This resource is available through the `/app/index.html` url.
|
||||||
resource is available through the `/app/index.html` url.
|
|
||||||
|
|
||||||
> For more information, check the [URL Dispatch][usingappprefix] section.
|
> For more information, check the [URL Dispatch][usingappprefix] section.
|
||||||
|
|
||||||
## State
|
## State
|
||||||
|
|
||||||
Application state is shared with all routes and resources within the same scope. State can be
|
Application state is shared with all routes and resources within the same scope. State can be accessed with the [`web::Data<T>`][data] extractor where `T` is the type of the state. State is also accessible for middleware.
|
||||||
accessed with the [`web::Data<T>`][data] extractor where `T` is the type of the state. State is also
|
|
||||||
accessible for middleware.
|
|
||||||
|
|
||||||
Let's write a simple application and store the application name in the state:
|
Let's write a simple application and store the application name in the state:
|
||||||
|
|
||||||
@ -46,16 +36,11 @@ Any number of state types could be registered within the application.
|
|||||||
|
|
||||||
## Shared Mutable State
|
## Shared Mutable State
|
||||||
|
|
||||||
`HttpServer` accepts an application factory rather than an application instance. An `HttpServer`
|
`HttpServer` accepts an application factory rather than an application instance. An `HttpServer` constructs an application instance for each thread. Therefore, application data must be constructed multiple times. If you want to share data between different threads, a shareable object should be used, e.g. `Send` + `Sync`.
|
||||||
constructs an application instance for each thread. Therefore, application data must be constructed
|
|
||||||
multiple times. If you want to share data between different threads, a shareable object should be
|
|
||||||
used, e.g. `Send` + `Sync`.
|
|
||||||
|
|
||||||
Internally, [`web::Data`][data] uses `Arc`. Thus, in order to avoid creating two `Arc`s, we should
|
Internally, [`web::Data`][data] uses `Arc`. Thus, in order to avoid creating two `Arc`s, we should create our Data before registering it using [`App::app_data()`][appdata].
|
||||||
create our Data before registering it using [`App::app_data()`][appdata].
|
|
||||||
|
|
||||||
In the following example, we will write an application with mutable, shared state. First, we define
|
In the following example, we will write an application with mutable, shared state. First, we define our state and create our handler:
|
||||||
our state and create our handler:
|
|
||||||
|
|
||||||
{{< include-example example="application" file="mutable_state.rs" section="setup_mutable" >}}
|
{{< include-example example="application" file="mutable_state.rs" section="setup_mutable" >}}
|
||||||
|
|
||||||
@ -65,39 +50,25 @@ and register the data in an `App`:
|
|||||||
|
|
||||||
## Using an Application Scope to Compose Applications
|
## Using an Application Scope to Compose Applications
|
||||||
|
|
||||||
The [`web::scope()`][webscope] method allows setting a resource group prefix. This scope represents
|
The [`web::scope()`][webscope] method allows setting a resource group prefix. This scope represents a resource prefix that will be prepended to all resource patterns added by the resource configuration. This can be used to help mount a set of routes at a different location than the original author intended while still maintaining the same resource names.
|
||||||
a resource prefix that will be prepended to all resource patterns added by the resource
|
|
||||||
configuration. This can be used to help mount a set of routes at a different location than the
|
|
||||||
original author intended while still maintaining the same resource names.
|
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
{{< include-example example="application" file="scope.rs" section="scope" >}}
|
{{< include-example example="application" file="scope.rs" section="scope" >}}
|
||||||
|
|
||||||
In the above example, the `show_users` route will have an effective route pattern of `/users/show`
|
In the above example, the `show_users` route will have an effective route pattern of `/users/show` instead of `/show` because the application's scope argument will be prepended to the pattern. The route will then only match if the URL path is `/users/show`, and when the [`HttpRequest.url_for()`][urlfor] function is called with the route name `show_users`, it will generate a URL with that same path.
|
||||||
instead of `/show` because the application's scope argument will be prepended to the pattern. The
|
|
||||||
route will then only match if the URL path is `/users/show`, and when the
|
|
||||||
[`HttpRequest.url_for()`][urlfor] function is called with the route name `show_users`, it will
|
|
||||||
generate a URL with that same path.
|
|
||||||
|
|
||||||
## Application guards and virtual hosting
|
## Application guards and virtual hosting
|
||||||
|
|
||||||
You can think of a guard as a simple function that accepts a _request_ object reference and returns
|
You can think of a guard as a simple function that accepts a _request_ object reference and returns _true_ or _false_. Formally, a guard is any object that implements the [`Guard`][guardtrait] trait. Actix-web provides several guards. You can check the [functions section][guardfuncs] of the API docs.
|
||||||
_true_ or _false_. Formally, a guard is any object that implements the [`Guard`][guardtrait] trait.
|
|
||||||
Actix-web provides several guards. You can check the [functions section][guardfuncs] of the API
|
|
||||||
docs.
|
|
||||||
|
|
||||||
One of the provided guards is [`Header`][guardheader]. It can be used as a filter based on request
|
One of the provided guards is [`Header`][guardheader]. It can be used as a filter based on request header information.
|
||||||
header information.
|
|
||||||
|
|
||||||
{{< include-example example="application" file="vh.rs" section="vh" >}}
|
{{< include-example example="application" file="vh.rs" section="vh" >}}
|
||||||
|
|
||||||
# Configure
|
# Configure
|
||||||
|
|
||||||
For simplicity and reusability both [`App`][appconfig] and [`web::Scope`][webscopeconfig] provide
|
For simplicity and reusability both [`App`][appconfig] and [`web::Scope`][webscopeconfig] provide the `configure` method. This function is useful for moving parts of the configuration to a different module or even library. For example, some of the resource's configuration could be moved to a different module.
|
||||||
the `configure` method. This function is useful for moving parts of the configuration to a different
|
|
||||||
module or even library. For example, some of the resource's configuration could be moved to a
|
|
||||||
different module.
|
|
||||||
|
|
||||||
{{< include-example example="application" file="config.rs" section="config" >}}
|
{{< include-example example="application" file="config.rs" section="config" >}}
|
||||||
|
|
||||||
|
@ -6,8 +6,7 @@ weight: 1000
|
|||||||
|
|
||||||
# Auto-Reloading Development Server
|
# Auto-Reloading Development Server
|
||||||
|
|
||||||
During development it can be very handy to have cargo automatically recompile the code on changes.
|
During development it can be very handy to have cargo automatically recompile the code on changes. This can be accomplished very easily by using [`cargo-watch`].
|
||||||
This can be accomplished very easily by using [`cargo-watch`].
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo watch -x 'run --bin app'
|
cargo watch -x 'run --bin app'
|
||||||
@ -15,8 +14,6 @@ cargo watch -x 'run --bin app'
|
|||||||
|
|
||||||
## Historical Note
|
## Historical Note
|
||||||
|
|
||||||
An old version of this page recommended using a combination of systemfd and listenfd, but this has
|
An old version of this page recommended using a combination of systemfd and listenfd, but this has many gotchas and was difficult to integrate properly, especially when part of a broader development workflow. We consider [`cargo-watch`] to be sufficient for auto-reloading purposes.
|
||||||
many gotchas and was difficult to integrate properly, especially when part of a broader development
|
|
||||||
workflow. We consider [`cargo-watch`] to be sufficient for auto-reloading purposes.
|
|
||||||
|
|
||||||
[`cargo-watch`]: https://github.com/passcod/cargo-watch
|
[`cargo-watch`]: https://github.com/passcod/cargo-watch
|
||||||
|
@ -4,12 +4,11 @@ menu: docs_architecture
|
|||||||
weight: 1030
|
weight: 1030
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
# Architecture overview
|
# Architecture overview
|
||||||
|
|
||||||
After Server has started listening to all sockets, [`Accept`][Accept] and [`Worker`][Worker] are two main loops responsible for processing incoming client connections.
|
After Server has started listening to all sockets, [`Accept`][accept] and [`Worker`][worker] are two main loops responsible for processing incoming client connections.
|
||||||
|
|
||||||
Once connection accepted Application level protocol processing happens in a protocol specific [`Dispatcher`][Dispatcher] loop spawned from [`Worker`][Worker].
|
Once connection accepted Application level protocol processing happens in a protocol specific [`Dispatcher`][dispatcher] loop spawned from [`Worker`][worker].
|
||||||
|
|
||||||
Please note, below diagrams are outlining happy-path scenarios only.
|
Please note, below diagrams are outlining happy-path scenarios only.
|
||||||
|
|
||||||
@ -19,13 +18,13 @@ Once connection accepted Application level protocol processing happens in a prot
|
|||||||
|
|
||||||
![](/img/diagrams/connection_accept.svg)
|
![](/img/diagrams/connection_accept.svg)
|
||||||
|
|
||||||
Most of code implementation resides in [`actix-server`][server] crate for struct [`Accept`][Accept].
|
Most of code implementation resides in [`actix-server`][server] crate for struct [`Accept`][accept].
|
||||||
|
|
||||||
## Worker loop in more detail
|
## Worker loop in more detail
|
||||||
|
|
||||||
![](/img/diagrams/connection_worker.svg)
|
![](/img/diagrams/connection_worker.svg)
|
||||||
|
|
||||||
Most of code implementation resides in [`actix-server`][server] crate for struct [`Worker`][Worker].
|
Most of code implementation resides in [`actix-server`][server] crate for struct [`Worker`][worker].
|
||||||
|
|
||||||
## Request loop roughly
|
## Request loop roughly
|
||||||
|
|
||||||
@ -33,10 +32,9 @@ Most of code implementation resides in [`actix-server`][server] crate for struct
|
|||||||
|
|
||||||
Most of code implementation for request loop resides in [`actix-web`][web] and [`actix-http`][http] crates.
|
Most of code implementation for request loop resides in [`actix-web`][web] and [`actix-http`][http] crates.
|
||||||
|
|
||||||
|
|
||||||
[server]: https://crates.io/crates/actix-server
|
[server]: https://crates.io/crates/actix-server
|
||||||
[web]: https://crates.io/crates/actix-web
|
[web]: https://crates.io/crates/actix-web
|
||||||
[http]: https://crates.io/crates/actix-http
|
[http]: https://crates.io/crates/actix-http
|
||||||
[Accept]: https://github.com/actix/actix-net/blob/master/actix-server/src/accept.rs
|
[accept]: https://github.com/actix/actix-net/blob/master/actix-server/src/accept.rs
|
||||||
[Worker]: https://github.com/actix/actix-net/blob/master/actix-server/src/worker.rs
|
[worker]: https://github.com/actix/actix-net/blob/master/actix-server/src/worker.rs
|
||||||
[Dispatcher]: https://github.com/actix/actix-web/blob/master/actix-http/src/h1/dispatcher.rs
|
[dispatcher]: https://github.com/actix/actix-web/blob/master/actix-http/src/h1/dispatcher.rs
|
||||||
|
@ -14,34 +14,23 @@ We have several example projects showing use of async database adapters:
|
|||||||
|
|
||||||
# Diesel
|
# Diesel
|
||||||
|
|
||||||
The current version of Diesel (v1) does not support asynchronous operations, so it is important to
|
The current version of Diesel (v1) does not support asynchronous operations, so it is important to use the [`web::block`][web-block] function to offload your database operations to the Actix runtime thread-pool.
|
||||||
use the [`web::block`][web-block] function to offload your database operations to the Actix runtime
|
|
||||||
thread-pool.
|
|
||||||
|
|
||||||
You can create action functions that correspond to all the operations your app will perform on the
|
You can create action functions that correspond to all the operations your app will perform on the database.
|
||||||
database.
|
|
||||||
|
|
||||||
{{< include-example example="databases" file="main.rs" section="handler" >}}
|
{{< include-example example="databases" file="main.rs" section="handler" >}}
|
||||||
|
|
||||||
Now you should set up the database pool using a crate such as `r2d2`, which makes many DB
|
Now you should set up the database pool using a crate such as `r2d2`, which makes many DB connections available to your app. This means that multiple handlers can manipulate the DB at the same time, and still accept new connections. Simply, the pool in your app state. (In this case, it's beneficial not to use a state wrapper struct because the pool handles shared access for you.)
|
||||||
connections available to your app. This means that multiple handlers can manipulate the DB at the
|
|
||||||
same time, and still accept new connections. Simply, the pool in your app state. (In this case, it's
|
|
||||||
beneficial not to use a state wrapper struct because the pool handles shared access for you.)
|
|
||||||
|
|
||||||
{{< include-example example="databases" file="main.rs" section="main" >}}
|
{{< include-example example="databases" file="main.rs" section="main" >}}
|
||||||
|
|
||||||
Now, in a request handler, use the `Data<T>` extractor to get the pool from app state and get a
|
Now, in a request handler, use the `Data<T>` extractor to get the pool from app state and get a connection from it. This provides an owned database connection that can be passed into a [`web::block`][web-block] closure. Then just call the action function with the necessary arguments and `.await` the result.
|
||||||
connection from it. This provides an owned database connection that can be passed into a
|
|
||||||
[`web::block`][web-block] closure. Then just call the action function with the necessary arguments
|
|
||||||
and `.await` the result.
|
|
||||||
|
|
||||||
This example also maps the error to an `HttpResponse` before using the `?` operator but this is not
|
This example also maps the error to an `HttpResponse` before using the `?` operator but this is not necessary if your return error type implements [`ResponseError`][response-error].
|
||||||
necessary if your return error type implements [`ResponseError`][response-error].
|
|
||||||
|
|
||||||
{{< include-example example="databases" file="main.rs" section="index" >}}
|
{{< include-example example="databases" file="main.rs" section="index" >}}
|
||||||
|
|
||||||
That's it! See the full example here:
|
That's it! See the full example here: https://github.com/actix/examples/tree/master/databases/diesel
|
||||||
https://github.com/actix/examples/tree/master/databases/diesel
|
|
||||||
|
|
||||||
[web-block]: https://docs.rs/actix-web/3/actix_web/web/fn.block.html
|
[web-block]: https://docs.rs/actix-web/3/actix_web/web/fn.block.html
|
||||||
[response-error]: https://docs.rs/actix-web/3/actix_web/trait.ResponseError.html
|
[response-error]: https://docs.rs/actix-web/3/actix_web/trait.ResponseError.html
|
||||||
|
@ -6,13 +6,9 @@ weight: 180
|
|||||||
|
|
||||||
# Errors
|
# Errors
|
||||||
|
|
||||||
Actix-web uses its own [`actix_web::error::Error`][actixerror] type and
|
Actix-web uses its own [`actix_web::error::Error`][actixerror] type and [`actix_web::error::ResponseError`][responseerror] trait for error handling from web handlers.
|
||||||
[`actix_web::error::ResponseError`][responseerror] trait for error handling from web handlers.
|
|
||||||
|
|
||||||
If a handler returns an `Error` (referring to the [general Rust trait
|
If a handler returns an `Error` (referring to the [general Rust trait `std::error::Error`][stderror]) in a `Result` that also implements the `ResponseError` trait, actix-web will render that error as an HTTP response with its corresponding [`actix_web::http::StatusCode`][status_code]. An internal server error is generated by default:
|
||||||
`std::error::Error`][stderror]) in a `Result` that also implements the `ResponseError` trait,
|
|
||||||
actix-web will render that error as an HTTP response with its corresponding
|
|
||||||
[`actix_web::http::StatusCode`][status_code]. An internal server error is generated by default:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub trait ResponseError {
|
pub trait ResponseError {
|
||||||
@ -27,11 +23,9 @@ A `Responder` coerces compatible `Result`s into HTTP responses:
|
|||||||
impl<T: Responder, E: Into<Error>> Responder for Result<T, E>
|
impl<T: Responder, E: Into<Error>> Responder for Result<T, E>
|
||||||
```
|
```
|
||||||
|
|
||||||
`Error` in the code above is actix-web's error definition, and any errors that implement
|
`Error` in the code above is actix-web's error definition, and any errors that implement `ResponseError` can be converted to one automatically.
|
||||||
`ResponseError` can be converted to one automatically.
|
|
||||||
|
|
||||||
Actix-web provides `ResponseError` implementations for some common non-actix errors. For example, if
|
Actix-web provides `ResponseError` implementations for some common non-actix errors. For example, if a handler responds with an `io::Error`, that error is converted into an `HttpInternalServerError`:
|
||||||
a handler responds with an `io::Error`, that error is converted into an `HttpInternalServerError`:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::io;
|
use std::io;
|
||||||
@ -42,18 +36,15 @@ fn index(_req: HttpRequest) -> io::Result<NamedFile> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
See [the actix-web API documentation][responseerrorimpls] for a full list of foreign implementations
|
See [the actix-web API documentation][responseerrorimpls] for a full list of foreign implementations for `ResponseError`.
|
||||||
for `ResponseError`.
|
|
||||||
|
|
||||||
## An example of a custom error response
|
## An example of a custom error response
|
||||||
|
|
||||||
Here's an example implementation for `ResponseError`, using the [derive_more] crate
|
Here's an example implementation for `ResponseError`, using the [derive_more] crate for declarative error enums.
|
||||||
for declarative error enums.
|
|
||||||
|
|
||||||
{{< include-example example="errors" file="main.rs" section="response-error" >}}
|
{{< include-example example="errors" file="main.rs" section="response-error" >}}
|
||||||
|
|
||||||
`ResponseError` has a default implementation for `error_response()` that will render a _500_
|
`ResponseError` has a default implementation for `error_response()` that will render a _500_ (internal server error), and that's what will happen when the `index` handler executes above.
|
||||||
(internal server error), and that's what will happen when the `index` handler executes above.
|
|
||||||
|
|
||||||
Override `error_response()` to produce more useful results:
|
Override `error_response()` to produce more useful results:
|
||||||
|
|
||||||
@ -61,60 +52,44 @@ Override `error_response()` to produce more useful results:
|
|||||||
|
|
||||||
# Error helpers
|
# Error helpers
|
||||||
|
|
||||||
Actix-web provides a set of error helper functions that are useful for generating specific HTTP
|
Actix-web provides a set of error helper functions that are useful for generating specific HTTP error codes from other errors. Here we convert `MyError`, which doesn't implement the `ResponseError` trait, to a _400_ (bad request) using `map_err`:
|
||||||
error codes from other errors. Here we convert `MyError`, which doesn't implement the
|
|
||||||
`ResponseError` trait, to a _400_ (bad request) using `map_err`:
|
|
||||||
|
|
||||||
{{< include-example example="errors" file="helpers.rs" section="helpers" >}}
|
{{< include-example example="errors" file="helpers.rs" section="helpers" >}}
|
||||||
|
|
||||||
See the [API documentation for actix-web's `error` module][actixerror] for a full list of available
|
See the [API documentation for actix-web's `error` module][actixerror] for a full list of available error helpers.
|
||||||
error helpers.
|
|
||||||
|
|
||||||
# Error logging
|
# Error logging
|
||||||
|
|
||||||
Actix logs all errors at the `WARN` log level. If an application's log level is set to `DEBUG` and
|
Actix logs all errors at the `WARN` log level. If an application's log level is set to `DEBUG` and `RUST_BACKTRACE` is enabled, the backtrace is also logged. These are configurable with environmental variables:
|
||||||
`RUST_BACKTRACE` is enabled, the backtrace is also logged. These are configurable with environmental
|
|
||||||
variables:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
>> RUST_BACKTRACE=1 RUST_LOG=actix_web=debug cargo run
|
>> RUST_BACKTRACE=1 RUST_LOG=actix_web=debug cargo run
|
||||||
```
|
```
|
||||||
|
|
||||||
The `Error` type uses the cause's error backtrace if available. If the underlying failure does not
|
The `Error` type uses the cause's error backtrace if available. If the underlying failure does not provide a backtrace, a new backtrace is constructed pointing to the point where the conversion occurred (rather than the origin of the error).
|
||||||
provide a backtrace, a new backtrace is constructed pointing to the point where the conversion
|
|
||||||
occurred (rather than the origin of the error).
|
|
||||||
|
|
||||||
# Recommended practices in error handling
|
# Recommended practices in error handling
|
||||||
|
|
||||||
It might be useful to think about dividing the errors an application produces into two broad groups:
|
It might be useful to think about dividing the errors an application produces into two broad groups: those which are intended to be user-facing, and those which are not.
|
||||||
those which are intended to be user-facing, and those which are not.
|
|
||||||
|
|
||||||
An example of the former is that I might use failure to specify a `UserError` enum which
|
An example of the former is that I might use failure to specify a `UserError` enum which encapsulates a `ValidationError` to return whenever a user sends bad input:
|
||||||
encapsulates a `ValidationError` to return whenever a user sends bad input:
|
|
||||||
|
|
||||||
{{< include-example example="errors" file="recommend_one.rs" section="recommend-one" >}}
|
{{< include-example example="errors" file="recommend_one.rs" section="recommend-one" >}}
|
||||||
|
|
||||||
This will behave exactly as intended because the error message defined with `display` is written
|
This will behave exactly as intended because the error message defined with `display` is written with the explicit intent to be read by a user.
|
||||||
with the explicit intent to be read by a user.
|
|
||||||
|
|
||||||
However, sending back an error's message isn't desirable for all errors -- there are many failures
|
However, sending back an error's message isn't desirable for all errors -- there are many failures that occur in a server environment where we'd probably want the specifics to be hidden from the user. For example, if a database goes down and client libraries start producing connect timeout errors, or if an HTML template was improperly formatted and errors when rendered. In these cases, it might be preferable to map the errors to a generic error suitable for user consumption.
|
||||||
that occur in a server environment where we'd probably want the specifics to be hidden from the
|
|
||||||
user. For example, if a database goes down and client libraries start producing connect timeout
|
|
||||||
errors, or if an HTML template was improperly formatted and errors when rendered. In these cases, it
|
|
||||||
might be preferable to map the errors to a generic error suitable for user consumption.
|
|
||||||
|
|
||||||
Here's an example that maps an internal error to a user-facing `InternalError` with a custom
|
Here's an example that maps an internal error to a user-facing `InternalError` with a custom message:
|
||||||
message:
|
|
||||||
|
|
||||||
{{< include-example example="errors" file="recommend_two.rs" section="recommend-two" >}}
|
{{< include-example example="errors" file="recommend_two.rs" section="recommend-two" >}}
|
||||||
|
|
||||||
By dividing errors into those which are user facing and those which are not, we can ensure that we
|
By dividing errors into those which are user facing and those which are not, we can ensure that we don't accidentally expose users to errors thrown by application internals which they weren't meant to see.
|
||||||
don't accidentally expose users to errors thrown by application internals which they weren't meant
|
|
||||||
to see.
|
|
||||||
|
|
||||||
# Error Logging
|
# Error Logging
|
||||||
|
|
||||||
This is a basic example using `middleware::Logger` which depends on `env_logger` and `log`:
|
This is a basic example using `middleware::Logger` which depends on `env_logger` and `log`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.8"
|
env_logger = "0.8"
|
||||||
@ -127,7 +102,6 @@ log = "0.4"
|
|||||||
[errorhelpers]: https://docs.rs/actix-web/3/actix_web/trait.ResponseError.html
|
[errorhelpers]: https://docs.rs/actix-web/3/actix_web/trait.ResponseError.html
|
||||||
[derive_more]: https://crates.io/crates/derive_more
|
[derive_more]: https://crates.io/crates/derive_more
|
||||||
[responseerror]: https://docs.rs/actix-web/3/actix_web/error/trait.ResponseError.html
|
[responseerror]: https://docs.rs/actix-web/3/actix_web/error/trait.ResponseError.html
|
||||||
[responseerrorimpls]:
|
[responseerrorimpls]: https://docs.rs/actix-web/3/actix_web/error/trait.ResponseError.html#foreign-impls
|
||||||
https://docs.rs/actix-web/3/actix_web/error/trait.ResponseError.html#foreign-impls
|
|
||||||
[stderror]: https://doc.rust-lang.org/std/error/trait.Error.html
|
[stderror]: https://doc.rust-lang.org/std/error/trait.Error.html
|
||||||
[status_code]: https://docs.rs/actix-web/3.0.0/actix_web/http/struct.StatusCode.html
|
[status_code]: https://docs.rs/actix-web/3.0.0/actix_web/http/struct.StatusCode.html
|
||||||
|
@ -6,29 +6,21 @@ weight: 170
|
|||||||
|
|
||||||
# Type-safe information extraction
|
# Type-safe information extraction
|
||||||
|
|
||||||
Actix-web provides a facility for type-safe request information access called *extractors*
|
Actix-web provides a facility for type-safe request information access called _extractors_ (i.e., `impl FromRequest`). By default, actix-web provides several extractor implementations.
|
||||||
(i.e., `impl FromRequest`). By default, actix-web provides several extractor implementations.
|
|
||||||
|
|
||||||
An extractor can be accessed as an argument to a handler function. Actix-web supports
|
An extractor can be accessed as an argument to a handler function. Actix-web supports up to 12 extractors per handler function. Argument position does not matter.
|
||||||
up to 12 extractors per handler function. Argument position does not matter.
|
|
||||||
|
|
||||||
{{< include-example example="extractors" file="main.rs" section="option-one" >}}
|
{{< include-example example="extractors" file="main.rs" section="option-one" >}}
|
||||||
|
|
||||||
# Path
|
# Path
|
||||||
|
|
||||||
[*Path*][pathstruct] provides information that can be extracted from the Request's
|
[_Path_][pathstruct] provides information that can be extracted from the Request's path. You can deserialize any variable segment from the path.
|
||||||
path. You can deserialize any variable segment from the path.
|
|
||||||
|
|
||||||
For instance, for resource that registered for the `/users/{user_id}/{friend}` path,
|
For instance, for resource that registered for the `/users/{user_id}/{friend}` path, two segments could be deserialized, `user_id` and `friend`. These segments could be extracted into a `tuple`, i.e. `Path<(u32, String)>` or any structure that implements the `Deserialize` trait from the _serde_ crate.
|
||||||
two segments could be deserialized, `user_id` and `friend`. These segments could be
|
|
||||||
extracted into a `tuple`, i.e. `Path<(u32, String)>` or any structure that implements
|
|
||||||
the `Deserialize` trait from the *serde* crate.
|
|
||||||
|
|
||||||
{{< include-example example="extractors" file="path_one.rs" section="path-one" >}}
|
{{< include-example example="extractors" file="path_one.rs" section="path-one" >}}
|
||||||
|
|
||||||
It is also possible to extract path information to a specific type that implements the
|
It is also possible to extract path information to a specific type that implements the `Deserialize` trait from _serde_. Here is an equivalent example that uses _serde_ instead of a _tuple_ type.
|
||||||
`Deserialize` trait from *serde*. Here is an equivalent example that uses *serde*
|
|
||||||
instead of a *tuple* type.
|
|
||||||
|
|
||||||
{{< include-example example="extractors" file="path_two.rs" section="path-two" >}}
|
{{< include-example example="extractors" file="path_two.rs" section="path-two" >}}
|
||||||
|
|
||||||
@ -38,24 +30,17 @@ It is also possible to `get` or `query` the request for path parameters by name:
|
|||||||
|
|
||||||
# Query
|
# Query
|
||||||
|
|
||||||
The [*Query*][querystruct] type provides extraction functionality for the request's
|
The [_Query_][querystruct] type provides extraction functionality for the request's query parameters. Underneath it uses _serde_urlencoded_ crate.
|
||||||
query parameters. Underneath it uses *serde_urlencoded* crate.
|
|
||||||
|
|
||||||
{{< include-example example="extractors" file="query.rs" section="query" >}}
|
{{< include-example example="extractors" file="query.rs" section="query" >}}
|
||||||
|
|
||||||
# Json
|
# Json
|
||||||
|
|
||||||
[*Json*][jsonstruct] allows deserialization of a request body into a struct. To extract
|
[_Json_][jsonstruct] allows deserialization of a request body into a struct. To extract typed information from a request's body, the type `T` must implement the `Deserialize` trait from _serde_.
|
||||||
typed information from a request's body, the type `T` must implement the `Deserialize`
|
|
||||||
trait from *serde*.
|
|
||||||
|
|
||||||
{{< include-example example="extractors" file="json_one.rs" section="json-one" >}}
|
{{< include-example example="extractors" file="json_one.rs" section="json-one" >}}
|
||||||
|
|
||||||
Some extractors provide a way to configure the extraction process. To configure
|
Some extractors provide a way to configure the extraction process. To configure an extractor, pass its configuration object to the resource's `.data()` method. In the case of _Json_ extractor it returns a [_JsonConfig_][jsonconfig]. You can configure the maximum size of the JSON payload as well as a custom error handler function.
|
||||||
an extractor, pass its configuration object to the resource's `.data()` method.
|
|
||||||
In the case of *Json* extractor it returns a [*JsonConfig*][jsonconfig].
|
|
||||||
You can configure the maximum size of the JSON payload as
|
|
||||||
well as a custom error handler function.
|
|
||||||
|
|
||||||
The following example limits the size of the payload to 4kb and uses a custom error handler.
|
The following example limits the size of the payload to 4kb and uses a custom error handler.
|
||||||
|
|
||||||
@ -63,11 +48,9 @@ The following example limits the size of the payload to 4kb and uses a custom er
|
|||||||
|
|
||||||
# Form
|
# Form
|
||||||
|
|
||||||
At the moment, only url-encoded forms are supported. The url-encoded body could be
|
At the moment, only url-encoded forms are supported. The url-encoded body could be extracted to a specific type. This type must implement the `Deserialize` trait from the _serde_ crate.
|
||||||
extracted to a specific type. This type must implement the `Deserialize` trait from
|
|
||||||
the *serde* crate.
|
|
||||||
|
|
||||||
[*FormConfig*][formconfig] allows configuring the extraction process.
|
[_FormConfig_][formconfig] allows configuring the extraction process.
|
||||||
|
|
||||||
{{< include-example example="extractors" file="form.rs" section="form" >}}
|
{{< include-example example="extractors" file="form.rs" section="form" >}}
|
||||||
|
|
||||||
@ -75,43 +58,29 @@ the *serde* crate.
|
|||||||
|
|
||||||
Actix-web also provides several other extractors:
|
Actix-web also provides several other extractors:
|
||||||
|
|
||||||
* [*Data*][datastruct] - If you need access to an application state.
|
- [_Data_][datastruct] - If you need access to an application state.
|
||||||
* *HttpRequest* - *HttpRequest* itself is an extractor which returns self, in case you
|
- _HttpRequest_ - _HttpRequest_ itself is an extractor which returns self, in case you need access to the request.
|
||||||
need access to the request.
|
- _String_ - You can convert a request's payload to a _String_. [_Example_][stringexample] is available in doc strings.
|
||||||
* *String* - You can convert a request's payload to a *String*. [*Example*][stringexample]
|
- _actix_web::web::Bytes_ - You can convert a request's payload into _Bytes_. [_Example_][bytesexample] is available in doc strings.
|
||||||
is available in doc strings.
|
- _Payload_ - You can access a request's payload. [_Example_][payloadexample]
|
||||||
* *actix_web::web::Bytes* - You can convert a request's payload into *Bytes*.
|
|
||||||
[*Example*][bytesexample]
|
|
||||||
is available in doc strings.
|
|
||||||
* *Payload* - You can access a request's payload.
|
|
||||||
[*Example*][payloadexample]
|
|
||||||
|
|
||||||
# Application state extractor
|
# Application state extractor
|
||||||
|
|
||||||
Application state is accessible from the handler with the `web::Data` extractor;
|
Application state is accessible from the handler with the `web::Data` extractor; however, state is accessible as a read-only reference. If you need mutable access to state, it must be implemented.
|
||||||
however, state is accessible as a read-only reference. If you need mutable access to state,
|
|
||||||
it must be implemented.
|
|
||||||
|
|
||||||
> **Beware**, actix creates multiple copies of the application state and the handlers. It creates
|
> **Beware**, actix creates multiple copies of the application state and the handlers. It creates one copy for each thread.
|
||||||
> one copy for each thread.
|
|
||||||
|
|
||||||
Here is an example of a handler that stores the number of processed requests:
|
Here is an example of a handler that stores the number of processed requests:
|
||||||
|
|
||||||
{{< include-example example="request-handlers" file="main.rs" section="data" >}}
|
{{< include-example example="request-handlers" file="main.rs" section="data" >}}
|
||||||
|
|
||||||
Although this handler will work, `data.count` will only count the number of requests
|
Although this handler will work, `data.count` will only count the number of requests handled _by each thread_. To count the number of total requests across all threads, one should use `Arc` and [atomics][atomics].
|
||||||
handled *by each thread*. To count the number of total requests across all threads,
|
|
||||||
one should use `Arc` and [atomics][atomics].
|
|
||||||
|
|
||||||
{{< include-example example="request-handlers" file="handlers_arc.rs" section="arc" >}}
|
{{< include-example example="request-handlers" file="handlers_arc.rs" section="arc" >}}
|
||||||
|
|
||||||
> **Note**, if you want the *entire* state to be shared across all threads, use
|
> **Note**, if you want the _entire_ state to be shared across all threads, use `web::Data` and `app_data` as described in [Shared Mutable State][shared_mutable_state].
|
||||||
> `web::Data` and `app_data` as described in [Shared Mutable State][shared_mutable_state].
|
|
||||||
|
|
||||||
> Be careful with synchronization primitives like `Mutex` or `RwLock`. The `actix-web` framework
|
> Be careful with synchronization primitives like `Mutex` or `RwLock`. The `actix-web` framework handles requests asynchronously. By blocking thread execution, all concurrent request handling processes would block. If you need to share or update some state from multiple threads, consider using the tokio synchronization primitives.
|
||||||
> handles requests asynchronously. By blocking thread execution, all concurrent
|
|
||||||
> request handling processes would block. If you need to share or update some state
|
|
||||||
> from multiple threads, consider using the tokio synchronization primitives.
|
|
||||||
|
|
||||||
[pathstruct]: https://docs.rs/actix-web/3/actix_web/dev/struct.Path.html
|
[pathstruct]: https://docs.rs/actix-web/3/actix_web/dev/struct.Path.html
|
||||||
[querystruct]: https://docs.rs/actix-web/3/actix_web/web/struct.Query.html
|
[querystruct]: https://docs.rs/actix-web/3/actix_web/web/struct.Query.html
|
||||||
|
@ -6,12 +6,9 @@ weight: 130
|
|||||||
|
|
||||||
## Installing Rust
|
## Installing Rust
|
||||||
|
|
||||||
If you don't have Rust yet, we recommend you use `rustup` to manage your Rust installation. The
|
If you don't have Rust yet, we recommend you use `rustup` to manage your Rust installation. The [official rust guide][rustguide] has a wonderful section on getting started.
|
||||||
[official rust guide][rustguide] has a wonderful section on getting started.
|
|
||||||
|
|
||||||
Actix Web currently has a minimum supported Rust version (MSRV) of {{< rust-version "actix-web" >}}.
|
Actix Web currently has a minimum supported Rust version (MSRV) of {{< rust-version "actix-web" >}}. Running `rustup update` will ensure you have the latest and greatest Rust version available. As such, this guide assumes you are running Rust {{< rust-version "actix-web" >}} or later.
|
||||||
Running `rustup update` will ensure you have the latest and greatest Rust version available. As
|
|
||||||
such, this guide assumes you are running Rust {{< rust-version "actix-web" >}} or later.
|
|
||||||
|
|
||||||
## Hello, world!
|
## Hello, world!
|
||||||
|
|
||||||
@ -29,26 +26,17 @@ Add `actix-web` as a dependency of your project by adding the following to your
|
|||||||
actix-web = "{{< actix-version "actix-web" >}}"
|
actix-web = "{{< actix-version "actix-web" >}}"
|
||||||
```
|
```
|
||||||
|
|
||||||
Request handlers use async functions that accept zero or more parameters. These parameters can be
|
Request handlers use async functions that accept zero or more parameters. These parameters can be extracted from a request (see `FromRequest` trait) and returns a type that can be converted into an `HttpResponse` (see `Responder` trait):
|
||||||
extracted from a request (see `FromRequest` trait) and returns a type that can be converted into an
|
|
||||||
`HttpResponse` (see `Responder` trait):
|
|
||||||
|
|
||||||
{{< include-example example="getting-started" section="handlers" >}}
|
{{< include-example example="getting-started" section="handlers" >}}
|
||||||
|
|
||||||
Notice that some of these handlers have routing information attached directly using the built-in
|
Notice that some of these handlers have routing information attached directly using the built-in macros. These allow you to specify the method and path that the handler should respond to. You will see below how to register `manual_hello` (i.e. routes that do not use a routing macro).
|
||||||
macros. These allow you to specify the method and path that the handler should respond to. You will
|
|
||||||
see below how to register `manual_hello` (i.e. routes that do not use a routing macro).
|
|
||||||
|
|
||||||
Next, create an `App` instance and register the request handlers. Use `App::service` for the
|
Next, create an `App` instance and register the request handlers. Use `App::service` for the handlers using routing macros and `App::route` for manually routed handlers, declaring the path and method. Finally, the app is started inside an `HttpServer` which will serve incoming requests using your `App` as an "application factory".
|
||||||
handlers using routing macros and `App::route` for manually routed handlers, declaring the path
|
|
||||||
and method. Finally, the app is started inside an `HttpServer` which will serve incoming requests
|
|
||||||
using your `App` as an "application factory".
|
|
||||||
|
|
||||||
{{< include-example example="getting-started" section="main" >}}
|
{{< include-example example="getting-started" section="main" >}}
|
||||||
|
|
||||||
That's it! Compile and run the program with `cargo run`. The `#[actix_web::main]` macro executes the
|
That's it! Compile and run the program with `cargo run`. The `#[actix_web::main]` macro executes the async main function within the actix runtime. Now you can go to `http://127.0.0.1:8080/` or any of the other routes you defined to see the results.
|
||||||
async main function within the actix runtime. Now you can go to `http://127.0.0.1:8080/` or any of
|
|
||||||
the other routes you defined to see the results.
|
|
||||||
|
|
||||||
<!-- LINKS -->
|
<!-- LINKS -->
|
||||||
|
|
||||||
|
@ -6,18 +6,13 @@ weight: 160
|
|||||||
|
|
||||||
# Request Handlers
|
# Request Handlers
|
||||||
|
|
||||||
A request handler is an async function that accepts zero or more parameters that can be extracted
|
A request handler is an async function that accepts zero or more parameters that can be extracted from a request (i.e., [_impl FromRequest_][implfromrequest]) and returns a type that can be converted into an HttpResponse (i.e., [_impl Responder_][respondertrait]).
|
||||||
from a request (i.e., [*impl FromRequest*][implfromrequest]) and returns a type that can
|
|
||||||
be converted into an HttpResponse (i.e., [*impl Responder*][respondertrait]).
|
|
||||||
|
|
||||||
Request handling happens in two stages. First the handler object is called, returning any
|
Request handling happens in two stages. First the handler object is called, returning any object that implements the [_Responder_][respondertrait] trait. Then, `respond_to()` is called on the returned object, converting itself to a `HttpResponse` or `Error`.
|
||||||
object that implements the [*Responder*][respondertrait] trait. Then, `respond_to()` is
|
|
||||||
called on the returned object, converting itself to a `HttpResponse` or `Error`.
|
|
||||||
|
|
||||||
By default actix-web provides `Responder` implementations for some standard types,
|
By default actix-web provides `Responder` implementations for some standard types, such as `&'static str`, `String`, etc.
|
||||||
such as `&'static str`, `String`, etc.
|
|
||||||
|
|
||||||
> For a complete list of implementations, check the [*Responder documentation*][responderimpls].
|
> For a complete list of implementations, check the [_Responder documentation_][responderimpls].
|
||||||
|
|
||||||
Examples of valid handlers:
|
Examples of valid handlers:
|
||||||
|
|
||||||
@ -33,8 +28,7 @@ async fn index(_req: HttpRequest) -> String {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also change the signature to return `impl Responder` which works well if more
|
You can also change the signature to return `impl Responder` which works well if more complex types are involved.
|
||||||
complex types are involved.
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
async fn index(_req: HttpRequest) -> impl Responder {
|
async fn index(_req: HttpRequest) -> impl Responder {
|
||||||
@ -58,18 +52,15 @@ Let's create a response for a custom type that serializes to an `application/jso
|
|||||||
|
|
||||||
## Streaming response body
|
## Streaming response body
|
||||||
|
|
||||||
Response body can be generated asynchronously. In this case, body must implement
|
Response body can be generated asynchronously. In this case, body must implement the stream trait `Stream<Item=Bytes, Error=Error>`, i.e.:
|
||||||
the stream trait `Stream<Item=Bytes, Error=Error>`, i.e.:
|
|
||||||
|
|
||||||
{{< include-example example="async-handlers" file="stream.rs" section="stream" >}}
|
{{< include-example example="async-handlers" file="stream.rs" section="stream" >}}
|
||||||
|
|
||||||
## Different return types (Either)
|
## Different return types (Either)
|
||||||
|
|
||||||
Sometimes, you need to return different types of responses. For example, you can error
|
Sometimes, you need to return different types of responses. For example, you can error check and return errors, return async responses, or any result that requires two different types.
|
||||||
check and return errors, return async responses, or any result that requires two different types.
|
|
||||||
|
|
||||||
For this case, the [Either][either] type can be used. `Either` allows combining two
|
For this case, the [Either][either] type can be used. `Either` allows combining two different responder types into a single type.
|
||||||
different responder types into a single type.
|
|
||||||
|
|
||||||
{{< include-example example="either" file="main.rs" section="either" >}}
|
{{< include-example example="either" file="main.rs" section="either" >}}
|
||||||
|
|
||||||
|
@ -4,28 +4,27 @@ menu: docs_protocols
|
|||||||
weight: 250
|
weight: 250
|
||||||
---
|
---
|
||||||
|
|
||||||
`actix-web` automatically upgrades connections to *HTTP/2* if possible.
|
`actix-web` automatically upgrades connections to _HTTP/2_ if possible.
|
||||||
|
|
||||||
# Negotiation
|
# Negotiation
|
||||||
|
|
||||||
*HTTP/2* protocol over TLS without prior knowledge requires [TLS ALPN][tlsalpn].
|
_HTTP/2_ protocol over TLS without prior knowledge requires [TLS ALPN][tlsalpn].
|
||||||
|
|
||||||
<!-- TODO: use rustls example -->
|
<!-- TODO: use rustls example -->
|
||||||
|
|
||||||
> Currently, only `rust-openssl` has support.
|
> Currently, only `rust-openssl` has support.
|
||||||
|
|
||||||
`alpn` negotiation requires enabling the feature. When enabled, `HttpServer` provides the
|
`alpn` negotiation requires enabling the feature. When enabled, `HttpServer` provides the [bind_openssl][bindopenssl] method.
|
||||||
[bind_openssl][bindopenssl] method.
|
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "{{< actix-version "actix-web" >}}", features = ["openssl"] }
|
actix-web = { version = "{{< actix-version "actix-web" >}}", features = ["openssl"] }
|
||||||
openssl = { version = "0.10", features = ["v110"] }
|
openssl = { version = "0.10", features = ["v110"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
{{< include-example example="http2" file="main.rs" section="main" >}}
|
{{< include-example example="http2" file="main.rs" section="main" >}}
|
||||||
|
|
||||||
Upgrades to *HTTP/2.0* schema described in [rfc section 3.2][rfcsection32] is not
|
Upgrades to _HTTP/2.0_ schema described in [rfc section 3.2][rfcsection32] is not supported. Starting _HTTP/2_ with prior knowledge is supported for both clear text connection and tls connection. [rfc section 3.4][rfcsection34].
|
||||||
supported. Starting *HTTP/2* with prior knowledge is supported for both clear text
|
|
||||||
connection and tls connection. [rfc section 3.4][rfcsection34].
|
|
||||||
|
|
||||||
> Check out [examples/tls][examples] for a concrete example.
|
> Check out [examples/tls][examples] for a concrete example.
|
||||||
|
|
||||||
|
@ -6,51 +6,40 @@ weight: 220
|
|||||||
|
|
||||||
# Middleware
|
# Middleware
|
||||||
|
|
||||||
Actix-web's middleware system allows us to add additional behavior to request/response
|
Actix-web's middleware system allows us to add additional behavior to request/response processing. Middleware can hook into an incoming request process, enabling us to modify requests as well as halt request processing to return a response early.
|
||||||
processing. Middleware can hook into an incoming request process, enabling us to modify
|
|
||||||
requests as well as halt request processing to return a response early.
|
|
||||||
|
|
||||||
Middleware can also hook into response processing.
|
Middleware can also hook into response processing.
|
||||||
|
|
||||||
Typically, middleware is involved in the following actions:
|
Typically, middleware is involved in the following actions:
|
||||||
|
|
||||||
* Pre-process the Request
|
- Pre-process the Request
|
||||||
* Post-process a Response
|
- Post-process a Response
|
||||||
* Modify application state
|
- Modify application state
|
||||||
* Access external services (redis, logging, sessions)
|
- Access external services (redis, logging, sessions)
|
||||||
|
|
||||||
Middleware is registered for each `App`, `scope`, or `Resource` and executed in opposite
|
Middleware is registered for each `App`, `scope`, or `Resource` and executed in opposite order as registration. In general, a _middleware_ is a type that implements the [_Service trait_][servicetrait] and [_Transform trait_][transformtrait]. Each method in the traits has a default implementation. Each method can return a result immediately or a _future_ object.
|
||||||
order as registration. In general, a *middleware* is a type that implements the
|
|
||||||
[*Service trait*][servicetrait] and [*Transform trait*][transformtrait]. Each method in
|
|
||||||
the traits has a default implementation. Each method can return a result immediately
|
|
||||||
or a *future* object.
|
|
||||||
|
|
||||||
The following demonstrates creating a simple middleware:
|
The following demonstrates creating a simple middleware:
|
||||||
|
|
||||||
{{< include-example example="middleware" file="main.rs" section="simple" >}}
|
{{< include-example example="middleware" file="main.rs" section="simple" >}}
|
||||||
|
|
||||||
Alternatively, for simple use cases, you can use [*wrap_fn*][wrap_fn] to create small, ad-hoc middleware:
|
Alternatively, for simple use cases, you can use [_wrap_fn_][wrap_fn] to create small, ad-hoc middleware:
|
||||||
|
|
||||||
{{< include-example example="middleware" file="wrap_fn.rs" section="wrap-fn" >}}
|
{{< include-example example="middleware" file="wrap_fn.rs" section="wrap-fn" >}}
|
||||||
|
|
||||||
> Actix-web provides several useful middleware, such as *logging*, *user sessions*,
|
> Actix-web provides several useful middleware, such as _logging_, _user sessions_, _compress_, etc.
|
||||||
> *compress*, etc.
|
|
||||||
|
|
||||||
**Warning: if you use `wrap()` or `wrap_fn()` multiple times, the last occurrence will be executed first.**
|
**Warning: if you use `wrap()` or `wrap_fn()` multiple times, the last occurrence will be executed first.**
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
|
|
||||||
Logging is implemented as a middleware. It is common to register a logging middleware
|
Logging is implemented as a middleware. It is common to register a logging middleware as the first middleware for the application. Logging middleware must be registered for each application.
|
||||||
as the first middleware for the application. Logging middleware must be registered for
|
|
||||||
each application.
|
|
||||||
|
|
||||||
The `Logger` middleware uses the standard log crate to log information. You should enable logger
|
The `Logger` middleware uses the standard log crate to log information. You should enable logger for _actix_web_ package to see access log ([env_logger][envlogger] or similar).
|
||||||
for *actix_web* package to see access log ([env_logger][envlogger] or similar).
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Create `Logger` middleware with the specified `format`. Default `Logger` can be created
|
Create `Logger` middleware with the specified `format`. Default `Logger` can be created with `default` method, it uses the default format:
|
||||||
with `default` method, it uses the default format:
|
|
||||||
|
|
||||||
```ignore
|
```ignore
|
||||||
%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
|
%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
|
||||||
@ -67,53 +56,40 @@ INFO:actix_web::middleware::logger: 127.0.0.1:59947 [02/Dec/2017:00:22:40 -0800]
|
|||||||
|
|
||||||
## Format
|
## Format
|
||||||
|
|
||||||
- `%%` The percent sign
|
- `%%` The percent sign
|
||||||
- `%a` Remote IP-address (IP-address of proxy if using reverse proxy)
|
- `%a` Remote IP-address (IP-address of proxy if using reverse proxy)
|
||||||
- `%t` Time when the request was started to process
|
- `%t` Time when the request was started to process
|
||||||
- `%P` The process ID of the child that serviced the request
|
- `%P` The process ID of the child that serviced the request
|
||||||
- `%r` First line of request
|
- `%r` First line of request
|
||||||
- `%s` Response status code
|
- `%s` Response status code
|
||||||
- `%b` Size of response in bytes, including HTTP headers
|
- `%b` Size of response in bytes, including HTTP headers
|
||||||
- `%T` Time taken to serve the request, in seconds with floating fraction in .06f format
|
- `%T` Time taken to serve the request, in seconds with floating fraction in .06f format
|
||||||
- `%D` Time taken to serve the request, in milliseconds
|
- `%D` Time taken to serve the request, in milliseconds
|
||||||
- `%{FOO}i` request.headers['FOO']
|
- `%{FOO}i` request.headers['FOO']
|
||||||
- `%{FOO}o` response.headers['FOO']
|
- `%{FOO}o` response.headers['FOO']
|
||||||
- `%{FOO}e` os.environ['FOO']
|
- `%{FOO}e` os.environ['FOO']
|
||||||
|
|
||||||
## Default headers
|
## Default headers
|
||||||
|
|
||||||
To set default response headers, the `DefaultHeaders` middleware can be used. The
|
To set default response headers, the `DefaultHeaders` middleware can be used. The _DefaultHeaders_ middleware does not set the header if response headers already contain a specified header.
|
||||||
*DefaultHeaders* middleware does not set the header if response headers already contain
|
|
||||||
a specified header.
|
|
||||||
|
|
||||||
{{< include-example example="middleware" file="default_headers.rs" section="default-headers" >}}
|
{{< include-example example="middleware" file="default_headers.rs" section="default-headers" >}}
|
||||||
|
|
||||||
## User sessions
|
## User sessions
|
||||||
|
|
||||||
Actix-web provides a general solution for session management. The
|
Actix-web provides a general solution for session management. The [**actix-session**][actixsession] middleware can use multiple backend types to store session data.
|
||||||
[**actix-session**][actixsession] middleware can use multiple backend types to store session data.
|
|
||||||
|
|
||||||
> By default, only cookie session backend is implemented. Other backend implementations
|
> By default, only cookie session backend is implemented. Other backend implementations can be added.
|
||||||
> can be added.
|
|
||||||
|
|
||||||
[**CookieSession**][cookiesession] uses cookies as session storage. `CookieSessionBackend`
|
[**CookieSession**][cookiesession] uses cookies as session storage. `CookieSessionBackend` creates sessions which are limited to storing fewer than 4000 bytes of data, as the payload must fit into a single cookie. An internal server error is generated if a session contains more than 4000 bytes.
|
||||||
creates sessions which are limited to storing fewer than 4000 bytes of data, as the payload
|
|
||||||
must fit into a single cookie. An internal server error is generated if a session
|
|
||||||
contains more than 4000 bytes.
|
|
||||||
|
|
||||||
A cookie may have a security policy of *signed* or *private*. Each has a respective
|
A cookie may have a security policy of _signed_ or _private_. Each has a respective `CookieSession` constructor.
|
||||||
`CookieSession` constructor.
|
|
||||||
|
|
||||||
A *signed* cookie may be viewed but not modified by the client. A *private* cookie may
|
A _signed_ cookie may be viewed but not modified by the client. A _private_ cookie may neither be viewed nor modified by the client.
|
||||||
neither be viewed nor modified by the client.
|
|
||||||
|
|
||||||
The constructors take a key as an argument. This is the private key for cookie session -
|
The constructors take a key as an argument. This is the private key for cookie session - when this value is changed, all session data is lost.
|
||||||
when this value is changed, all session data is lost.
|
|
||||||
|
|
||||||
In general, you create a `SessionStorage` middleware and initialize it with specific
|
In general, you create a `SessionStorage` middleware and initialize it with specific backend implementation, such as a `CookieSession`. To access session data the [`Session`][requestsession] extractor must be used. This method returns a [_Session_][sessionobj] object, which allows us to get or set session data.
|
||||||
backend implementation, such as a `CookieSession`. To access session data the
|
|
||||||
[`Session`][requestsession] extractor must be used. This method returns a
|
|
||||||
[*Session*][sessionobj] object, which allows us to get or set session data.
|
|
||||||
|
|
||||||
{{< include-example example="middleware" file="user_sessions.rs" section="user-session" >}}
|
{{< include-example example="middleware" file="user_sessions.rs" section="user-session" >}}
|
||||||
|
|
||||||
@ -121,10 +97,7 @@ backend implementation, such as a `CookieSession`. To access session data the
|
|||||||
|
|
||||||
`ErrorHandlers` middleware allows us to provide custom handlers for responses.
|
`ErrorHandlers` middleware allows us to provide custom handlers for responses.
|
||||||
|
|
||||||
You can use the `ErrorHandlers::handler()` method to register a custom error handler
|
You can use the `ErrorHandlers::handler()` method to register a custom error handler for a specific status code. You can modify an existing response or create a completly new one. The error handler can return a response immediately or return a future that resolves into a response.
|
||||||
for a specific status code. You can modify an existing response or create a completly new
|
|
||||||
one. The error handler can return a response immediately or return a future that resolves
|
|
||||||
into a response.
|
|
||||||
|
|
||||||
{{< include-example example="middleware" file="errorhandler.rs" section="error-handler" >}}
|
{{< include-example example="middleware" file="errorhandler.rs" section="error-handler" >}}
|
||||||
|
|
||||||
|
@ -8,30 +8,30 @@ weight: 200
|
|||||||
|
|
||||||
There are several options for json body deserialization.
|
There are several options for json body deserialization.
|
||||||
|
|
||||||
The first option is to use *Json* extractor. First, you define a handler function
|
The first option is to use _Json_ extractor. First, you define a handler function that accepts `Json<T>` as a parameter, then, you use the `.to()` method for registering this handler. It is also possible to accept arbitrary valid json object by using `serde_json::Value` as a type `T`.
|
||||||
that accepts `Json<T>` as a parameter, then, you use the `.to()` method for registering
|
|
||||||
this handler. It is also possible to accept arbitrary valid json object by
|
|
||||||
using `serde_json::Value` as a type `T`.
|
|
||||||
|
|
||||||
First example of json of `JSON Request` depends on `serde`:
|
First example of json of `JSON Request` depends on `serde`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "1"
|
serde = "1"
|
||||||
````
|
```
|
||||||
Second example of `JSON Request` depends on `serde` and `serde_json`:
|
|
||||||
|
Second example of `JSON Request` depends on `serde` and `serde_json`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "1"
|
serde = "1"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to add default value for a field, refer to `serde`'s [documentation](https://serde.rs/attr-default.html).
|
If you want to add default value for a field, refer to `serde`'s [documentation](https://serde.rs/attr-default.html).
|
||||||
|
|
||||||
{{< include-example example="requests" file="main.rs" section="json-request" >}}
|
{{< include-example example="requests" file="main.rs" section="json-request" >}}
|
||||||
|
|
||||||
You may also manually load the payload into memory and then deserialize it.
|
You may also manually load the payload into memory and then deserialize it.
|
||||||
|
|
||||||
In the following example, we will deserialize a *MyObj* struct. We need to load the request
|
In the following example, we will deserialize a _MyObj_ struct. We need to load the request body first and then deserialize the json into an object.
|
||||||
body first and then deserialize the json into an object.
|
|
||||||
|
|
||||||
{{< include-example example="requests" file="manual.rs" section="json-manual" >}}
|
{{< include-example example="requests" file="manual.rs" section="json-manual" >}}
|
||||||
|
|
||||||
@ -39,22 +39,18 @@ body first and then deserialize the json into an object.
|
|||||||
|
|
||||||
# Content Encoding
|
# Content Encoding
|
||||||
|
|
||||||
Actix-web automatically *decompresses* payloads. The following codecs are supported:
|
Actix-web automatically _decompresses_ payloads. The following codecs are supported:
|
||||||
|
|
||||||
* Brotli
|
- Brotli
|
||||||
* Gzip
|
- Gzip
|
||||||
* Deflate
|
- Deflate
|
||||||
* Zstd
|
- Zstd
|
||||||
|
|
||||||
If request headers contain a `Content-Encoding` header, the request payload is decompressed
|
If request headers contain a `Content-Encoding` header, the request payload is decompressed according to the header value. Multiple codecs are not supported, i.e: `Content-Encoding: br, gzip`.
|
||||||
according to the header value. Multiple codecs are not supported, i.e: `Content-Encoding: br, gzip`.
|
|
||||||
|
|
||||||
# Chunked transfer encoding
|
# Chunked transfer encoding
|
||||||
|
|
||||||
Actix automatically decodes *chunked* encoding. The [`web::Payload`][payloadextractor]
|
Actix automatically decodes _chunked_ encoding. The [`web::Payload`][payloadextractor] extractor already contains the decoded byte stream. If the request payload is compressed with one of the supported compression codecs (br, gzip, deflate), then the byte stream is decompressed.
|
||||||
extractor already contains the decoded byte stream. If the request payload is compressed
|
|
||||||
with one of the supported compression codecs (br, gzip, deflate), then the byte stream
|
|
||||||
is decompressed.
|
|
||||||
|
|
||||||
# Multipart body
|
# Multipart body
|
||||||
|
|
||||||
@ -64,23 +60,20 @@ Actix-web provides multipart stream support with an external crate, [`actix-mult
|
|||||||
|
|
||||||
# Urlencoded body
|
# Urlencoded body
|
||||||
|
|
||||||
Actix-web provides support for *application/x-www-form-urlencoded* encoded bodies with
|
Actix-web provides support for _application/x-www-form-urlencoded_ encoded bodies with the [`web::Form`][formencoded] extractor which resolves to the deserialized instance. The type of the instance must implement the `Deserialize` trait from _serde_.
|
||||||
the [`web::Form`][formencoded] extractor which resolves to the deserialized instance. The
|
|
||||||
type of the instance must implement the `Deserialize` trait from *serde*.
|
|
||||||
|
|
||||||
The *UrlEncoded* future can resolve into an error in several cases:
|
The _UrlEncoded_ future can resolve into an error in several cases:
|
||||||
|
|
||||||
* content type is not `application/x-www-form-urlencoded`
|
- content type is not `application/x-www-form-urlencoded`
|
||||||
* transfer encoding is `chunked`.
|
- transfer encoding is `chunked`.
|
||||||
* content-length is greater than 256k
|
- content-length is greater than 256k
|
||||||
* payload terminates with error.
|
- payload terminates with error.
|
||||||
|
|
||||||
{{< include-example example="requests" file="urlencoded.rs" section="urlencoded" >}}
|
{{< include-example example="requests" file="urlencoded.rs" section="urlencoded" >}}
|
||||||
|
|
||||||
# Streaming request
|
# Streaming request
|
||||||
|
|
||||||
*HttpRequest* is a stream of `Bytes` objects. It can be used to read the request
|
_HttpRequest_ is a stream of `Bytes` objects. It can be used to read the request body payload.
|
||||||
body payload.
|
|
||||||
|
|
||||||
In the following example, we read and print the request payload chunk by chunk:
|
In the following example, we read and print the request payload chunk by chunk:
|
||||||
|
|
||||||
|
@ -6,23 +6,17 @@ weight: 210
|
|||||||
|
|
||||||
# Response
|
# Response
|
||||||
|
|
||||||
A builder-like pattern is used to construct an instance of `HttpResponse`. `HttpResponse`
|
A builder-like pattern is used to construct an instance of `HttpResponse`. `HttpResponse` provides several methods that return a `HttpResponseBuilder` instance, which implements various convenience methods for building responses.
|
||||||
provides several methods that return a `HttpResponseBuilder` instance, which implements
|
|
||||||
various convenience methods for building responses.
|
|
||||||
|
|
||||||
> Check the [documentation][responsebuilder] for type descriptions.
|
> Check the [documentation][responsebuilder] for type descriptions.
|
||||||
|
|
||||||
The methods `.body`, `.finish`, and `.json` finalize response creation and return a
|
The methods `.body`, `.finish`, and `.json` finalize response creation and return a constructed _HttpResponse_ instance. If this methods is called on the same builder instance multiple times, the builder will panic.
|
||||||
constructed *HttpResponse* instance. If this methods is called on the same builder
|
|
||||||
instance multiple times, the builder will panic.
|
|
||||||
|
|
||||||
{{< include-example example="responses" file="main.rs" section="builder" >}}
|
{{< include-example example="responses" file="main.rs" section="builder" >}}
|
||||||
|
|
||||||
# JSON Response
|
# JSON Response
|
||||||
|
|
||||||
The `Json` type allows to respond with well-formed JSON data: simply return a value of
|
The `Json` type allows to respond with well-formed JSON data: simply return a value of type `Json<T>` where `T` is the type of a structure to serialize into _JSON_. The type `T` must implement the `Serialize` trait from _serde_.
|
||||||
type `Json<T>` where `T` is the type of a structure to serialize into *JSON*.
|
|
||||||
The type `T` must implement the `Serialize` trait from *serde*.
|
|
||||||
|
|
||||||
For the following example to work, you need to add `serde` to your dependencies in `Cargo.toml`:
|
For the following example to work, you need to add `serde` to your dependencies in `Cargo.toml`:
|
||||||
|
|
||||||
@ -33,28 +27,22 @@ serde = "1"
|
|||||||
|
|
||||||
{{< include-example example="responses" file="json_resp.rs" section="json-resp" >}}
|
{{< include-example example="responses" file="json_resp.rs" section="json-resp" >}}
|
||||||
|
|
||||||
Using the `Json` type this way instead of calling the `.json` method on a `HttpResponse` makes it
|
Using the `Json` type this way instead of calling the `.json` method on a `HttpResponse` makes it immediately clear that the function returns JSON and not any other type of response.
|
||||||
immediately clear that the function returns JSON and not any other type of response.
|
|
||||||
|
|
||||||
# Content encoding
|
# Content encoding
|
||||||
|
|
||||||
Actix-web can automatically *compress* payloads with the [*Compress middleware*][compressmidddleware].
|
Actix-web can automatically _compress_ payloads with the [_Compress middleware_][compressmidddleware]. The following codecs are supported:
|
||||||
The following codecs are supported:
|
|
||||||
|
|
||||||
* Brotli
|
- Brotli
|
||||||
* Gzip
|
- Gzip
|
||||||
* Deflate
|
- Deflate
|
||||||
* Identity
|
- Identity
|
||||||
|
|
||||||
{{< include-example example="responses" file="compress.rs" section="compress" >}}
|
{{< include-example example="responses" file="compress.rs" section="compress" >}}
|
||||||
|
|
||||||
Response payload is compressed based on the *encoding* parameter from the
|
Response payload is compressed based on the _encoding_ parameter from the `middleware::BodyEncoding` trait. By default, `ContentEncoding::Auto` is used. If `ContentEncoding::Auto` is selected, then the compression depends on the request's `Accept-Encoding` header.
|
||||||
`middleware::BodyEncoding` trait. By default, `ContentEncoding::Auto` is used. If
|
|
||||||
`ContentEncoding::Auto` is selected, then the compression depends on the request's
|
|
||||||
`Accept-Encoding` header.
|
|
||||||
|
|
||||||
> `ContentEncoding::Identity` can be used to disable compression.
|
> `ContentEncoding::Identity` can be used to disable compression. If another content encoding is selected, the compression is enforced for that codec.
|
||||||
> If another content encoding is selected, the compression is enforced for that codec.
|
|
||||||
|
|
||||||
For example, to enable `brotli` for a single handler use `ContentEncoding::Br`:
|
For example, to enable `brotli` for a single handler use `ContentEncoding::Br`:
|
||||||
|
|
||||||
@ -64,20 +52,15 @@ or for the entire application:
|
|||||||
|
|
||||||
{{< include-example example="responses" file="brotli_two.rs" section="brotli-two" >}}
|
{{< include-example example="responses" file="brotli_two.rs" section="brotli-two" >}}
|
||||||
|
|
||||||
In this case we explicitly disable content compression by setting content encoding to
|
In this case we explicitly disable content compression by setting content encoding to an `Identity` value:
|
||||||
an `Identity` value:
|
|
||||||
|
|
||||||
{{< include-example example="responses" file="identity.rs" section="identity" >}}
|
{{< include-example example="responses" file="identity.rs" section="identity" >}}
|
||||||
|
|
||||||
When dealing with an already compressed body (for example when serving assets),
|
When dealing with an already compressed body (for example when serving assets), set the content encoding to `Identity` to avoid compressing the already compressed data and set the `content-encoding` header manually:
|
||||||
set the content encoding to `Identity` to avoid compressing the already compressed
|
|
||||||
data and set the `content-encoding` header manually:
|
|
||||||
|
|
||||||
{{< include-example example="responses" file="identity_two.rs" section="identity-two" >}}
|
{{< include-example example="responses" file="identity_two.rs" section="identity-two" >}}
|
||||||
|
|
||||||
Also it is possible to set default content encoding on application level, by
|
Also it is possible to set default content encoding on application level, by default `ContentEncoding::Auto` is used, which implies automatic content compression negotiation.
|
||||||
default `ContentEncoding::Auto` is used, which implies automatic content compression
|
|
||||||
negotiation.
|
|
||||||
|
|
||||||
{{< include-example example="responses" file="auto.rs" section="auto" >}}
|
{{< include-example example="responses" file="auto.rs" section="auto" >}}
|
||||||
|
|
||||||
|
@ -8,18 +8,13 @@ weight: 150
|
|||||||
|
|
||||||
The [**HttpServer**][httpserverstruct] type is responsible for serving HTTP requests.
|
The [**HttpServer**][httpserverstruct] type is responsible for serving HTTP requests.
|
||||||
|
|
||||||
`HttpServer` accepts an application factory as a parameter, and the application factory
|
`HttpServer` accepts an application factory as a parameter, and the application factory must have `Send` + `Sync` boundaries. More about that in the _multi-threading_ section.
|
||||||
must have `Send` + `Sync` boundaries. More about that in the *multi-threading* section.
|
|
||||||
|
|
||||||
To bind to a specific socket address, [`bind()`][bindmethod] must be used, and it may be
|
To bind to a specific socket address, [`bind()`][bindmethod] must be used, and it may be called multiple times. To bind ssl socket, [`bind_openssl()`][bindopensslmethod] or [`bind_rustls()`][bindrusttls] should be used. To run the HTTP server, use the `HttpServer::run()` method.
|
||||||
called multiple times. To bind ssl socket, [`bind_openssl()`][bindopensslmethod] or
|
|
||||||
[`bind_rustls()`][bindrusttls] should be used. To run the HTTP server, use the `HttpServer::run()`
|
|
||||||
method.
|
|
||||||
|
|
||||||
{{< include-example example="server" section="main" >}}
|
{{< include-example example="server" section="main" >}}
|
||||||
|
|
||||||
The `run()` method returns an instance of the [`Server`][server] type. Methods of server type
|
The `run()` method returns an instance of the [`Server`][server] type. Methods of server type could be used for managing the HTTP server
|
||||||
could be used for managing the HTTP server
|
|
||||||
|
|
||||||
- `pause()` - Pause accepting incoming connections
|
- `pause()` - Pause accepting incoming connections
|
||||||
- `resume()` - Resume accepting incoming connections
|
- `resume()` - Resume accepting incoming connections
|
||||||
@ -31,30 +26,19 @@ The following example shows how to start the HTTP server in a separate thread.
|
|||||||
|
|
||||||
## Multi-threading
|
## Multi-threading
|
||||||
|
|
||||||
`HttpServer` automatically starts a number of HTTP *workers*, by default this number is
|
`HttpServer` automatically starts a number of HTTP _workers_, by default this number is equal to the number of logical CPUs in the system. This number can be overridden with the [`HttpServer::workers()`][workers] method.
|
||||||
equal to the number of logical CPUs in the system. This number can be overridden with the
|
|
||||||
[`HttpServer::workers()`][workers] method.
|
|
||||||
|
|
||||||
{{< include-example example="server" file="workers.rs" section="workers" >}}
|
{{< include-example example="server" file="workers.rs" section="workers" >}}
|
||||||
|
|
||||||
Once the workers are created, they each receive a separate *application* instance to handle
|
Once the workers are created, they each receive a separate _application_ instance to handle requests. Application state is not shared between the threads, and handlers are free to manipulate their copy of the state with no concurrency concerns.
|
||||||
requests. Application state is not shared between the threads, and handlers are free to manipulate
|
|
||||||
their copy of the state with no concurrency concerns.
|
|
||||||
|
|
||||||
> Application state does not need to be `Send` or `Sync`, but application
|
> Application state does not need to be `Send` or `Sync`, but application factories must be `Send` + `Sync`.
|
||||||
factories must be `Send` + `Sync`.
|
|
||||||
|
|
||||||
To share state between worker threads, use an `Arc`. Special care should be taken once sharing and
|
To share state between worker threads, use an `Arc`. Special care should be taken once sharing and synchronization are introduced. In many cases, performance costs are inadvertently introduced as a result of locking the shared state for modifications.
|
||||||
synchronization are introduced. In many cases, performance costs are inadvertently introduced as a
|
|
||||||
result of locking the shared state for modifications.
|
|
||||||
|
|
||||||
In some cases these costs can be alleviated using more efficient locking strategies, for example
|
In some cases these costs can be alleviated using more efficient locking strategies, for example using [read/write locks](https://doc.rust-lang.org/std/sync/struct.RwLock.html) instead of [mutexes](https://doc.rust-lang.org/std/sync/struct.Mutex.html) to achieve non-exclusive locking, but the most performant implementations often tend to be ones in which no locking occurs at all.
|
||||||
using [read/write locks](https://doc.rust-lang.org/std/sync/struct.RwLock.html) instead of
|
|
||||||
[mutexes](https://doc.rust-lang.org/std/sync/struct.Mutex.html) to achieve non-exclusive locking,
|
|
||||||
but the most performant implementations often tend to be ones in which no locking occurs at all.
|
|
||||||
|
|
||||||
Since each worker thread processes its requests sequentially, handlers which block the current
|
Since each worker thread processes its requests sequentially, handlers which block the current thread will cause the current worker to stop processing new requests:
|
||||||
thread will cause the current worker to stop processing new requests:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn my_handler() -> impl Responder {
|
fn my_handler() -> impl Responder {
|
||||||
@ -63,9 +47,7 @@ fn my_handler() -> impl Responder {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For this reason, any long, non-cpu-bound operation (e.g. I/O, database operations, etc.) should be
|
For this reason, any long, non-cpu-bound operation (e.g. I/O, database operations, etc.) should be expressed as futures or asynchronous functions. Async handlers get executed concurrently by worker threads and thus don't block execution:
|
||||||
expressed as futures or asynchronous functions. Async handlers get executed concurrently by worker
|
|
||||||
threads and thus don't block execution:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
async fn my_handler() -> impl Responder {
|
async fn my_handler() -> impl Responder {
|
||||||
@ -74,15 +56,11 @@ async fn my_handler() -> impl Responder {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The same limitation applies to extractors as well. When a handler function receives an argument
|
The same limitation applies to extractors as well. When a handler function receives an argument which implements `FromRequest`, and that implementation blocks the current thread, the worker thread will block when running the handler. Special attention must be given when implementing extractors for this very reason, and they should also be implemented asynchronously where needed.
|
||||||
which implements `FromRequest`, and that implementation blocks the current thread, the worker thread
|
|
||||||
will block when running the handler. Special attention must be given when implementing extractors
|
|
||||||
for this very reason, and they should also be implemented asynchronously where needed.
|
|
||||||
|
|
||||||
## SSL
|
## SSL
|
||||||
|
|
||||||
There are two features for the ssl server: `rustls` and `openssl`. The `rustls` feature is for
|
There are two features for the ssl server: `rustls` and `openssl`. The `rustls` feature is for `rustls` integration and `openssl` is for `openssl`.
|
||||||
`rustls` integration and `openssl` is for `openssl`.
|
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -92,16 +70,17 @@ openssl = { version = "0.10" }
|
|||||||
|
|
||||||
{{< include-example example="server" file="ssl.rs" section="ssl" >}}
|
{{< include-example example="server" file="ssl.rs" section="ssl" >}}
|
||||||
|
|
||||||
> **Note**: the *HTTP/2.0* protocol requires [tls alpn][tlsalpn].
|
> **Note**: the _HTTP/2.0_ protocol requires [tls alpn][tlsalpn]. At the moment, only `openssl` has `alpn` support. For a full example, check out [examples/openssl][exampleopenssl].
|
||||||
> At the moment, only `openssl` has `alpn` support.
|
|
||||||
> For a full example, check out [examples/openssl][exampleopenssl].
|
|
||||||
|
|
||||||
To create the key.pem and cert.pem use the command. **Fill in your own subject**
|
To create the key.pem and cert.pem use the command. **Fill in your own subject**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
|
$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
|
||||||
-days 365 -sha256 -subj "/C=CN/ST=Fujian/L=Xiamen/O=TVlinux/OU=Org/CN=muro.lxd"
|
-days 365 -sha256 -subj "/C=CN/ST=Fujian/L=Xiamen/O=TVlinux/OU=Org/CN=muro.lxd"
|
||||||
```
|
```
|
||||||
|
|
||||||
To remove the password, then copy nopass.pem to key.pem
|
To remove the password, then copy nopass.pem to key.pem
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ openssl rsa -in key.pem -out nopass.pem
|
$ openssl rsa -in key.pem -out nopass.pem
|
||||||
```
|
```
|
||||||
@ -110,41 +89,33 @@ $ openssl rsa -in key.pem -out nopass.pem
|
|||||||
|
|
||||||
Actix can wait for requests on a keep-alive connection.
|
Actix can wait for requests on a keep-alive connection.
|
||||||
|
|
||||||
> *keep alive* connection behavior is defined by server settings.
|
> _keep alive_ connection behavior is defined by server settings.
|
||||||
|
|
||||||
- `75`, `Some(75)`, `KeepAlive::Timeout(75)` - enable 75 second *keep alive* timer.
|
- `75`, `Some(75)`, `KeepAlive::Timeout(75)` - enable 75 second _keep alive_ timer.
|
||||||
- `None` or `KeepAlive::Disabled` - disable *keep alive*.
|
- `None` or `KeepAlive::Disabled` - disable _keep alive_.
|
||||||
- `KeepAlive::Tcp(75)` - use `SO_KEEPALIVE` socket option.
|
- `KeepAlive::Tcp(75)` - use `SO_KEEPALIVE` socket option.
|
||||||
|
|
||||||
{{< include-example example="server" file="keep_alive.rs" section="keep-alive" >}}
|
{{< include-example example="server" file="keep_alive.rs" section="keep-alive" >}}
|
||||||
|
|
||||||
If the first option above is selected, then *keep alive* state is calculated based on the
|
If the first option above is selected, then _keep alive_ state is calculated based on the response's _connection-type_. By default `HttpResponse::connection_type` is not defined. In that case _keep alive_ is defined by the request's HTTP version.
|
||||||
response's *connection-type*. By default `HttpResponse::connection_type` is not
|
|
||||||
defined. In that case *keep alive* is defined by the request's HTTP version.
|
|
||||||
|
|
||||||
> *keep alive* is **off** for *HTTP/1.0* and is **on** for *HTTP/1.1* and *HTTP/2.0*.
|
> _keep alive_ is **off** for _HTTP/1.0_ and is **on** for _HTTP/1.1_ and _HTTP/2.0_.
|
||||||
|
|
||||||
*Connection type* can be changed with `HttpResponseBuilder::connection_type()` method.
|
_Connection type_ can be changed with `HttpResponseBuilder::connection_type()` method.
|
||||||
|
|
||||||
{{< include-example example="server" file="keep_alive_tp.rs" section="example" >}}
|
{{< include-example example="server" file="keep_alive_tp.rs" section="example" >}}
|
||||||
|
|
||||||
## Graceful shutdown
|
## Graceful shutdown
|
||||||
|
|
||||||
`HttpServer` supports graceful shutdown. After receiving a stop signal, workers
|
`HttpServer` supports graceful shutdown. After receiving a stop signal, workers have a specific amount of time to finish serving requests. Any workers still alive after the timeout are force-dropped. By default the shutdown timeout is set to 30 seconds. You can change this parameter with the [`HttpServer::shutdown_timeout()`][shutdowntimeout] method.
|
||||||
have a specific amount of time to finish serving requests. Any workers still alive after the
|
|
||||||
timeout are force-dropped. By default the shutdown timeout is set to 30 seconds. You
|
|
||||||
can change this parameter with the [`HttpServer::shutdown_timeout()`][shutdowntimeout]
|
|
||||||
method.
|
|
||||||
|
|
||||||
`HttpServer` handles several OS signals. *CTRL-C* is available on all OSs, other signals
|
`HttpServer` handles several OS signals. _CTRL-C_ is available on all OSs, other signals are available on unix systems.
|
||||||
are available on unix systems.
|
|
||||||
|
|
||||||
- *SIGINT* - Force shutdown workers
|
- _SIGINT_ - Force shutdown workers
|
||||||
- *SIGTERM* - Graceful shutdown workers
|
- _SIGTERM_ - Graceful shutdown workers
|
||||||
- *SIGQUIT* - Force shutdown workers
|
- _SIGQUIT_ - Force shutdown workers
|
||||||
|
|
||||||
> It is possible to disable signal handling with
|
> It is possible to disable signal handling with [`HttpServer::disable_signals()`][disablesignals] method.
|
||||||
[`HttpServer::disable_signals()`][disablesignals] method.
|
|
||||||
|
|
||||||
[server]: https://docs.rs/actix-web/3/actix_web/dev/struct.Server.html
|
[server]: https://docs.rs/actix-web/3/actix_web/dev/struct.Server.html
|
||||||
[httpserverstruct]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html
|
[httpserverstruct]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html
|
||||||
|
@ -6,26 +6,19 @@ weight: 230
|
|||||||
|
|
||||||
# Individual file
|
# Individual file
|
||||||
|
|
||||||
It is possible to serve static files with a custom path pattern and `NamedFile`. To
|
It is possible to serve static files with a custom path pattern and `NamedFile`. To match a path tail, we can use a `[.*]` regex.
|
||||||
match a path tail, we can use a `[.*]` regex.
|
|
||||||
|
|
||||||
{{< include-example example="static-files" file="main.rs" section="individual-file" >}}
|
{{< include-example example="static-files" file="main.rs" section="individual-file" >}}
|
||||||
|
|
||||||
# Directory
|
# Directory
|
||||||
|
|
||||||
To serve files from specific directories and sub-directories, `Files` can be used.
|
To serve files from specific directories and sub-directories, `Files` can be used. `Files` must be registered with an `App::service()` method, otherwise it will be unable to serve sub-paths.
|
||||||
`Files` must be registered with an `App::service()` method, otherwise
|
|
||||||
it will be unable to serve sub-paths.
|
|
||||||
|
|
||||||
{{< include-example example="static-files" file="directory.rs" section="directory" >}}
|
{{< include-example example="static-files" file="directory.rs" section="directory" >}}
|
||||||
|
|
||||||
By default files listing for sub-directories is disabled. Attempt to load directory
|
By default files listing for sub-directories is disabled. Attempt to load directory listing will return _404 Not Found_ response. To enable files listing, use [_Files::show_files_listing()_][showfileslisting] method.
|
||||||
listing will return *404 Not Found* response. To enable files listing, use
|
|
||||||
[*Files::show_files_listing()*][showfileslisting]
|
|
||||||
method.
|
|
||||||
|
|
||||||
Instead of showing files listing for directory, it is possible to redirect to a specific
|
Instead of showing files listing for directory, it is possible to redirect to a specific index file. Use the [_Files::index_file()_][indexfile] method to configure this redirect.
|
||||||
index file. Use the [*Files::index_file()*][indexfile] method to configure this redirect.
|
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
@ -35,8 +28,7 @@ index file. Use the [*Files::index_file()*][indexfile] method to configure this
|
|||||||
- `use_etag` - specifies whether `ETag` shall be calculated and included in headers.
|
- `use_etag` - specifies whether `ETag` shall be calculated and included in headers.
|
||||||
- `use_last_modified` - specifies whether file modified timestamp should be used and added to `Last-Modified` header.
|
- `use_last_modified` - specifies whether file modified timestamp should be used and added to `Last-Modified` header.
|
||||||
|
|
||||||
All of the above methods are optional and provided with the best defaults, But it is
|
All of the above methods are optional and provided with the best defaults, But it is possible to customize any of them.
|
||||||
possible to customize any of them.
|
|
||||||
|
|
||||||
{{< include-example example="static-files" file="configuration.rs" section="config-one" >}}
|
{{< include-example example="static-files" file="configuration.rs" section="config-one" >}}
|
||||||
|
|
||||||
|
@ -6,43 +6,33 @@ weight: 215
|
|||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
|
|
||||||
Every application should be well tested. Actix-web provides tools to perform unit and
|
Every application should be well tested. Actix-web provides tools to perform unit and integration tests.
|
||||||
integration tests.
|
|
||||||
|
|
||||||
# Unit Tests
|
# Unit Tests
|
||||||
|
|
||||||
For unit testing, actix-web provides a request builder type.
|
For unit testing, actix-web provides a request builder type. [_TestRequest_][testrequest] implements a builder-like pattern. You can generate a `HttpRequest` instance with `to_http_request()` and call your handler with it.
|
||||||
[*TestRequest*][testrequest] implements a builder-like pattern. You can generate a
|
|
||||||
`HttpRequest` instance with `to_http_request()` and call your handler with it.
|
|
||||||
|
|
||||||
{{< include-example example="testing" file="main.rs" section="unit-tests" >}}
|
{{< include-example example="testing" file="main.rs" section="unit-tests" >}}
|
||||||
|
|
||||||
# Integration tests
|
# Integration tests
|
||||||
|
|
||||||
There are a few methods for testing your application. Actix-web can be used
|
There are a few methods for testing your application. Actix-web can be used to run the application with specific handlers in a real HTTP server.
|
||||||
to run the application with specific handlers in a real HTTP server.
|
|
||||||
|
|
||||||
`TestRequest::get()`, `TestRequest::post()` and other
|
`TestRequest::get()`, `TestRequest::post()` and other methods can be used to send requests to the test server.
|
||||||
methods can be used to send requests to the test server.
|
|
||||||
|
|
||||||
To create a `Service` for testing, use the `test::init_service` method which accepts a
|
To create a `Service` for testing, use the `test::init_service` method which accepts a regular `App` builder.
|
||||||
regular `App` builder.
|
|
||||||
|
|
||||||
> Check the [API documentation][actixdocs] for more information.
|
> Check the [API documentation][actixdocs] for more information.
|
||||||
|
|
||||||
{{< include-example example="testing" file="integration_one.rs" section="integration-one" >}}
|
{{< include-example example="testing" file="integration_one.rs" section="integration-one" >}}
|
||||||
|
|
||||||
If you need more complex application configuration, testing should be very similar to creating
|
If you need more complex application configuration, testing should be very similar to creating the normal application. For example, you may need to initialize application state. Create an `App` with a `data` method and attach state just like you would from a normal application.
|
||||||
the normal application. For example, you may need to initialize application state. Create an
|
|
||||||
`App` with a `data` method and attach state just like you would from a normal application.
|
|
||||||
|
|
||||||
{{< include-example example="testing" file="integration_two.rs" section="integration-two" >}}
|
{{< include-example example="testing" file="integration_two.rs" section="integration-two" >}}
|
||||||
|
|
||||||
# Stream response tests
|
# Stream response tests
|
||||||
|
|
||||||
If you need to test stream generation, it would be enough to call `take_body()` and convert a
|
If you need to test stream generation, it would be enough to call `take_body()` and convert a resulting [_ResponseBody_][responsebody] into a future and execute it, for example when testing [_Server Sent Events_][serversentevents].
|
||||||
resulting [*ResponseBody*][responsebody] into a future and execute it, for example when testing
|
|
||||||
[*Server Sent Events*][serversentevents].
|
|
||||||
|
|
||||||
{{< include-example example="testing" file="stream_response.rs" section="stream-response" >}}
|
{{< include-example example="testing" file="stream_response.rs" section="stream-response" >}}
|
||||||
|
|
||||||
|
@ -6,102 +6,59 @@ weight: 190
|
|||||||
|
|
||||||
# URL Dispatch
|
# URL Dispatch
|
||||||
|
|
||||||
URL dispatch provides a simple way for mapping URLs to handler code using a simple pattern
|
URL dispatch provides a simple way for mapping URLs to handler code using a simple pattern matching language. If one of the patterns matches the path information associated with a request, a particular handler object is invoked.
|
||||||
matching language. If one of the patterns matches the path information associated with a request,
|
|
||||||
a particular handler object is invoked.
|
|
||||||
|
|
||||||
> A request handler is a function that accepts zero or more parameters that can be extracted
|
> A request handler is a function that accepts zero or more parameters that can be extracted from a request (i.e., [_impl FromRequest_][implfromrequest]) and returns a type that can be converted into an HttpResponse (i.e., [_impl Responder_][implresponder]). More information is available in the [handler section][handlersection].
|
||||||
> from a request (i.e., [*impl FromRequest*][implfromrequest]) and returns a type that can
|
|
||||||
> be converted into an HttpResponse (i.e., [*impl Responder*][implresponder]). More information
|
|
||||||
> is available in the [handler section][handlersection].
|
|
||||||
|
|
||||||
# Resource configuration
|
# Resource configuration
|
||||||
|
|
||||||
Resource configuration is the act of adding a new resources to an application. A resource
|
Resource configuration is the act of adding a new resources to an application. A resource has a name, which acts as an identifier to be used for URL generation. The name also allows developers to add routes to existing resources. A resource also has a pattern, meant to match against the _PATH_ portion of a _URL_ (the portion following the scheme and port, e.g. _/foo/bar_ in the _URL_ _http://localhost:8080/foo/bar?q=value_). It does not match against the _QUERY_ portion (the portion that follows _?_, e.g. _q=value_ in _http://localhost:8080/foo/bar?q=value_).
|
||||||
has a name, which acts as an identifier to be used for URL generation. The name also
|
|
||||||
allows developers to add routes to existing resources. A resource also has a pattern,
|
|
||||||
meant to match against the *PATH* portion of a *URL* (the portion following the scheme and
|
|
||||||
port, e.g. */foo/bar* in the *URL* *http://localhost:8080/foo/bar?q=value*). It does not
|
|
||||||
match against the *QUERY* portion (the portion that follows *?*, e.g. *q=value*
|
|
||||||
in *http://localhost:8080/foo/bar?q=value*).
|
|
||||||
|
|
||||||
The [*App::route()*][approute] method provides simple way of registering routes. This
|
The [_App::route()_][approute] method provides simple way of registering routes. This method adds a single route to application routing table. This method accepts a _path pattern_, _HTTP method_ and a handler function. `route()` method could be called multiple times for the same path, in that case, multiple routes register for the same resource path.
|
||||||
method adds a single route to application routing table. This method accepts a *path pattern*,
|
|
||||||
*HTTP method* and a handler function. `route()` method could be called multiple times
|
|
||||||
for the same path, in that case, multiple routes register for the same resource path.
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" section="main" >}}
|
{{< include-example example="url-dispatch" section="main" >}}
|
||||||
|
|
||||||
While *App::route()* provides simple way of registering routes, to access complete resource
|
While _App::route()_ provides simple way of registering routes, to access complete resource configuration, a different method has to be used. The [_App::service()_][appservice] method adds a single [resource][webresource] to application routing table. This method accepts a _path pattern_, guards, and one or more routes.
|
||||||
configuration, a different method has to be used. The [*App::service()*][appservice] method
|
|
||||||
adds a single [resource][webresource] to application routing table. This method accepts a
|
|
||||||
*path pattern*, guards, and one or more routes.
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="resource.rs" section="resource" >}}
|
{{< include-example example="url-dispatch" file="resource.rs" section="resource" >}}
|
||||||
|
|
||||||
If a resource does not contain any route or does not have any matching routes, it
|
If a resource does not contain any route or does not have any matching routes, it returns _NOT FOUND_ HTTP response.
|
||||||
returns *NOT FOUND* HTTP response.
|
|
||||||
|
|
||||||
## Configuring a Route
|
## Configuring a Route
|
||||||
|
|
||||||
Resource contains a set of routes. Each route in turn has a set of `guards` and a handler.
|
Resource contains a set of routes. Each route in turn has a set of `guards` and a handler. New routes can be created with `Resource::route()` method which returns a reference to new _Route_ instance. By default the _route_ does not contain any guards, so matches all requests and the default handler is `HttpNotFound`.
|
||||||
New routes can be created with `Resource::route()` method which returns a reference
|
|
||||||
to new *Route* instance. By default the *route* does not contain any guards, so matches
|
|
||||||
all requests and the default handler is `HttpNotFound`.
|
|
||||||
|
|
||||||
The application routes incoming requests based on route criteria which are defined during
|
The application routes incoming requests based on route criteria which are defined during resource registration and route registration. Resource matches all routes it contains in the order the routes were registered via `Resource::route()`.
|
||||||
resource registration and route registration. Resource matches all routes it contains in
|
|
||||||
the order the routes were registered via `Resource::route()`.
|
|
||||||
|
|
||||||
> A *Route* can contain any number of *guards* but only one handler.
|
> A _Route_ can contain any number of _guards_ but only one handler.
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="cfg.rs" section="cfg" >}}
|
{{< include-example example="url-dispatch" file="cfg.rs" section="cfg" >}}
|
||||||
|
|
||||||
In this example, `HttpResponse::Ok()` is returned for *GET* requests if the request
|
In this example, `HttpResponse::Ok()` is returned for _GET_ requests if the request contains `Content-Type` header, the value of this header is _text/plain_, and path equals to `/path`.
|
||||||
contains `Content-Type` header, the value of this header is *text/plain*, and path
|
|
||||||
equals to `/path`.
|
|
||||||
|
|
||||||
If a resource can not match any route, a "NOT FOUND" response is returned.
|
If a resource can not match any route, a "NOT FOUND" response is returned.
|
||||||
|
|
||||||
[*ResourceHandler::route()*][resourcehandler] returns a [*Route*][route] object. Route
|
[_ResourceHandler::route()_][resourcehandler] returns a [_Route_][route] object. Route can be configured with a builder-like pattern. Following configuration methods are available:
|
||||||
can be configured with a builder-like pattern. Following configuration methods are available:
|
|
||||||
|
|
||||||
* [*Route::guard()*][routeguard] registers a new guard. Any number of guards can be
|
- [_Route::guard()_][routeguard] registers a new guard. Any number of guards can be registered for each route.
|
||||||
registered for each route.
|
- [_Route::method()_][routemethod] registers a method guard. Any number of guards can be registered for each route.
|
||||||
* [*Route::method()*][routemethod] registers a method guard. Any number of guards can be
|
- [_Route::to()_][routeto] registers an async handler function for this route. Only one handler can be registered. Usually handler registration is the last config operation.
|
||||||
registered for each route.
|
|
||||||
* [*Route::to()*][routeto] registers an async handler function for this route.
|
|
||||||
Only one handler can be registered. Usually handler registration is the last config operation.
|
|
||||||
|
|
||||||
# Route matching
|
# Route matching
|
||||||
|
|
||||||
The main purpose of route configuration is to match (or not match) the request's `path`
|
The main purpose of route configuration is to match (or not match) the request's `path` against a URL path pattern. `path` represents the path portion of the URL that was requested.
|
||||||
against a URL path pattern. `path` represents the path portion of the URL that was requested.
|
|
||||||
|
|
||||||
The way that *actix-web* does this is very simple. When a request enters the system,
|
The way that _actix-web_ does this is very simple. When a request enters the system, for each resource configuration declaration present in the system, actix checks the request's path against the pattern declared. This checking happens in the order that the routes were declared via `App::service()` method. If resource can not be found, the _default resource_ is used as the matched resource.
|
||||||
for each resource configuration declaration present in the system, actix checks
|
|
||||||
the request's path against the pattern declared. This checking happens in the order that
|
|
||||||
the routes were declared via `App::service()` method. If resource can not be found,
|
|
||||||
the *default resource* is used as the matched resource.
|
|
||||||
|
|
||||||
When a route configuration is declared, it may contain route guard arguments. All route
|
When a route configuration is declared, it may contain route guard arguments. All route guards associated with a route declaration must be `true` for the route configuration to be used for a given request during a check. If any guard in the set of route guard arguments provided to a route configuration returns `false` during a check, that route is skipped and route matching continues through the ordered set of routes.
|
||||||
guards associated with a route declaration must be `true` for the route configuration to
|
|
||||||
be used for a given request during a check. If any guard in the set of route guard
|
|
||||||
arguments provided to a route configuration returns `false` during a check, that route is
|
|
||||||
skipped and route matching continues through the ordered set of routes.
|
|
||||||
|
|
||||||
If any route matches, the route matching process stops and the handler associated with
|
If any route matches, the route matching process stops and the handler associated with the route is invoked. If no route matches after all route patterns are exhausted, a _NOT FOUND_ response get returned.
|
||||||
the route is invoked. If no route matches after all route patterns are exhausted, a
|
|
||||||
*NOT FOUND* response get returned.
|
|
||||||
|
|
||||||
# Resource pattern syntax
|
# Resource pattern syntax
|
||||||
|
|
||||||
The syntax of the pattern matching language used by actix in the pattern
|
The syntax of the pattern matching language used by actix in the pattern argument is straightforward.
|
||||||
argument is straightforward.
|
|
||||||
|
|
||||||
The pattern used in route configuration may start with a slash character. If the pattern
|
The pattern used in route configuration may start with a slash character. If the pattern does not start with a slash character, an implicit slash will be prepended to it at matching time. For example, the following patterns are equivalent:
|
||||||
does not start with a slash character, an implicit slash will be prepended
|
|
||||||
to it at matching time. For example, the following patterns are equivalent:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
{foo}/bar/baz
|
{foo}/bar/baz
|
||||||
@ -113,15 +70,11 @@ and:
|
|||||||
/{foo}/bar/baz
|
/{foo}/bar/baz
|
||||||
```
|
```
|
||||||
|
|
||||||
A *variable part* (replacement marker) is specified in the form *{identifier}*,
|
A _variable part_ (replacement marker) is specified in the form _{identifier}_, where this means "accept any characters up to the next slash character and use this as the name in the `HttpRequest.match_info()` object".
|
||||||
where this means "accept any characters up to the next slash character and use this
|
|
||||||
as the name in the `HttpRequest.match_info()` object".
|
|
||||||
|
|
||||||
A replacement marker in a pattern matches the regular expression `[^{}/]+`.
|
A replacement marker in a pattern matches the regular expression `[^{}/]+`.
|
||||||
|
|
||||||
A match_info is the `Params` object representing the dynamic parts extracted from a
|
A match_info is the `Params` object representing the dynamic parts extracted from a _URL_ based on the routing pattern. It is available as _request.match_info_. For example, the following pattern defines one literal segment (foo) and two replacement markers (baz, and bar):
|
||||||
*URL* based on the routing pattern. It is available as *request.match_info*. For example, the
|
|
||||||
following pattern defines one literal segment (foo) and two replacement markers (baz, and bar):
|
|
||||||
|
|
||||||
```
|
```
|
||||||
foo/{baz}/{bar}
|
foo/{baz}/{bar}
|
||||||
@ -141,18 +94,13 @@ foo/1/2/ -> No match (trailing slash)
|
|||||||
bar/abc/def -> First segment literal mismatch
|
bar/abc/def -> First segment literal mismatch
|
||||||
```
|
```
|
||||||
|
|
||||||
The match for a segment replacement marker in a segment will be done only up to
|
The match for a segment replacement marker in a segment will be done only up to the first non-alphanumeric character in the segment in the pattern. So, for instance, if this route pattern was used:
|
||||||
the first non-alphanumeric character in the segment in the pattern. So, for instance,
|
|
||||||
if this route pattern was used:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
foo/{name}.html
|
foo/{name}.html
|
||||||
```
|
```
|
||||||
|
|
||||||
The literal path */foo/biz.html* will match the above route pattern, and the match result
|
The literal path _/foo/biz.html_ will match the above route pattern, and the match result will be `Params {'name': 'biz'}`. However, the literal path _/foo/biz_ will not match, because it does not contain a literal _.html_ at the end of the segment represented by _{name}.html_ (it only contains biz, not biz.html).
|
||||||
will be `Params {'name': 'biz'}`. However, the literal path */foo/biz* will not match,
|
|
||||||
because it does not contain a literal *.html* at the end of the segment represented
|
|
||||||
by *{name}.html* (it only contains biz, not biz.html).
|
|
||||||
|
|
||||||
To capture both segments, two replacement markers can be used:
|
To capture both segments, two replacement markers can be used:
|
||||||
|
|
||||||
@ -160,28 +108,16 @@ To capture both segments, two replacement markers can be used:
|
|||||||
foo/{name}.{ext}
|
foo/{name}.{ext}
|
||||||
```
|
```
|
||||||
|
|
||||||
The literal path */foo/biz.html* will match the above route pattern, and the match
|
The literal path _/foo/biz.html_ will match the above route pattern, and the match result will be _Params {'name': 'biz', 'ext': 'html'}_. This occurs because there is a literal part of _._ (period) between the two replacement markers _{name}_ and _{ext}_.
|
||||||
result will be *Params {'name': 'biz', 'ext': 'html'}*. This occurs because there is a
|
|
||||||
literal part of *.* (period) between the two replacement markers *{name}* and *{ext}*.
|
|
||||||
|
|
||||||
Replacement markers can optionally specify a regular expression which will be used to decide
|
Replacement markers can optionally specify a regular expression which will be used to decide whether a path segment should match the marker. To specify that a replacement marker should match only a specific set of characters as defined by a regular expression, you must use a slightly extended form of replacement marker syntax. Within braces, the replacement marker name must be followed by a colon, then directly thereafter, the regular expression. The default regular expression associated with a replacement marker _[^/]+_ matches one or more characters which are not a slash. For example, under the hood, the replacement marker _{foo}_ can more verbosely be spelled as _{foo:[^/]+}_. You can change this to be an arbitrary regular expression to match an arbitrary sequence of characters, such as _{foo:\d+}_ to match only digits.
|
||||||
whether a path segment should match the marker. To specify that a replacement marker should
|
|
||||||
match only a specific set of characters as defined by a regular expression, you must use a
|
|
||||||
slightly extended form of replacement marker syntax. Within braces, the replacement marker
|
|
||||||
name must be followed by a colon, then directly thereafter, the regular expression. The default
|
|
||||||
regular expression associated with a replacement marker *[^/]+* matches one or more characters
|
|
||||||
which are not a slash. For example, under the hood, the replacement marker *{foo}* can more
|
|
||||||
verbosely be spelled as *{foo:[^/]+}*. You can change this to be an arbitrary regular expression
|
|
||||||
to match an arbitrary sequence of characters, such as *{foo:\d+}* to match only digits.
|
|
||||||
|
|
||||||
Segments must contain at least one character in order to match a segment replacement marker.
|
Segments must contain at least one character in order to match a segment replacement marker. For example, for the URL _/abc/_:
|
||||||
For example, for the URL */abc/*:
|
|
||||||
|
|
||||||
* */abc/{foo}* will not match.
|
- _/abc/{foo}_ will not match.
|
||||||
* */{foo}/* will match.
|
- _/{foo}/_ will match.
|
||||||
|
|
||||||
> **Note**: path will be URL-unquoted and decoded into valid unicode string before
|
> **Note**: path will be URL-unquoted and decoded into valid unicode string before matching pattern and values representing matched path segments will be URL-unquoted too.
|
||||||
> matching pattern and values representing matched path segments will be URL-unquoted too.
|
|
||||||
|
|
||||||
So for instance, the following pattern:
|
So for instance, the following pattern:
|
||||||
|
|
||||||
@ -201,9 +137,7 @@ The match dictionary will look like so (the value is URL-decoded):
|
|||||||
Params {'bar': 'La Pe\xf1a'}
|
Params {'bar': 'La Pe\xf1a'}
|
||||||
```
|
```
|
||||||
|
|
||||||
Literal strings in the path segment should represent the decoded value of the
|
Literal strings in the path segment should represent the decoded value of the path provided to actix. You don't want to use a URL-encoded value in the pattern. For example, rather than this:
|
||||||
path provided to actix. You don't want to use a URL-encoded value in the pattern.
|
|
||||||
For example, rather than this:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
/Foo%20Bar/{baz}
|
/Foo%20Bar/{baz}
|
||||||
@ -230,8 +164,7 @@ foo/abc/def/a/b/c -> Params {'bar': 'abc', 'tail': 'def/a/b/c'}
|
|||||||
|
|
||||||
# Scoping Routes
|
# Scoping Routes
|
||||||
|
|
||||||
Scoping helps you organize routes sharing common root paths. You can nest
|
Scoping helps you organize routes sharing common root paths. You can nest scopes within scopes.
|
||||||
scopes within scopes.
|
|
||||||
|
|
||||||
Suppose that you want to organize paths to endpoints used to view "Users". Such paths may include:
|
Suppose that you want to organize paths to endpoints used to view "Users". Such paths may include:
|
||||||
|
|
||||||
@ -239,21 +172,17 @@ Suppose that you want to organize paths to endpoints used to view "Users". Such
|
|||||||
- /users/show
|
- /users/show
|
||||||
- /users/show/{id}
|
- /users/show/{id}
|
||||||
|
|
||||||
|
|
||||||
A scoped layout of these paths would appear as follows
|
A scoped layout of these paths would appear as follows
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="scope.rs" section="scope" >}}
|
{{< include-example example="url-dispatch" file="scope.rs" section="scope" >}}
|
||||||
|
|
||||||
A *scoped* path can contain variable path segments as resources. Consistent with
|
A _scoped_ path can contain variable path segments as resources. Consistent with un-scoped paths.
|
||||||
un-scoped paths.
|
|
||||||
|
|
||||||
You can get variable path segments from `HttpRequest::match_info()`.
|
You can get variable path segments from `HttpRequest::match_info()`. [`Path` extractor][pathextractor] also is able to extract scope level variable segments.
|
||||||
[`Path` extractor][pathextractor] also is able to extract scope level variable segments.
|
|
||||||
|
|
||||||
# Match information
|
# Match information
|
||||||
|
|
||||||
All values representing matched path segments are available in [`HttpRequest::match_info`][matchinfo].
|
All values representing matched path segments are available in [`HttpRequest::match_info`][matchinfo]. Specific values can be retrieved with [`Path::get()`][pathget].
|
||||||
Specific values can be retrieved with [`Path::get()`][pathget].
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="minfo.rs" section="minfo" >}}
|
{{< include-example example="url-dispatch" file="minfo.rs" section="minfo" >}}
|
||||||
|
|
||||||
@ -261,38 +190,27 @@ For this example for path '/a/1/2/', values v1 and v2 will resolve to "1" and "2
|
|||||||
|
|
||||||
## Path information extractor
|
## Path information extractor
|
||||||
|
|
||||||
Actix provides functionality for type safe path information extraction. [*Path*][pathstruct]
|
Actix provides functionality for type safe path information extraction. [_Path_][pathstruct] extracts information, destination type could be defined in several different forms. Simplest approach is to use `tuple` type. Each element in tuple must correspond to one element from path pattern. i.e. you can match path pattern `/{id}/{username}/` against `Path<(u32, String)>` type, but `Path<(String, String, String)>` type will always fail.
|
||||||
extracts information, destination type could be defined in several different forms. Simplest
|
|
||||||
approach is to use `tuple` type. Each element in tuple must correspond to one element from
|
|
||||||
path pattern. i.e. you can match path pattern `/{id}/{username}/` against
|
|
||||||
`Path<(u32, String)>` type, but `Path<(String, String, String)>` type will always fail.
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="path.rs" section="path" >}}
|
{{< include-example example="url-dispatch" file="path.rs" section="path" >}}
|
||||||
|
|
||||||
It also possible to extract path pattern information to a struct. In this case,
|
It also possible to extract path pattern information to a struct. In this case, this struct must implement _serde's_ `Deserialize` trait.
|
||||||
this struct must implement *serde's* `Deserialize` trait.
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="path2.rs" section="path" >}}
|
{{< include-example example="url-dispatch" file="path2.rs" section="path" >}}
|
||||||
|
|
||||||
[*Query*][query] provides similar functionality for request query parameters.
|
[_Query_][query] provides similar functionality for request query parameters.
|
||||||
|
|
||||||
# Generating resource URLs
|
# Generating resource URLs
|
||||||
|
|
||||||
Use the [*HttpRequest.url_for()*][urlfor] method to generate URLs based on resource
|
Use the [_HttpRequest.url_for()_][urlfor] method to generate URLs based on resource patterns. For example, if you've configured a resource with the name "foo" and the pattern "{a}/{b}/{c}", you might do this:
|
||||||
patterns. For example, if you've configured a resource with the name "foo" and the
|
|
||||||
pattern "{a}/{b}/{c}", you might do this:
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="urls.rs" section="url" >}}
|
{{< include-example example="url-dispatch" file="urls.rs" section="url" >}}
|
||||||
|
|
||||||
This would return something like the string *http://example.com/test/1/2/3* (at least if
|
This would return something like the string *http://example.com/test/1/2/3* (at least if the current protocol and hostname implied http://example.com). `url_for()` method returns [_Url object_][urlobj] so you can modify this url (add query parameters, anchor, etc). `url_for()` could be called only for _named_ resources otherwise error get returned.
|
||||||
the current protocol and hostname implied http://example.com). `url_for()` method
|
|
||||||
returns [*Url object*][urlobj] so you can modify this url (add query parameters, anchor, etc).
|
|
||||||
`url_for()` could be called only for *named* resources otherwise error get returned.
|
|
||||||
|
|
||||||
# External resources
|
# External resources
|
||||||
|
|
||||||
Resources that are valid URLs, can be registered as external resources. They are useful
|
Resources that are valid URLs, can be registered as external resources. They are useful for URL generation purposes only and are never considered for matching at request time.
|
||||||
for URL generation purposes only and are never considered for matching at request time.
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="url_ext.rs" section="ext" >}}
|
{{< include-example example="url-dispatch" file="url_ext.rs" section="ext" >}}
|
||||||
|
|
||||||
@ -300,77 +218,56 @@ for URL generation purposes only and are never considered for matching at reques
|
|||||||
|
|
||||||
By normalizing it means:
|
By normalizing it means:
|
||||||
|
|
||||||
* To add a trailing slash to the path.
|
- To add a trailing slash to the path.
|
||||||
* To replace multiple slashes with one.
|
- To replace multiple slashes with one.
|
||||||
|
|
||||||
The handler returns as soon as it finds a path that resolves correctly. The order of
|
The handler returns as soon as it finds a path that resolves correctly. The order of normalization conditions, if all are enabled, is 1) merge, 2) both merge and append and 3) append. If the path resolves with at least one of those conditions, it will redirect to the new path.
|
||||||
normalization conditions, if all are enabled, is 1) merge, 2) both merge and append and
|
|
||||||
3) append. If the path resolves with at least one of those conditions, it will redirect
|
|
||||||
to the new path.
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="norm.rs" section="norm" >}}
|
{{< include-example example="url-dispatch" file="norm.rs" section="norm" >}}
|
||||||
|
|
||||||
In this example `//resource///` will be redirected to `/resource/`.
|
In this example `//resource///` will be redirected to `/resource/`.
|
||||||
|
|
||||||
In this example, the path normalization handler is registered for all methods,
|
In this example, the path normalization handler is registered for all methods, but you should not rely on this mechanism to redirect _POST_ requests. The redirect of the slash-appending _Not Found_ will turn a _POST_ request into a GET, losing any _POST_ data in the original request.
|
||||||
but you should not rely on this mechanism to redirect *POST* requests. The redirect of the
|
|
||||||
slash-appending *Not Found* will turn a *POST* request into a GET, losing any
|
|
||||||
*POST* data in the original request.
|
|
||||||
|
|
||||||
It is possible to register path normalization only for *GET* requests only:
|
It is possible to register path normalization only for _GET_ requests only:
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="norm2.rs" section="norm" >}}
|
{{< include-example example="url-dispatch" file="norm2.rs" section="norm" >}}
|
||||||
|
|
||||||
## Using an Application Prefix to Compose Applications
|
## Using an Application Prefix to Compose Applications
|
||||||
|
|
||||||
The `web::scope()` method allows to set a specific application scope. This scope represents
|
The `web::scope()` method allows to set a specific application scope. This scope represents a resource prefix that will be prepended to all resource patterns added by the resource configuration. This can be used to help mount a set of routes at a different location than the included callable's author intended while still maintaining the same resource names.
|
||||||
a resource prefix that will be prepended to all resource patterns added by the resource
|
|
||||||
configuration. This can be used to help mount a set of routes at a different location
|
|
||||||
than the included callable's author intended while still maintaining the same resource names.
|
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="scope.rs" section="scope" >}}
|
{{< include-example example="url-dispatch" file="scope.rs" section="scope" >}}
|
||||||
|
|
||||||
In the above example, the *show_users* route will have an effective route pattern of
|
In the above example, the _show_users_ route will have an effective route pattern of _/users/show_ instead of _/show_ because the application's scope will be prepended to the pattern. The route will then only match if the URL path is _/users/show_, and when the `HttpRequest.url_for()` function is called with the route name show_users, it will generate a URL with that same path.
|
||||||
*/users/show* instead of */show* because the application's scope will be prepended
|
|
||||||
to the pattern. The route will then only match if the URL path is */users/show*,
|
|
||||||
and when the `HttpRequest.url_for()` function is called with the route name show_users,
|
|
||||||
it will generate a URL with that same path.
|
|
||||||
|
|
||||||
# Custom route guard
|
# Custom route guard
|
||||||
|
|
||||||
You can think of a guard as a simple function that accepts a *request* object reference
|
You can think of a guard as a simple function that accepts a _request_ object reference and returns _true_ or _false_. Formally, a guard is any object that implements the [`Guard`][guardtrait] trait. Actix provides several predicates, you can check [functions section][guardfuncs] of API docs.
|
||||||
and returns *true* or *false*. Formally, a guard is any object that implements the
|
|
||||||
[`Guard`][guardtrait] trait. Actix provides several predicates, you can check
|
|
||||||
[functions section][guardfuncs] of API docs.
|
|
||||||
|
|
||||||
Here is a simple guard that check that a request contains a specific *header*:
|
Here is a simple guard that check that a request contains a specific _header_:
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="guard.rs" section="guard" >}}
|
{{< include-example example="url-dispatch" file="guard.rs" section="guard" >}}
|
||||||
|
|
||||||
In this example, *index* handler will be called only if request contains *CONTENT-TYPE* header.
|
In this example, _index_ handler will be called only if request contains _CONTENT-TYPE_ header.
|
||||||
|
|
||||||
Guards can not access or modify the request object, but it is possible to store extra
|
Guards can not access or modify the request object, but it is possible to store extra information in [request extensions][requestextensions].
|
||||||
information in [request extensions][requestextensions].
|
|
||||||
|
|
||||||
## Modifying guard values
|
## Modifying guard values
|
||||||
|
|
||||||
You can invert the meaning of any predicate value by wrapping it in a `Not` predicate.
|
You can invert the meaning of any predicate value by wrapping it in a `Not` predicate. For example, if you want to return "METHOD NOT ALLOWED" response for all methods except "GET":
|
||||||
For example, if you want to return "METHOD NOT ALLOWED" response for all methods
|
|
||||||
except "GET":
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="guard2.rs" section="guard2" >}}
|
{{< include-example example="url-dispatch" file="guard2.rs" section="guard2" >}}
|
||||||
|
|
||||||
The `Any` guard accepts a list of guards and matches if any of the supplied
|
The `Any` guard accepts a list of guards and matches if any of the supplied guards match. i.e:
|
||||||
guards match. i.e:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
guard::Any(guard::Get()).or(guard::Post())
|
guard::Any(guard::Get()).or(guard::Post())
|
||||||
```
|
```
|
||||||
|
|
||||||
The `All` guard accepts a list of guard and matches if all of the supplied
|
The `All` guard accepts a list of guard and matches if all of the supplied guards match. i.e:
|
||||||
guards match. i.e:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
guard::All(guard::Get()).and(guard::Header("content-type", "plain/text"))
|
guard::All(guard::Get()).and(guard::Header("content-type", "plain/text"))
|
||||||
@ -378,11 +275,7 @@ guard::All(guard::Get()).and(guard::Header("content-type", "plain/text"))
|
|||||||
|
|
||||||
# Changing the default Not Found response
|
# Changing the default Not Found response
|
||||||
|
|
||||||
If the path pattern can not be found in the routing table or a resource can not find matching
|
If the path pattern can not be found in the routing table or a resource can not find matching route, the default resource is used. The default response is _NOT FOUND_. It is possible to override the _NOT FOUND_ response with `App::default_service()`. This method accepts a _configuration function_ same as normal resource configuration with `App::service()` method.
|
||||||
route, the default resource is used. The default response is *NOT FOUND*.
|
|
||||||
It is possible to override the *NOT FOUND* response with `App::default_service()`.
|
|
||||||
This method accepts a *configuration function* same as normal resource configuration
|
|
||||||
with `App::service()` method.
|
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" file="dhandler.rs" section="default" >}}
|
{{< include-example example="url-dispatch" file="dhandler.rs" section="default" >}}
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ menu: docs_protocols
|
|||||||
weight: 240
|
weight: 240
|
||||||
---
|
---
|
||||||
|
|
||||||
Actix-web supports WebSockets with the `actix-web-actors` crate. It is possible to convert a
|
Actix-web supports WebSockets with the `actix-web-actors` crate. It is possible to convert a request's `Payload` to a stream of [_ws::Message_][message] with a [_web::Payload_][payload] and then use stream combinators to handle actual messages, but it is simpler to handle websocket communications with an http actor.
|
||||||
request's `Payload` to a stream of [*ws::Message*][message] with a [*web::Payload*][payload]
|
|
||||||
and then use stream combinators to handle actual messages, but it is simpler to handle
|
|
||||||
websocket communications with an http actor.
|
|
||||||
|
|
||||||
The following is an example of a simple websocket echo server:
|
The following is an example of a simple websocket echo server:
|
||||||
|
|
||||||
@ -15,8 +12,7 @@ The following is an example of a simple websocket echo server:
|
|||||||
|
|
||||||
> A simple websocket echo server example is available in the [examples directory][examples].
|
> A simple websocket echo server example is available in the [examples directory][examples].
|
||||||
|
|
||||||
> An example chat server with the ability to chat over a websocket or TCP connection
|
> An example chat server with the ability to chat over a websocket or TCP connection is available in [websocket-chat directory][chat]
|
||||||
> is available in [websocket-chat directory][chat]
|
|
||||||
|
|
||||||
[message]: https://docs.rs/actix-web-actors/2/actix_web_actors/ws/enum.Message.html
|
[message]: https://docs.rs/actix-web-actors/2/actix_web_actors/ws/enum.Message.html
|
||||||
[payload]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html
|
[payload]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html
|
||||||
|
@ -6,28 +6,16 @@ weight: 100
|
|||||||
|
|
||||||
# Actix is an Ecosystem of Crates
|
# Actix is an Ecosystem of Crates
|
||||||
|
|
||||||
Long ago, `actix-web` was built on top of `actix`, a powerful and fast actor system.
|
Long ago, `actix-web` was built on top of `actix`, a powerful and fast actor system. Now, `actix-web` is largely unrelated to the actor framework and is built using a different system. Though `actix` is still maintained, its usefulness as a general tool is diminishing as the futures and async/await ecosystem matures. At this time, the use of `actix` is only required for WebSocket endpoints.
|
||||||
Now, `actix-web` is largely unrelated to the actor framework and is built using a different system.
|
|
||||||
Though `actix` is still maintained, its usefulness as a general tool is diminishing as the
|
|
||||||
futures and async/await ecosystem matures. At this time, the use of `actix` is only required for
|
|
||||||
WebSocket endpoints.
|
|
||||||
|
|
||||||
We call `actix-web` a powerful and pragmatic framework. For all intents and purposes it's a
|
We call `actix-web` a powerful and pragmatic framework. For all intents and purposes it's a micro-framework with a few twists. If you are already a Rust programmer you will probably find yourself at home quickly, but even if you are coming from another programming language you should find `actix-web` easy to pick up.
|
||||||
micro-framework with a few twists. If you are already a Rust programmer you will probably find
|
|
||||||
yourself at home quickly, but even if you are coming from another programming language you should
|
|
||||||
find `actix-web` easy to pick up.
|
|
||||||
|
|
||||||
<!-- TODO -->
|
<!-- TODO -->
|
||||||
<!-- actix-extras -->
|
<!-- actix-extras -->
|
||||||
|
|
||||||
An application developed with `actix-web` will expose an HTTP server contained within a native
|
An application developed with `actix-web` will expose an HTTP server contained within a native executable. You can either put this behind another HTTP server like nginx or serve it up as-is. Even in the complete absence of another HTTP server `actix-web` is powerful enough to provide HTTP/1 and HTTP/2 support as well as TLS (HTTPS). This makes it useful for building small services ready for production.
|
||||||
executable. You can either put this behind another HTTP server like nginx or serve it up as-is. Even
|
|
||||||
in the complete absence of another HTTP server `actix-web` is powerful enough to provide HTTP/1 and
|
|
||||||
HTTP/2 support as well as TLS (HTTPS). This makes it useful for building small services ready for
|
|
||||||
production.
|
|
||||||
|
|
||||||
Most importantly: `actix-web` runs on Rust {{< rust-version "actix-web" >}} or later and it works
|
Most importantly: `actix-web` runs on Rust {{< rust-version "actix-web" >}} or later and it works with stable releases.
|
||||||
with stable releases.
|
|
||||||
|
|
||||||
<!-- TODO -->
|
<!-- TODO -->
|
||||||
<!-- which is built upon the fantastic [Tokio][tokio] asynchronous I/O system -->
|
<!-- which is built upon the fantastic [Tokio][tokio] asynchronous I/O system -->
|
||||||
|
Loading…
Reference in New Issue
Block a user