1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-12-12 19:26:38 +00:00
actix-web/guide/src/qs_4.md

314 lines
9 KiB
Markdown
Raw Normal View History

2017-12-02 07:42:21 +00:00
# Handler
2018-03-28 20:16:01 +00:00
A request handler can be any object that implements
2018-04-06 01:30:52 +00:00
[`Handler` trait](../actix_web/dev/trait.Handler.html).
Request handling happens in two stages. First the handler object is called,
returning any object that implements the
[`Responder` trait](../actix_web/trait.Responder.html#foreign-impls).
Then, `respond_to()` is called on the returned object, converting itself to a `Reply` or `Error`.
2017-12-08 23:25:37 +00:00
2018-03-28 20:16:01 +00:00
By default actix provides `Responder` implementations for some standard types,
2018-04-06 01:30:52 +00:00
such as `&'static str`, `String`, etc.
> For a complete list of implementations, check
> [*Responder documentation*](../actix_web/trait.Responder.html#foreign-impls).
2017-12-02 07:42:21 +00:00
2017-12-08 23:25:37 +00:00
Examples of valid handlers:
2017-12-02 07:42:21 +00:00
```rust,ignore
fn index(req: HttpRequest) -> &'static str {
"Hello world!"
}
```
```rust,ignore
fn index(req: HttpRequest) -> String {
"Hello world!".to_owned()
}
```
```rust,ignore
fn index(req: HttpRequest) -> Bytes {
Bytes::from_static("Hello world!")
}
```
```rust,ignore
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
...
}
```
2018-04-06 01:30:52 +00:00
*Handler* trait is generic over *S*, which defines the application state's type.
Application state is accessible from the handler with the `HttpRequest::state()` method;
however, state is accessible as a read-only reference. If you need mutable access to state,
it must be implemented.
> **Note**: Alternatively, the handler can mutably access its own state because the `handle` method takes
> mutable reference to *self*. **Beware**, actix creates multiple copies
> of the application state and the handlers, unique for each thread. If you run your
> application in several threads, actix will create the same amount as number of threads
> of application state objects and handler objects.
2017-12-26 17:00:45 +00:00
2018-03-28 20:16:01 +00:00
Here is an example of a handler that stores the number of processed requests:
2017-12-26 17:00:45 +00:00
```rust
# extern crate actix_web;
2018-03-31 07:16:55 +00:00
use actix_web::{App, HttpRequest, HttpResponse, dev::Handler};
2017-12-26 17:00:45 +00:00
struct MyHandler(usize);
impl<S> Handler<S> for MyHandler {
type Result = HttpResponse;
/// Handle request
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
self.0 += 1;
HttpResponse::Ok().into()
2017-12-26 17:00:45 +00:00
}
}
# fn main() {}
```
2018-04-06 01:30:52 +00:00
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`.
2017-12-26 17:00:45 +00:00
```rust
# extern crate actix;
# extern crate actix_web;
2018-03-31 07:16:55 +00:00
use actix_web::{server, App, HttpRequest, HttpResponse, dev::Handler};
2017-12-26 17:00:45 +00:00
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
struct MyHandler(Arc<AtomicUsize>);
impl<S> Handler<S> for MyHandler {
type Result = HttpResponse;
/// Handle request
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
self.0.fetch_add(1, Ordering::Relaxed);
HttpResponse::Ok().into()
2017-12-26 17:00:45 +00:00
}
}
fn main() {
let sys = actix::System::new("example");
let inc = Arc::new(AtomicUsize::new(0));
server::new(
2018-03-28 20:16:01 +00:00
move || {
2017-12-26 17:00:45 +00:00
let cloned = inc.clone();
2018-03-31 07:16:55 +00:00
App::new()
2018-01-01 01:26:32 +00:00
.resource("/", move |r| r.h(MyHandler(cloned)))
2017-12-26 17:00:45 +00:00
})
.bind("127.0.0.1:8088").unwrap()
.start();
println!("Started http server: 127.0.0.1:8088");
2018-02-13 06:56:47 +00:00
# actix::Arbiter::system().do_send(actix::msgs::SystemExit(0));
2017-12-26 17:00:45 +00:00
let _ = sys.run();
}
```
2018-04-06 01:30:52 +00:00
> Be careful with synchronization primitives like `Mutex` or `RwLock`. 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 [actix](https://actix.github.io/actix/actix/) actor system.
2017-12-26 19:19:08 +00:00
2017-12-08 23:25:37 +00:00
## Response with custom type
2017-12-02 07:42:21 +00:00
2018-04-06 01:30:52 +00:00
To return a custom type directly from a handler function, the type needs to implement the `Responder` trait.
2018-03-28 20:16:01 +00:00
Let's create a response for a custom type that serializes to an `application/json` response:
2017-12-02 07:42:21 +00:00
```rust
2017-12-06 19:00:39 +00:00
# extern crate actix;
# extern crate actix_web;
2017-12-02 07:42:21 +00:00
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
use actix_web::{server, App, HttpRequest, HttpResponse, Error, Responder, http};
2017-12-02 07:42:21 +00:00
#[derive(Serialize)]
struct MyObj {
2017-12-08 23:25:37 +00:00
name: &'static str,
2017-12-02 07:42:21 +00:00
}
2017-12-21 07:27:30 +00:00
/// Responder
2017-12-14 17:43:42 +00:00
impl Responder for MyObj {
type Item = HttpResponse;
type Error = Error;
2018-03-31 00:31:18 +00:00
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, Error> {
let body = serde_json::to_string(&self)?;
2017-12-02 07:42:21 +00:00
// Create response and set content type
Ok(HttpResponse::Ok()
2017-12-02 07:42:21 +00:00
.content_type("application/json")
.body(body))
2017-12-02 07:42:21 +00:00
}
}
2017-12-21 07:27:30 +00:00
/// Because `MyObj` implements `Responder`, it is possible to return it directly
2017-12-08 23:25:37 +00:00
fn index(req: HttpRequest) -> MyObj {
MyObj{name: "user"}
}
2017-12-02 07:42:21 +00:00
fn main() {
let sys = actix::System::new("example");
server::new(
2018-03-31 07:16:55 +00:00
|| App::new()
2018-03-31 00:31:18 +00:00
.resource("/", |r| r.method(http::Method::GET).f(index)))
2017-12-17 20:35:04 +00:00
.bind("127.0.0.1:8088").unwrap()
.start();
2017-12-02 07:42:21 +00:00
println!("Started http server: 127.0.0.1:8088");
2018-02-13 06:56:47 +00:00
# actix::Arbiter::system().do_send(actix::msgs::SystemExit(0));
2017-12-02 07:42:21 +00:00
let _ = sys.run();
}
```
## Async handlers
2018-04-06 01:30:52 +00:00
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.
2017-12-02 07:42:21 +00:00
2018-04-06 01:30:52 +00:00
In this case, the handler must return a `Future` object that resolves to the *Responder* type, i.e:
2017-12-02 07:42:21 +00:00
2017-12-05 00:09:22 +00:00
```rust
# extern crate actix_web;
# extern crate futures;
# extern crate bytes;
# use actix_web::*;
# use bytes::Bytes;
# use futures::stream::once;
2018-03-22 04:02:04 +00:00
# use futures::future::{Future, result};
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
2017-12-05 00:09:22 +00:00
result(Ok(HttpResponse::Ok()
.content_type("text/html")
.body(format!("Hello!"))))
2018-03-22 04:02:04 +00:00
.responder()
2017-12-02 07:42:21 +00:00
}
2018-03-22 04:02:04 +00:00
fn index2(req: HttpRequest) -> Box<Future<Item=&'static str, Error=Error>> {
2017-12-20 20:51:39 +00:00
result(Ok("Welcome!"))
2018-03-22 04:02:04 +00:00
.responder()
2017-12-20 20:51:39 +00:00
}
2017-12-05 00:09:22 +00:00
fn main() {
2018-03-31 07:16:55 +00:00
App::new()
.resource("/async", |r| r.route().a(index))
2017-12-20 20:51:39 +00:00
.resource("/", |r| r.route().a(index2))
2017-12-05 00:09:22 +00:00
.finish();
}
```
2017-12-02 07:42:21 +00:00
2018-04-06 01:30:52 +00:00
Or the response body can be generated asynchronously. In this case, body
must implement the stream trait `Stream<Item=Bytes, Error=Error>`, i.e:
2017-12-02 07:42:21 +00:00
2017-12-05 00:09:22 +00:00
```rust
# extern crate actix_web;
# extern crate futures;
# extern crate bytes;
# use actix_web::*;
# use bytes::Bytes;
# use futures::stream::once;
2017-12-02 07:42:21 +00:00
fn index(req: HttpRequest) -> HttpResponse {
2017-12-05 00:09:22 +00:00
let body = once(Ok(Bytes::from_static(b"test")));
2017-12-02 07:42:21 +00:00
2017-12-05 00:09:22 +00:00
HttpResponse::Ok()
2017-12-02 07:42:21 +00:00
.content_type("application/json")
.body(Body::Streaming(Box::new(body)))
2017-12-02 07:42:21 +00:00
}
fn main() {
2018-03-31 07:16:55 +00:00
App::new()
.resource("/async", |r| r.f(index))
2017-12-02 07:42:21 +00:00
.finish();
}
```
2018-03-28 20:16:01 +00:00
Both methods can be combined. (i.e Async response with streaming body)
2018-01-23 04:10:05 +00:00
2018-03-28 20:16:01 +00:00
It is possible to return a `Result` where the `Result::Item` type can be `Future`.
2018-04-06 01:30:52 +00:00
In this example, the `index` handler can return an error immediately or return a
2018-03-22 04:02:04 +00:00
future that resolves to a `HttpResponse`.
```rust
# extern crate actix_web;
# extern crate futures;
# extern crate bytes;
# use actix_web::*;
# use bytes::Bytes;
# use futures::stream::once;
# use futures::future::{Future, result};
fn index(req: HttpRequest) -> Result<Box<Future<Item=HttpResponse, Error=Error>>, Error> {
if is_error() {
Err(error::ErrorBadRequest("bad request"))
} else {
Ok(Box::new(
result(Ok(HttpResponse::Ok()
2018-03-22 04:02:04 +00:00
.content_type("text/html")
.body(format!("Hello!"))))))
2018-03-22 04:02:04 +00:00
}
}
#
# fn is_error() -> bool { true }
# fn main() {
2018-03-31 07:16:55 +00:00
# App::new()
2018-03-22 04:02:04 +00:00
# .resource("/async", |r| r.route().f(index))
# .finish();
# }
```
2018-03-10 18:12:44 +00:00
## Different return types (Either)
2018-04-06 01:30:52 +00:00
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.
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.
2018-03-10 18:12:44 +00:00
```rust
# extern crate actix_web;
# extern crate futures;
# use actix_web::*;
# use futures::future::Future;
use futures::future::result;
use actix_web::{Either, Error, HttpResponse};
2018-03-10 18:12:44 +00:00
type RegisterResult = Either<HttpResponse, Box<Future<Item=HttpResponse, Error=Error>>>;
fn index(req: HttpRequest) -> RegisterResult {
2018-03-11 16:28:22 +00:00
if is_a_variant() { // <- choose variant A
2018-03-10 18:12:44 +00:00
Either::A(
HttpResponse::BadRequest().body("Bad data"))
2018-03-10 18:12:44 +00:00
} else {
2018-03-11 16:28:22 +00:00
Either::B( // <- variant B
result(Ok(HttpResponse::Ok()
2018-03-10 18:12:44 +00:00
.content_type("text/html")
.body(format!("Hello!")))).responder())
2018-03-10 18:12:44 +00:00
}
}
2018-03-11 16:28:22 +00:00
# fn is_a_variant() -> bool { true }
# fn main() {
2018-03-31 07:16:55 +00:00
# App::new()
2018-03-11 16:28:22 +00:00
# .resource("/register", |r| r.f(index))
# .finish();
# }
2018-03-10 18:12:44 +00:00
```
2018-01-23 04:10:05 +00:00
## Tokio core handle
2018-03-28 20:16:01 +00:00
Any actix web handler runs within a properly configured
2018-01-23 04:10:05 +00:00
[actix system](https://actix.github.io/actix/actix/struct.System.html)
and [arbiter](https://actix.github.io/actix/actix/struct.Arbiter.html).
2018-03-28 20:16:01 +00:00
You can always get access to the tokio handle via the
2018-01-23 04:10:05 +00:00
[Arbiter::handle()](https://actix.github.io/actix/actix/struct.Arbiter.html#method.handle)
method.