mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 09:42:40 +01:00
Merge pull request #160 from memoryruins/guide
Guide: edits to first half
This commit is contained in:
commit
12586db15c
@ -1,11 +1,8 @@
|
|||||||
# Quick start
|
# Quick start
|
||||||
|
|
||||||
Before you can start writing a actix web applications, you’ll need a version of Rust installed.
|
|
||||||
We recommend you use rustup to install or configure such a version.
|
|
||||||
|
|
||||||
## Install Rust
|
## Install Rust
|
||||||
|
|
||||||
Before we begin, we need to install Rust using the [rustup](https://www.rustup.rs/) installer:
|
Before we begin, we need to install Rust using the [rustup](https://www.rustup.rs/):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl https://sh.rustup.rs -sSf | sh
|
curl https://sh.rustup.rs -sSf | sh
|
||||||
@ -21,9 +18,10 @@ Actix web framework requires rust version 1.21 and up.
|
|||||||
|
|
||||||
## Running Examples
|
## Running Examples
|
||||||
|
|
||||||
The fastest way to start experimenting with actix web is to clone the actix web repository
|
The fastest way to start experimenting with actix web is to clone the
|
||||||
and run the included examples in the examples/ directory. The following set of
|
[repository](https://github.com/actix/actix-web) and run the included examples.
|
||||||
commands runs the `basics` example:
|
|
||||||
|
The following set of commands runs the `basics` example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/actix/actix-web
|
git clone https://github.com/actix/actix-web
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
# Getting Started
|
# Getting Started
|
||||||
|
|
||||||
Let’s create and run our first actix web application. We’ll create a new Cargo project
|
Let’s write our first actix web application!
|
||||||
that depends on actix web and then run the application.
|
|
||||||
|
|
||||||
In the previous section we already installed the required rust version. Now let's create new cargo projects.
|
|
||||||
|
|
||||||
## Hello, world!
|
## Hello, world!
|
||||||
|
|
||||||
Let’s write our first actix web application! Start by creating a new binary-based
|
Start by creating a new binary-based Cargo project and changing into the new directory:
|
||||||
Cargo project and changing into the new directory:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo new hello-world --bin
|
cargo new hello-world --bin
|
||||||
@ -24,11 +20,12 @@ actix = "0.5"
|
|||||||
actix-web = "0.4"
|
actix-web = "0.4"
|
||||||
```
|
```
|
||||||
|
|
||||||
In order to implement a web server, first we need to create a request handler.
|
In order to implement a web server, we first need to create a request handler.
|
||||||
|
|
||||||
A request handler is a function that accepts an `HttpRequest` instance as its only parameter
|
A request handler is a function that accepts an `HttpRequest` instance as its only parameter
|
||||||
and returns a type that can be converted into `HttpResponse`:
|
and returns a type that can be converted into `HttpResponse`:
|
||||||
|
|
||||||
|
Filename: src/main.rs
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
# use actix_web::*;
|
# use actix_web::*;
|
||||||
@ -64,10 +61,10 @@ connections. The server accepts a function that should return an `HttpHandler` i
|
|||||||
.run();
|
.run();
|
||||||
```
|
```
|
||||||
|
|
||||||
That's it. Now, compile and run the program with `cargo run`.
|
That's it! Now, compile and run the program with `cargo run`.
|
||||||
Head over to ``http://localhost:8088/`` to see the results.
|
Head over to ``http://localhost:8088/`` to see the results.
|
||||||
|
|
||||||
Here is full source of main.rs file:
|
The full source of src/main.rs is listed below:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# use std::thread;
|
# use std::thread;
|
||||||
@ -80,7 +77,7 @@ fn index(req: HttpRequest) -> &'static str {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
# // In the doctest suite we can't run blocking code - deliberately leak a thread
|
# // In the doctest suite we can't run blocking code - deliberately leak a thread
|
||||||
# // If copying this example in show-all mode make sure you skip the thread spawn
|
# // If copying this example in show-all mode, make sure you skip the thread spawn
|
||||||
# // call.
|
# // call.
|
||||||
# thread::spawn(|| {
|
# thread::spawn(|| {
|
||||||
HttpServer::new(
|
HttpServer::new(
|
||||||
@ -92,7 +89,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Note on the `actix` crate. Actix web framework is built on top of actix actor library.
|
> **Note**: actix web is built upon [actix](https://github.com/actix/actix),
|
||||||
|
> an [actor model](https://en.wikipedia.org/wiki/Actor_model) framework in Rust.
|
||||||
|
|
||||||
`actix::System` initializes actor system, `HttpServer` is an actor and must run within a
|
`actix::System` initializes actor system, `HttpServer` is an actor and must run within a
|
||||||
properly configured actix system. For more information please check
|
properly configured actix system.
|
||||||
[actix documentation](https://actix.github.io/actix/actix/)
|
|
||||||
|
> For more information, check out the [actix documentation](https://actix.github.io/actix/actix/)
|
||||||
|
> and [actix guide](https://actix.github.io/actix/guide/).
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
# Application
|
# Application
|
||||||
|
|
||||||
Actix web provides some primitives to build web servers and applications with Rust.
|
Actix web provides various primitives to build web servers and applications with Rust.
|
||||||
It provides routing, middlewares, pre-processing of requests, and post-processing of responses,
|
It provides routing, middlewares, pre-processing of requests, post-processing of responses,
|
||||||
websocket protocol handling, multipart streams, etc.
|
websocket protocol handling, multipart streams, etc.
|
||||||
|
|
||||||
All actix web servers are built around the `App` instance.
|
All actix web servers are built around the `App` instance.
|
||||||
It is used for registering routes for resources, and middlewares.
|
It is used for registering routes for resources and middlewares.
|
||||||
It also stores application specific state that is shared across all handlers
|
It also stores application state shared across all handlers within same application.
|
||||||
within same application.
|
|
||||||
|
|
||||||
Application acts as a namespace for all routes, i.e all routes for a specific application
|
Applications act as a namespace for all routes, i.e all routes for a specific application
|
||||||
have the same url path prefix. The application prefix always contains a leading "/" slash.
|
have the same url path prefix. The application prefix always contains a leading "/" slash.
|
||||||
If supplied prefix does not contain leading slash, it gets inserted.
|
If a supplied prefix does not contain leading slash, it is automatically inserted.
|
||||||
The prefix should consist of value path segments. i.e for an application with prefix `/app`
|
The prefix should consist of value path segments.
|
||||||
any request with the paths `/app`, `/app/` or `/app/test` would match,
|
|
||||||
but path `/application` would not match.
|
> For an application with prefix `/app`,
|
||||||
|
> any request with the paths `/app`, `/app/`, or `/app/test` would match;
|
||||||
|
> however, the path `/application` would not match.
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -31,10 +32,11 @@ but path `/application` would not match.
|
|||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example application with `/app` prefix and `index.html` resource
|
In this example, an application with the `/app` prefix and a `index.html` resource
|
||||||
gets created. This resource is available as on `/app/index.html` url.
|
are created. This resource is available through the `/app/index.html` url.
|
||||||
For more information check
|
|
||||||
[*URL Matching*](./qs_5.html#using-a-application-prefix-to-compose-applications) section.
|
> For more information, check the
|
||||||
|
> [URL Dispatch](./qs_5.html#using-a-application-prefix-to-compose-applications) section.
|
||||||
|
|
||||||
Multiple applications can be served with one server:
|
Multiple applications can be served with one server:
|
||||||
|
|
||||||
@ -59,18 +61,17 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
All `/app1` requests route to the first application, `/app2` to the second and then all other to the third.
|
All `/app1` requests route to the first application, `/app2` to the second, and all other to the third.
|
||||||
Applications get matched based on registration order, if an application with more general
|
**Applications get matched based on registration order**. If an application with a more generic
|
||||||
prefix is registered before a less generic one, that would effectively block the less generic
|
prefix is registered before a less generic one, it would effectively block the less generic
|
||||||
application from getting matched. For example, if *application* with prefix "/" gets registered
|
application matching. For example, if an `App` with the prefix `"/"` was registered
|
||||||
as first application, it would match all incoming requests.
|
as the first application, it would match all incoming requests.
|
||||||
|
|
||||||
## State
|
## State
|
||||||
|
|
||||||
Application state is shared with all routes and resources within the same application.
|
Application state is shared with all routes and resources within the same application.
|
||||||
State can be accessed with the `HttpRequest::state()` method as a read-only,
|
When using an http actor,state can be accessed with the `HttpRequest::state()` as read-only,
|
||||||
but an interior mutability pattern with `RefCell` can be used to achieve state mutability.
|
but interior mutability with `RefCell` can be used to achieve state mutability.
|
||||||
State can be accessed with `HttpContext::state()` when using an http actor.
|
|
||||||
State is also available for route matching predicates and middlewares.
|
State is also available for route matching predicates and middlewares.
|
||||||
|
|
||||||
Let's write a simple application that uses shared state. We are going to store request count
|
Let's write a simple application that uses shared state. We are going to store request count
|
||||||
@ -102,8 +103,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Note on application state, http server accepts an application factory rather than an application
|
> **Note**: http server accepts an application factory rather than an application
|
||||||
instance. Http server constructs an application instance for each thread, so application state
|
> instance. Http server constructs an application instance for each thread, thus application state
|
||||||
must be constructed multiple times. If you want to share state between different threads, a
|
> must be constructed multiple times. If you want to share state between different threads, a
|
||||||
shared object should be used, like `Arc`. Application state does not need to be `Send` and `Sync`
|
> shared object should be used, e.g. `Arc`. Application state does not need to be `Send` and `Sync`,
|
||||||
but the application factory must be `Send` + `Sync`.
|
> but the application factory must be `Send` + `Sync`.
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
# Server
|
# Server
|
||||||
|
|
||||||
The [*HttpServer*](../actix_web/struct.HttpServer.html) type is responsible for
|
The [**HttpServer**](../actix_web/struct.HttpServer.html) type is responsible for
|
||||||
serving http requests. *HttpServer* accepts application factory as a parameter,
|
serving http requests.
|
||||||
Application factory must have `Send` + `Sync` boundaries. More about that in the
|
|
||||||
*multi-threading* section. To bind to a specific socket address, `bind()` must be used.
|
`HttpServer` accepts an application factory as a parameter, and the
|
||||||
This method can be called multiple times. To start the http server, one of the *start*
|
application factory must have `Send` + `Sync` boundaries. More about that in the
|
||||||
methods can be used. `start()` method starts a simple server, `start_tls()` or `start_ssl()`
|
*multi-threading* section.
|
||||||
starts ssl server. *HttpServer* is an actix actor, it has to be initialized
|
|
||||||
within a properly configured actix system:
|
To bind to a specific socket address, `bind()` must be used, and it may be called multiple times.
|
||||||
|
To start the http server, one of the start methods.
|
||||||
|
|
||||||
|
- use `start()` for a simple server
|
||||||
|
- use `start_tls()` or `start_ssl()` for a ssl server
|
||||||
|
|
||||||
|
`HttpServer` is an actix actor. It must be initialized within a properly configured actix system:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix;
|
# extern crate actix;
|
||||||
@ -29,17 +35,17 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
It is possible to start a server in a separate thread with the *spawn()* method. In that
|
> It is possible to start a server in a separate thread with the `spawn()` method. In that
|
||||||
case the server spawns a new thread and creates a new actix system in it. To stop
|
> case the server spawns a new thread and creates a new actix system in it. To stop
|
||||||
this server, send a `StopServer` message.
|
> this server, send a `StopServer` message.
|
||||||
|
|
||||||
Http server is implemented as an actix actor. It is possible to communicate with the server
|
`HttpServer` is implemented as an actix actor. It is possible to communicate with the server
|
||||||
via a messaging system. All start methods like `start()`, `start_ssl()`, etc. return the
|
via a messaging system. All start methods, e.g. `start()` and `start_ssl()`, return the
|
||||||
address of the started http server. Actix http server accepts several messages:
|
address of the started http server. It accepts several messages:
|
||||||
|
|
||||||
* `PauseServer` - Pause accepting incoming connections
|
- `PauseServer` - Pause accepting incoming connections
|
||||||
* `ResumeServer` - Resume accepting incoming connections
|
- `ResumeServer` - Resume accepting incoming connections
|
||||||
* `StopServer` - Stop incoming connection processing, stop all workers and exit
|
- `StopServer` - Stop incoming connection processing, stop all workers and exit
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate futures;
|
# extern crate futures;
|
||||||
@ -74,7 +80,7 @@ fn main() {
|
|||||||
|
|
||||||
## Multi-threading
|
## Multi-threading
|
||||||
|
|
||||||
Http server automatically starts an number of http workers, by default
|
`HttpServer` automatically starts an number of http workers, by default
|
||||||
this number is equal to number of logical CPUs in the system. This number
|
this number is equal to number of logical CPUs in the system. This number
|
||||||
can be overridden with the `HttpServer::threads()` method.
|
can be overridden with the `HttpServer::threads()` method.
|
||||||
|
|
||||||
@ -92,8 +98,10 @@ fn main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
The server creates a separate application instance for each created worker. Application state
|
The server creates a separate application instance for each created worker. Application state
|
||||||
is not shared between threads, to share state `Arc` could be used. Application state
|
is not shared between threads. To share state, `Arc` could be used.
|
||||||
does not need to be `Send` and `Sync` but application factory must be `Send` + `Sync`.
|
|
||||||
|
> Application state does not need to be `Send` and `Sync`,
|
||||||
|
> but factories must be `Send` + `Sync`.
|
||||||
|
|
||||||
## SSL
|
## SSL
|
||||||
|
|
||||||
@ -123,22 +131,21 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Note on *HTTP/2.0* protocol over tls without prior knowledge, it requires
|
> **Note**: the *HTTP/2.0* protocol requires
|
||||||
[tls alpn](https://tools.ietf.org/html/rfc7301). At the moment only
|
> [tls alpn](https://tools.ietf.org/html/rfc7301).
|
||||||
`openssl` has `alpn ` support.
|
> At the moment, only `openssl` has `alpn` support.
|
||||||
|
> For a full example, check out
|
||||||
Please check [example](https://github.com/actix/actix-web/tree/master/examples/tls)
|
> [examples/tls](https://github.com/actix/actix-web/tree/master/examples/tls).
|
||||||
for a full example.
|
|
||||||
|
|
||||||
## Keep-Alive
|
## Keep-Alive
|
||||||
|
|
||||||
Actix can wait for requests on a keep-alive connection. *Keep alive*
|
Actix can wait for requests on a keep-alive connection.
|
||||||
connection behavior is defined by server settings.
|
|
||||||
|
|
||||||
* `75` or `Some(75)` or `KeepAlive::Timeout(75)` - enable 75 sec *keep alive* timer according
|
> *keep alive* connection behavior is defined by server settings.
|
||||||
request and response settings.
|
|
||||||
* `None` or `KeepAlive::Disabled` - disable *keep alive*.
|
- `75`, `Some(75)`, `KeepAlive::Timeout(75)` - enable 75 second *keep alive* timer.
|
||||||
* `KeepAlive::Tcp(75)` - Use `SO_KEEPALIVE` socket option.
|
- `None` or `KeepAlive::Disabled` - disable *keep alive*.
|
||||||
|
- `KeepAlive::Tcp(75)` - use `SO_KEEPALIVE` socket option.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -163,11 +170,12 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If first option is selected then *keep alive* state is
|
If the first option is selected, then *keep alive* state is
|
||||||
calculated based on the response's *connection-type*. By default
|
calculated based on the response's *connection-type*. By default
|
||||||
`HttpResponse::connection_type` is not defined in that case *keep alive*
|
`HttpResponse::connection_type` is not defined. In that case *keep alive* is
|
||||||
defined by request's http version. Keep alive is off for *HTTP/1.0*
|
defined by the request's http version.
|
||||||
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 change with `HttpResponseBuilder::connection_type()` method.
|
*Connection type* can be change with `HttpResponseBuilder::connection_type()` method.
|
||||||
|
|
||||||
@ -186,19 +194,19 @@ fn index(req: HttpRequest) -> HttpResponse {
|
|||||||
|
|
||||||
## Graceful shutdown
|
## Graceful shutdown
|
||||||
|
|
||||||
Actix http server 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. Workers still alive after the
|
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.
|
timeout are force-dropped. By default the shutdown timeout is set to 30 seconds.
|
||||||
You can change this parameter with the `HttpServer::shutdown_timeout()` method.
|
You can change this parameter with the `HttpServer::shutdown_timeout()` method.
|
||||||
|
|
||||||
You can send a stop message to the server with the server address and specify if you want
|
You can send a stop message to the server with the server address and specify if you want
|
||||||
graceful shutdown or not. The `start()` methods return address of the server.
|
graceful shutdown or not. The `start()` methods returns address of the server.
|
||||||
|
|
||||||
Http server handles several OS signals. *CTRL-C* is available on all OSs,
|
`HttpServer` handles several OS signals. *CTRL-C* is available on all OSs,
|
||||||
other signals are available on unix systems.
|
other signals 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 `HttpServer::disable_signals()` method.
|
> It is possible to disable signal handling with `HttpServer::disable_signals()` method.
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
# Handler
|
# Handler
|
||||||
|
|
||||||
A request handler can be any object that implements
|
A request handler can be any object that implements
|
||||||
[*Handler trait*](../actix_web/dev/trait.Handler.html).
|
[`Handler` trait](../actix_web/dev/trait.Handler.html).
|
||||||
Request handling happens in two stages. First the handler object is called.
|
|
||||||
Handler can return any object that implements
|
Request handling happens in two stages. First the handler object is called,
|
||||||
[*Responder trait*](../actix_web/trait.Responder.html#foreign-impls).
|
returning any object that implements the
|
||||||
Then `respond_to()` is called on the returned object. And finally
|
[`Responder` trait](../actix_web/trait.Responder.html#foreign-impls).
|
||||||
result of the `respond_to()` call is converted to a `Reply` object.
|
Then, `respond_to()` is called on the returned object, converting itself to a `Reply` or `Error`.
|
||||||
|
|
||||||
By default actix provides `Responder` implementations for some standard types,
|
By default actix provides `Responder` implementations for some standard types,
|
||||||
like `&'static str`, `String`, etc.
|
such as `&'static str`, `String`, etc.
|
||||||
For a complete list of implementations, check
|
|
||||||
[*Responder documentation*](../actix_web/trait.Responder.html#foreign-impls).
|
> For a complete list of implementations, check
|
||||||
|
> [*Responder documentation*](../actix_web/trait.Responder.html#foreign-impls).
|
||||||
|
|
||||||
Examples of valid handlers:
|
Examples of valid handlers:
|
||||||
|
|
||||||
@ -39,15 +40,16 @@ fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Some notes on shared application state and handler state. If you noticed
|
*Handler* trait is generic over *S*, which defines the application state's type.
|
||||||
*Handler* trait is generic over *S*, which defines application state type. So
|
Application state is accessible from the handler with the `HttpRequest::state()` method;
|
||||||
application state is accessible from handler with the `HttpRequest::state()` method.
|
however, state is accessible as a read-only reference. If you need mutable access to state,
|
||||||
But state is accessible as a read-only reference - if you need mutable access to state
|
it must be implemented.
|
||||||
you have to implement it yourself. On other hand, handler can mutably access its own state
|
|
||||||
as the `handle` method takes a mutable reference to *self*. Beware, actix creates multiple copies
|
> **Note**: Alternatively, the handler can mutably access its own state because the `handle` method takes
|
||||||
of application state and handlers, unique for each thread, so if you run your
|
> mutable reference to *self*. **Beware**, actix creates multiple copies
|
||||||
application in several threads, actix will create the same amount as number of threads
|
> of the application state and the handlers, unique for each thread. If you run your
|
||||||
of application state objects and handler objects.
|
> application in several threads, actix will create the same amount as number of threads
|
||||||
|
> of application state objects and handler objects.
|
||||||
|
|
||||||
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:
|
||||||
|
|
||||||
@ -69,8 +71,8 @@ impl<S> Handler<S> for MyHandler {
|
|||||||
# fn main() {}
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
This handler will work, but `self.0` will be different depending on the number of threads and
|
Although this handler will work, `self.0` will be different depending on the number of threads and
|
||||||
number of requests processed per thread. A proper implementation would use `Arc` and `AtomicUsize`
|
number of requests processed per thread. A proper implementation would use `Arc` and `AtomicUsize`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix;
|
# extern crate actix;
|
||||||
@ -111,14 +113,15 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Be careful with synchronization primitives like *Mutex* or *RwLock*. Actix web framework
|
> Be careful with synchronization primitives like `Mutex` or `RwLock`. Actix web framework
|
||||||
handles requests asynchronously; by blocking thread execution all concurrent
|
> handles requests asynchronously. By blocking thread execution, all concurrent
|
||||||
request handling processes would block. If you need to share or update some state
|
> request handling processes would block. If you need to share or update some state
|
||||||
from multiple threads consider using the [actix](https://actix.github.io/actix/actix/) actor system.
|
> from multiple threads, consider using the [actix](https://actix.github.io/actix/actix/) actor system.
|
||||||
|
|
||||||
## Response with custom type
|
## Response with custom type
|
||||||
|
|
||||||
To return a custom type directly from a handler function, the type needs to implement the `Responder` trait.
|
To return a custom type directly from a handler function, the type needs to implement the `Responder` trait.
|
||||||
|
|
||||||
Let's create a response for a custom type that serializes to an `application/json` response:
|
Let's create a response for a custom type that serializes to an `application/json` response:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -171,10 +174,10 @@ fn main() {
|
|||||||
|
|
||||||
## Async handlers
|
## Async handlers
|
||||||
|
|
||||||
There are two different types of async handlers.
|
There are two different types of async handlers. Response objects can be generated asynchronously
|
||||||
|
or more precisely, any type that implements the [*Responder*](../actix_web/trait.Responder.html) trait.
|
||||||
|
|
||||||
Response objects can be generated asynchronously or more precisely, any type
|
In this case, the handler must return a `Future` object that resolves to the *Responder* type, i.e:
|
||||||
that implements the [*Responder*](../actix_web/trait.Responder.html) trait. In this case the handler must return a `Future` object that resolves to the *Responder* type, i.e:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -205,8 +208,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Or the response body can be generated asynchronously. In this case body
|
Or the response body can be generated asynchronously. In this case, body
|
||||||
must implement stream trait `Stream<Item=Bytes, Error=Error>`, i.e:
|
must implement the stream trait `Stream<Item=Bytes, Error=Error>`, i.e:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -233,7 +236,7 @@ fn main() {
|
|||||||
Both methods can be combined. (i.e Async response with streaming body)
|
Both methods can be combined. (i.e Async response with streaming body)
|
||||||
|
|
||||||
It is possible to return a `Result` where the `Result::Item` type can be `Future`.
|
It is possible to return a `Result` where the `Result::Item` type can be `Future`.
|
||||||
In this example the `index` handler can return an error immediately or return a
|
In this example, the `index` handler can return an error immediately or return a
|
||||||
future that resolves to a `HttpResponse`.
|
future that resolves to a `HttpResponse`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -265,11 +268,11 @@ fn index(req: HttpRequest) -> Result<Box<Future<Item=HttpResponse, Error=Error>>
|
|||||||
|
|
||||||
## Different return types (Either)
|
## Different return types (Either)
|
||||||
|
|
||||||
Sometimes you need to return different types of responses. For example
|
Sometimes, you need to return different types of responses. For example,
|
||||||
you can do error check and return error and return async response otherwise.
|
you can error check and return errors, return async responses, or any result that requires two different types.
|
||||||
Or any result that requires two different types.
|
|
||||||
For this case the [*Either*](../actix_web/enum.Either.html) type can be used.
|
For this case, the [`Either`](../actix_web/enum.Either.html) type can be used.
|
||||||
*Either* allows combining two different responder types into a single type.
|
`Either` allows combining two different responder types into a single type.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
# Errors
|
# Errors
|
||||||
|
|
||||||
Actix uses [`Error` type](../actix_web/error/struct.Error.html)
|
Actix uses the [`Error` type](../actix_web/error/struct.Error.html)
|
||||||
and [`ResponseError` trait](../actix_web/error/trait.ResponseError.html)
|
and [`ResponseError` trait](../actix_web/error/trait.ResponseError.html)
|
||||||
for handling handler's errors.
|
for handling handler's errors.
|
||||||
|
|
||||||
Any error that implements the `ResponseError` trait can be returned as an error value.
|
Any error that implements the `ResponseError` trait can be returned as an error value.
|
||||||
*Handler* can return an *Result* object; actix by default provides
|
`Handler` can return an `Result` object. By default, actix provides a
|
||||||
`Responder` implementation for compatible result types. Here is the implementation
|
`Responder` implementation for compatible result types. Here is the implementation
|
||||||
definition:
|
definition:
|
||||||
|
|
||||||
@ -12,7 +13,8 @@ definition:
|
|||||||
impl<T: Responder, E: Into<Error>> Responder for Result<T, E>
|
impl<T: Responder, E: Into<Error>> Responder for Result<T, E>
|
||||||
```
|
```
|
||||||
|
|
||||||
And any error that implements `ResponseError` can be converted into an `Error` object.
|
Any error that implements `ResponseError` can be converted into an `Error` object.
|
||||||
|
|
||||||
For example, if the *handler* function returns `io::Error`, it would be converted
|
For example, if the *handler* function returns `io::Error`, it would be converted
|
||||||
into an `HttpInternalServerError` response. Implementation for `io::Error` is provided
|
into an `HttpInternalServerError` response. Implementation for `io::Error` is provided
|
||||||
by default.
|
by default.
|
||||||
@ -35,7 +37,7 @@ fn index(req: HttpRequest) -> io::Result<fs::NamedFile> {
|
|||||||
|
|
||||||
## Custom error response
|
## Custom error response
|
||||||
|
|
||||||
To add support for custom errors, all we need to do is just implement the `ResponseError` trait
|
To add support for custom errors, all we need to do is implement the `ResponseError` trait
|
||||||
for the custom error type. The `ResponseError` trait has a default implementation
|
for the custom error type. The `ResponseError` trait has a default implementation
|
||||||
for the `error_response()` method: it generates a *500* response.
|
for the `error_response()` method: it generates a *500* response.
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ fn index(req: HttpRequest) -> Result<&'static str, MyError> {
|
|||||||
## Error helpers
|
## Error helpers
|
||||||
|
|
||||||
Actix provides a set of error helper types. It is possible to use them for generating
|
Actix provides a set of error helper types. It is possible to use them for generating
|
||||||
specific error responses. We can use helper types for the first example with custom error.
|
specific error responses. We can use the helper types for the first example with a custom error.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
|
@ -2,17 +2,19 @@
|
|||||||
|
|
||||||
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,
|
matching language. If one of the patterns matches the path information associated with a request,
|
||||||
a particular handler object is invoked. A handler is a specific object that implements the
|
a particular handler object is invoked.
|
||||||
`Handler` trait, defined in your application, that receives the request and returns
|
|
||||||
a response object. More information is available in the [handler section](../qs_4.html).
|
> A handler is a specific object that implements the
|
||||||
|
> `Handler` trait, defined in your application, that receives the request and returns
|
||||||
|
> a response object. More information is available in the [handler section](../qs_4.html).
|
||||||
|
|
||||||
## Resource configuration
|
## Resource configuration
|
||||||
|
|
||||||
Resource configuration is the act of adding a new resources to an application.
|
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.
|
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.
|
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*,
|
A resource also has a pattern, meant to match against the *PATH* portion of a *URL*.
|
||||||
it does not match against the *QUERY* portion (the portion following the scheme and
|
It does not match against the *QUERY* portion (the portion following the scheme and
|
||||||
port, e.g., */foo/bar* in the *URL* *http://localhost:8080/foo/bar?q=value*).
|
port, e.g., */foo/bar* in the *URL* *http://localhost:8080/foo/bar?q=value*).
|
||||||
|
|
||||||
The [App::resource](../actix_web/struct.App.html#method.resource) methods
|
The [App::resource](../actix_web/struct.App.html#method.resource) methods
|
||||||
@ -43,7 +45,7 @@ The *Configuration function* has the following type:
|
|||||||
```
|
```
|
||||||
|
|
||||||
The *Configuration function* can set a name and register specific routes.
|
The *Configuration function* can set a name and register specific routes.
|
||||||
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
|
||||||
@ -55,8 +57,9 @@ 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
|
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
|
the order the routes were registered via `Resource::route()`.
|
||||||
any number of *predicates* but only one handler.
|
|
||||||
|
> A *Route* can contain any number of *predicates* but only one handler.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -74,10 +77,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example `HttpResponse::Ok()` is returned for *GET* requests,
|
In this example, `HttpResponse::Ok()` is returned for *GET* requests.
|
||||||
if request contains `Content-Type` header and value of this header is *text/plain*
|
If a request contains `Content-Type` header, the value of this header is *text/plain*,
|
||||||
and path equals to `/path`. Resource calls handle of the first matching route.
|
and path equals to `/path`, Resource calls handle of the first matching route.
|
||||||
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.
|
||||||
|
|
||||||
[*Resource::route()*](../actix_web/struct.Resource.html#method.route) returns a
|
[*Resource::route()*](../actix_web/struct.Resource.html#method.route) returns a
|
||||||
[*Route*](../actix_web/struct.Route.html) object. Route can be configured with a
|
[*Route*](../actix_web/struct.Route.html) object. Route can be configured with a
|
||||||
@ -118,9 +122,7 @@ arguments provided to a route configuration returns `false` during a check, that
|
|||||||
skipped and route matching continues through the ordered set of routes.
|
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.
|
the route is invoked. If no route matches after all route patterns are exhausted, a *NOT FOUND* response get returned.
|
||||||
|
|
||||||
If no route matches after all route patterns are exhausted, a *NOT FOUND* response get returned.
|
|
||||||
|
|
||||||
## Resource pattern syntax
|
## Resource pattern syntax
|
||||||
|
|
||||||
@ -208,8 +210,9 @@ For example, for the URL */abc/*:
|
|||||||
* */abc/{foo}* will not match.
|
* */abc/{foo}* will not match.
|
||||||
* */{foo}/* will match.
|
* */{foo}/* will match.
|
||||||
|
|
||||||
Note that 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:
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -292,11 +295,11 @@ any) is skipped.
|
|||||||
For security purposes, if a segment meets any of the following conditions,
|
For security purposes, if a segment meets any of the following conditions,
|
||||||
an `Err` is returned indicating the condition met:
|
an `Err` is returned indicating the condition met:
|
||||||
|
|
||||||
* Decoded segment starts with any of: `.` (except `..`), `*`
|
* Decoded segment starts with any of: `.` (except `..`), `*`
|
||||||
* Decoded segment ends with any of: `:`, `>`, `<`
|
* Decoded segment ends with any of: `:`, `>`, `<`
|
||||||
* Decoded segment contains any of: `/`
|
* Decoded segment contains any of: `/`
|
||||||
* On Windows, decoded segment contains any of: '\'
|
* On Windows, decoded segment contains any of: '\'
|
||||||
* Percent-encoding results in invalid UTF8.
|
* Percent-encoding results in invalid UTF8.
|
||||||
|
|
||||||
As a result of these conditions, a `PathBuf` parsed from request path parameter is
|
As a result of these conditions, a `PathBuf` parsed from request path parameter is
|
||||||
safe to interpolate within, or use as a suffix of, a path without additional checks.
|
safe to interpolate within, or use as a suffix of, a path without additional checks.
|
||||||
@ -350,8 +353,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
It also possible to extract path information to a tuple, in this case you don't need
|
It also possible to extract path information to a tuple. In this case, you don't need
|
||||||
to define extra type, just use tuple for as a `Path` generic type.
|
to define an extra type; use a tuple as a `Path` generic type.
|
||||||
|
|
||||||
Here is previous example re-written using tuple instead of specific type.
|
Here is previous example re-written using tuple instead of specific type.
|
||||||
|
|
||||||
@ -433,21 +436,21 @@ fn main() {
|
|||||||
|
|
||||||
By normalizing it means:
|
By normalizing it means:
|
||||||
|
|
||||||
- Add a trailing slash to the path.
|
* Add a trailing slash to the path.
|
||||||
- Double slashes are replaced by one.
|
* Double slashes are replaced by one.
|
||||||
|
|
||||||
The handler returns as soon as it finds a path that resolves
|
The handler returns as soon as it finds a path that resolves
|
||||||
correctly. The order if all enable is 1) merge, 3) both merge and append
|
correctly. The order if all enable is 1) merge, 3) both merge and append
|
||||||
and 3) append. If the path resolves with
|
and 3) append. If the path resolves with
|
||||||
at least one of those conditions, it will redirect to the new path.
|
at least one of those conditions, it will redirect to the new path.
|
||||||
|
|
||||||
If *append* is *true* append slash when needed. If a resource is
|
If *append* is *true*, append slash when needed. If a resource is
|
||||||
defined with trailing slash and the request doesn't have one, it will
|
defined with trailing slash and the request doesn't have one, it will
|
||||||
be appended automatically.
|
be appended automatically.
|
||||||
|
|
||||||
If *merge* is *true*, merge multiple consecutive slashes in the path into one.
|
If *merge* is *true*, merge multiple consecutive slashes in the path into one.
|
||||||
|
|
||||||
This handler designed to be use as a handler for application's *default resource*.
|
This handler designed to be used as a handler for application's *default resource*.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -468,7 +471,7 @@ fn main() {
|
|||||||
|
|
||||||
In this example `/resource`, `//resource///` will be redirected to `/resource/`.
|
In this example `/resource`, `//resource///` will be redirected to `/resource/`.
|
||||||
|
|
||||||
In this example 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
|
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
|
slash-appending *Not Found* will turn a *POST* request into a GET, losing any
|
||||||
*POST* data in the original request.
|
*POST* data in the original request.
|
||||||
@ -493,7 +496,7 @@ fn main() {
|
|||||||
|
|
||||||
## Using an Application Prefix to Compose Applications
|
## Using an Application Prefix to Compose Applications
|
||||||
|
|
||||||
The `App::prefix()`" method allows to set a specific application prefix.
|
The `App::prefix()` method allows to set a specific application prefix.
|
||||||
This prefix represents a resource prefix that will be prepended to all resource patterns added
|
This prefix 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
|
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
|
location than the included callable's author intended while still maintaining the same
|
||||||
@ -556,7 +559,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
Predicates have access to the application's state via `HttpRequest::state()`.
|
Predicates have access to the application's state via `HttpRequest::state()`.
|
||||||
Also predicates can store extra information in
|
Also predicates can store extra information in
|
||||||
@ -565,7 +568,7 @@ Also predicates can store extra information in
|
|||||||
### Modifying predicate values
|
### Modifying predicate 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
|
For example, if you want to return "METHOD NOT ALLOWED" response for all methods
|
||||||
except "GET":
|
except "GET":
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
Loading…
Reference in New Issue
Block a user