mirror of
https://github.com/actix/actix-website
synced 2025-01-23 00:25:55 +01:00
extractors: done-ish.
This commit is contained in:
parent
59f010461a
commit
c4c32091a6
@ -6,37 +6,26 @@ weight: 170
|
|||||||
|
|
||||||
# Type-safe information extraction
|
# Type-safe information extraction
|
||||||
|
|
||||||
Actix provides facility for type-safe request information extraction. By default,
|
Actix-web provides a facility for type-safe request information access called *extractors*
|
||||||
actix provides several extractor implementations.
|
(ie, `impl FromRequest`). By default, actix-web provides several extractor implementations.
|
||||||
|
|
||||||
# Accessing Extractors
|
## Extractors Within Handler Functions
|
||||||
|
|
||||||
How you access an Extractor depends on whether you are using a handler function
|
An extractor can be accessed in a few different ways.
|
||||||
or a custom Handler type.
|
|
||||||
|
|
||||||
## Within Handler Functions
|
Option 1 - passed as a parameter to a handler function:
|
||||||
|
|
||||||
An Extractor can be passed to a handler function as a function parameter
|
{{< include-example example="extractors" file="main.rs" section="option-one" >}}
|
||||||
*or* accessed within the function by calling the ExtractorType::<...>::extract(req)
|
|
||||||
function.
|
|
||||||
|
|
||||||
{{< include-example example="extractors" file="main.rs" section="main" >}}
|
Option 2 - accessed by calling `extract()` on the Extractor
|
||||||
|
|
||||||
## Within Custom Handler Types
|
{{< include-example example="extractors" file="main.rs" section="option-two" >}}
|
||||||
|
|
||||||
Like a handler function, a custom Handler type can *access* an Extractor by
|
|
||||||
calling the ExtractorType::<...>::extract(&req) function. An Extractor
|
|
||||||
*cannot* be passed as a parameter to a custom Handler type because a custom
|
|
||||||
Handler type must follow the ``handle`` function signature specified by the
|
|
||||||
Handler trait it implements.
|
|
||||||
|
|
||||||
{{< include-example example="extractors" file="custom_handler.rs" section="custom-handler" >}}
|
|
||||||
|
|
||||||
# Path
|
# Path
|
||||||
|
|
||||||
[*Path*](../../actix-web/actix_web/struct.Path.html) provides information that can
|
[*Path*](https://docs.rs/actix-web/1.0.2/actix_web/dev/struct.Path.html) provides
|
||||||
be extracted from the Request's path. You can deserialize any variable
|
information that can be extracted from the Request's path. You can deserialize any
|
||||||
segment from the path.
|
variable segment from the path.
|
||||||
|
|
||||||
For instance, for resource that registered for the `/users/{userid}/{friend}` path
|
For instance, for resource that registered for the `/users/{userid}/{friend}` path
|
||||||
two segments could be deserialized, `userid` and `friend`. These segments
|
two segments could be deserialized, `userid` and `friend`. These segments
|
||||||
@ -51,27 +40,31 @@ 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" >}}
|
||||||
|
|
||||||
|
It is also possible to `get` or `query` the request for path parameters by name:
|
||||||
|
|
||||||
|
{{< include-example example="extractors" file="path_three.rs" section="path-three" >}}
|
||||||
|
|
||||||
# Query
|
# Query
|
||||||
|
|
||||||
Same can be done with the request's query.
|
The [*Query*](https://docs.rs/actix-web/1.0.2/actix_web/web/struct.Query.html)
|
||||||
The [*Query*](../../actix-web/actix_web/struct.Query.html)
|
type provides extraction functionality for the request's query parameters. Underneath it
|
||||||
type provides extraction functionality. Underneath it uses *serde_urlencoded* crate.
|
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*](../../actix-web/actix_web/struct.Json.html) allows to deserialize
|
[*Json*](https://docs.rs/actix-web/1.0.2/actix_web/web/struct.Json.html) allows to deserialize
|
||||||
a request body into a struct. To extract typed information from a request's body,
|
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*.
|
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. Json extractor
|
Some extractors provide a way to configure the extraction process. Json extractor
|
||||||
[*JsonConfig*](../../actix-web/actix_web/dev/struct.JsonConfig.html) type for configuration.
|
[*JsonConfig*](https://docs.rs/actix-web/1.0.2/actix_web/web/struct.JsonConfig.html) type
|
||||||
When you register a handler using `Route::with()`, it returns a configuration instance. In case of
|
for configuration. When you register a handler using `Route::with()`, it returns a
|
||||||
a *Json* extractor it returns a *JsonConfig*. You can configure the maximum size of the json
|
configuration instance. In case of a *Json* extractor it returns a *JsonConfig*. You can
|
||||||
payload as well as a custom error handler function.
|
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.
|
||||||
|
|
||||||
@ -83,14 +76,14 @@ At the moment only url-encoded forms are supported. The url-encoded body
|
|||||||
could be extracted to a specific type. This type must implement
|
could be extracted to a specific type. This type must implement
|
||||||
the `Deserialize` trait from the *serde* crate.
|
the `Deserialize` trait from the *serde* crate.
|
||||||
|
|
||||||
[*FormConfig*](../../actix-web/actix_web/dev/struct.FormConfig.html) allows
|
[*FormConfig*](https://docs.rs/actix-web/1.0.2/actix_web/web/struct.FormConfig.html) allows
|
||||||
configuring the extraction process.
|
configuring the extraction process.
|
||||||
|
|
||||||
{{< include-example example="extractors" file="form.rs" section="form" >}}
|
{{< include-example example="extractors" file="form.rs" section="form" >}}
|
||||||
|
|
||||||
# Multiple extractors
|
# Multiple extractors
|
||||||
|
|
||||||
Actix provides extractor implementations for tuples (up to 10 elements)
|
Actix-web provides extractor implementations for tuples (up to 10 elements)
|
||||||
whose elements implement `FromRequest`.
|
whose elements implement `FromRequest`.
|
||||||
|
|
||||||
For example we can use a path extractor and a query extractor at the same time.
|
For example we can use a path extractor and a query extractor at the same time.
|
||||||
@ -99,15 +92,42 @@ For example we can use a path extractor and a query extractor at the same time.
|
|||||||
|
|
||||||
# Other
|
# Other
|
||||||
|
|
||||||
Actix also provides several other extractors:
|
Actix-web also provides several other extractors:
|
||||||
|
|
||||||
* [*Data*](../../actix-web/actix_web/web/struct.Data.html) - If you need
|
* [*Data*](https://docs.rs/actix-web/1.0.2/actix_web/web/struct.Data.html) - If you need
|
||||||
access to an application state. This is similar to a `HttpRequest::app_data()`.
|
access to an application state.
|
||||||
* *HttpRequest* - *HttpRequest* itself is an extractor which returns self,
|
* *HttpRequest* - *HttpRequest* itself is an extractor which returns self,
|
||||||
in case you need access to the request.
|
in case you need access to the request.
|
||||||
* *String* - You can convert a request's payload to a *String*.
|
* *String* - You can convert a request's payload to a *String*.
|
||||||
[*Example*](../../actix-web/actix_web/trait.FromRequest.html#example-1)
|
[*Example*](https://docs.rs/actix-web/1.0.2/actix_web/trait.FromRequest.html#example-2)
|
||||||
is available in doc strings.
|
is available in doc strings.
|
||||||
* *bytes::Bytes* - You can convert a request's payload into *Bytes*.
|
* *bytes::Bytes* - You can convert a request's payload into *Bytes*.
|
||||||
[*Example*](../../actix-web/actix_web/trait.FromRequest.html#example)
|
[*Example*](https://docs.rs/actix-web/1.0.2/actix_web/trait.FromRequest.html#example-4)
|
||||||
is available in doc strings.
|
is available in doc strings.
|
||||||
|
* *Payload* - You can access a request's payload.
|
||||||
|
[*Example*](https://docs.rs/actix-web/1.0.2/actix_web/web/struct.Payload.html)
|
||||||
|
|
||||||
|
# Async Data Access
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
> **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.
|
||||||
|
|
||||||
|
Here is an example of a handler that stores the number of processed requests:
|
||||||
|
|
||||||
|
{{< include-example example="request-handlers" file="main.rs" section="data" >}}
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
{{< include-example example="request-handlers" file="handlers_arc.rs" section="arc" >}}
|
||||||
|
|
||||||
|
> 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 [actix](https://actix.github.io/actix/actix/) actor system.
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
use actix_web::{web, HttpRequest, HttpResponse};
|
|
||||||
|
|
||||||
struct MyHandler {}
|
|
||||||
struct MyInfo {}
|
|
||||||
|
|
||||||
// <custom-handler>
|
|
||||||
impl<S> Handler<S> for MyHandler {
|
|
||||||
type Result = HttpResponse;
|
|
||||||
|
|
||||||
/// Handle request
|
|
||||||
fn handle(&self, req: &HttpRequest<S>) -> Self::Result {
|
|
||||||
let params = web::Path::<(String, String)>::extract(req);
|
|
||||||
let info = web::Json::<MyInfo>::extract(req);
|
|
||||||
|
|
||||||
HttpResponse::Ok().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// </custom-handler>
|
|
@ -1,5 +1,5 @@
|
|||||||
// <form>
|
// <form>
|
||||||
use actix_web::{web, App, Result};
|
use actix_web::{web, App, HttpServer, Result};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -16,5 +16,9 @@ fn index(form: web::Form<FormData>) -> Result<String> {
|
|||||||
// </form>
|
// </form>
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
App::new().route("", web::post().to(index));
|
HttpServer::new(|| App::new().route("/", web::post().to(index)))
|
||||||
|
.bind("127.0.0.1:8088")
|
||||||
|
.unwrap()
|
||||||
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <json-one>
|
// <json-one>
|
||||||
use actix_web::{web, App, Result};
|
use actix_web::{web, App, HttpServer, Result};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -11,8 +11,12 @@ struct Info {
|
|||||||
fn index(info: web::Json<Info>) -> Result<String> {
|
fn index(info: web::Json<Info>) -> Result<String> {
|
||||||
Ok(format!("Welcome {}!", info.username))
|
Ok(format!("Welcome {}!", info.username))
|
||||||
}
|
}
|
||||||
|
// </json-one>
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
App::new().route("/", web::get().to(index));
|
HttpServer::new(|| App::new().route("/", web::post().to(index)))
|
||||||
|
.bind("127.0.0.1:8088")
|
||||||
|
.unwrap()
|
||||||
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
// </json-one>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <json-two>
|
// <json-two>
|
||||||
use actix_web::{error, web, App, FromRequest, HttpResponse, Responder};
|
use actix_web::{error, web, App, FromRequest, HttpResponse, HttpServer, Responder};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -13,6 +13,7 @@ fn index(info: web::Json<Info>) -> impl Responder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
HttpServer::new(|| {
|
||||||
App::new().service(
|
App::new().service(
|
||||||
web::resource("/")
|
web::resource("/")
|
||||||
.data(
|
.data(
|
||||||
@ -29,6 +30,11 @@ pub fn main() {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.route(web::post().to(index)),
|
.route(web::post().to(index)),
|
||||||
);
|
)
|
||||||
|
})
|
||||||
|
.bind("127.0.0.1:8088")
|
||||||
|
.unwrap()
|
||||||
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
// </json-two>
|
// </json-two>
|
||||||
|
@ -8,6 +8,7 @@ pub mod json_one;
|
|||||||
pub mod json_two;
|
pub mod json_two;
|
||||||
pub mod multiple;
|
pub mod multiple;
|
||||||
pub mod path_one;
|
pub mod path_one;
|
||||||
|
pub mod path_three;
|
||||||
pub mod path_two;
|
pub mod path_two;
|
||||||
pub mod query;
|
pub mod query;
|
||||||
|
|
||||||
@ -17,13 +18,13 @@ struct MyInfo {
|
|||||||
id: u32,
|
id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// <main>
|
// <option-one>
|
||||||
// Option 1: passed as a parameter to a handler function
|
|
||||||
fn index(path: web::Path<(String, String)>, json: web::Json<MyInfo>) -> impl Responder {
|
fn index(path: web::Path<(String, String)>, json: web::Json<MyInfo>) -> impl Responder {
|
||||||
format!("{} {} {} {}", path.0, path.1, json.id, json.username)
|
format!("{} {} {} {}", path.0, path.1, json.id, json.username)
|
||||||
}
|
}
|
||||||
|
// </option-one>
|
||||||
|
|
||||||
// Option 2: accessed by calling extract() on the Extractor
|
// <option-two>
|
||||||
fn extract(req: HttpRequest) -> impl Responder {
|
fn extract(req: HttpRequest) -> impl Responder {
|
||||||
let params = web::Path::<(String, String)>::extract(&req).unwrap();
|
let params = web::Path::<(String, String)>::extract(&req).unwrap();
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ fn extract(req: HttpRequest) -> impl Responder {
|
|||||||
|
|
||||||
format!("{} {} {} {}", params.0, params.1, info.username, info.id)
|
format!("{} {} {} {}", params.0, params.1, info.username, info.id)
|
||||||
}
|
}
|
||||||
// </main>
|
// </option-two>
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <multi>
|
// <multi>
|
||||||
use actix_web::{web, App};
|
use actix_web::{web, App, HttpServer};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -7,14 +7,23 @@ struct Info {
|
|||||||
username: String,
|
username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn index((_path, query): (web::Path<(u32, String)>, web::Query<Info>)) -> String {
|
fn index((path, query): (web::Path<(u32, String)>, web::Query<Info>)) -> String {
|
||||||
format!("Welcome {}!", query.username)
|
format!(
|
||||||
|
"Welcome {}, friend {}, useri {}!",
|
||||||
|
query.username, path.1, path.0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
HttpServer::new(|| {
|
||||||
App::new().route(
|
App::new().route(
|
||||||
"/users/{userid}/{friend}", // <- define path parameters
|
"/users/{userid}/{friend}", // <- define path parameters
|
||||||
web::get().to(index),
|
web::get().to(index),
|
||||||
);
|
)
|
||||||
|
})
|
||||||
|
.bind("127.0.0.1:8088")
|
||||||
|
.unwrap()
|
||||||
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
// </multi>
|
// </multi>
|
||||||
|
@ -1,17 +1,23 @@
|
|||||||
// <path-one>
|
// <path-one>
|
||||||
use actix_web::{web, App, Result};
|
use actix_web::{web, App, HttpServer, Result};
|
||||||
|
|
||||||
/// extract path info from "/users/{userid}/{friend}" url
|
/// extract path info from "/users/{userid}/{friend}" url
|
||||||
/// {userid} - - deserializes to a u32
|
/// {userid} - - deserializes to a u32
|
||||||
/// {friend} - deserializes to a String
|
/// {friend} - deserializes to a String
|
||||||
fn index(info: web::Path<(u32, String)>) -> Result<String> {
|
fn index(info: web::Path<(u32, String)>) -> Result<String> {
|
||||||
Ok(format!("Welcome {}! {}", info.1, info.0))
|
Ok(format!("Welcome {}, userid {}!", info.1, info.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
HttpServer::new(|| {
|
||||||
App::new().route(
|
App::new().route(
|
||||||
"/users/{userid}/{friend}", // <- define path parameters
|
"/users/{userid}/{friend}", // <- define path parameters
|
||||||
web::get().to(index),
|
web::get().to(index),
|
||||||
);
|
)
|
||||||
|
})
|
||||||
|
.bind("127.0.0.1:8088")
|
||||||
|
.unwrap()
|
||||||
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
// </path-one>
|
// </path-one>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <path-two>
|
// <path-two>
|
||||||
use actix_web::{web, App, Result};
|
use actix_web::{web, App, HttpServer, Result};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -14,9 +14,15 @@ fn index(info: web::Path<Info>) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
HttpServer::new(|| {
|
||||||
App::new().route(
|
App::new().route(
|
||||||
"/users/{userid}/{friend}", // <- define path parameters
|
"/users/{userid}/{friend}", // <- define path parameters
|
||||||
web::get().to(index),
|
web::get().to(index),
|
||||||
);
|
)
|
||||||
|
})
|
||||||
|
.bind("127.0.0.1:8088")
|
||||||
|
.unwrap()
|
||||||
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
// </path-two>
|
// </path-two>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <query>
|
// <query>
|
||||||
use actix_web::{web, App};
|
use actix_web::{web, App, HttpServer};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -11,8 +11,12 @@ struct Info {
|
|||||||
fn index(info: web::Query<Info>) -> String {
|
fn index(info: web::Query<Info>) -> String {
|
||||||
format!("Welcome {}!", info.username)
|
format!("Welcome {}!", info.username)
|
||||||
}
|
}
|
||||||
|
// </query>
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
App::new().route("/", web::get().to(index));
|
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
||||||
|
.bind("127.0.0.1:8088")
|
||||||
|
.unwrap()
|
||||||
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
// </query>
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "request-handlers"
|
name = "request-handlers"
|
||||||
version = "0.7.0"
|
version = "1.0.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "0.7"
|
actix-web = "1.0"
|
||||||
actix = "0.7"
|
|
||||||
|
@ -1,34 +1,37 @@
|
|||||||
// <arc>
|
// <arc>
|
||||||
use actix_web::{dev::Handler, server, App, HttpRequest, HttpResponse};
|
use actix_web::{web, App, HttpServer, Responder};
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
struct MyHandler(Arc<AtomicUsize>);
|
#[derive(Clone)]
|
||||||
|
struct AppState {
|
||||||
impl<S> Handler<S> for MyHandler {
|
count: Arc<AtomicUsize>,
|
||||||
type Result = HttpResponse;
|
|
||||||
|
|
||||||
/// Handle request
|
|
||||||
fn handle(&self, _req: &HttpRequest<S>) -> Self::Result {
|
|
||||||
self.0.fetch_add(1, Ordering::Relaxed);
|
|
||||||
HttpResponse::Ok().into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_count(data: web::Data<AppState>) -> impl Responder {
|
||||||
|
format!("count: {}", data.count.load(Ordering::Relaxed))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_one(data: web::Data<AppState>) -> impl Responder {
|
||||||
|
data.count.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
format!("count: {}", data.count.load(Ordering::Relaxed))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let sys = actix::System::new("example");
|
let data = AppState {
|
||||||
|
count: Arc::new(AtomicUsize::new(0)),
|
||||||
|
};
|
||||||
|
|
||||||
let inc = Arc::new(AtomicUsize::new(0));
|
HttpServer::new(move || {
|
||||||
|
App::new()
|
||||||
server::new(move || {
|
.data(data.clone())
|
||||||
let cloned = inc.clone();
|
.route("/", web::to(show_count))
|
||||||
App::new().resource("/", move |r| r.h(MyHandler(cloned)))
|
.route("/add", web::to(add_one))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")
|
.bind("127.0.0.1:8088")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.start();
|
.run()
|
||||||
|
.unwrap();
|
||||||
println!("Started http server: 127.0.0.1:8088");
|
|
||||||
let _ = sys.run();
|
|
||||||
}
|
}
|
||||||
// </arc>
|
// </arc>
|
||||||
|
@ -1,25 +1,38 @@
|
|||||||
mod handlers_arc;
|
pub mod handlers_arc;
|
||||||
// <handler>
|
// <data>
|
||||||
use actix_web::{dev::Handler, server, App, HttpRequest, HttpResponse};
|
use actix_web::{web, App, HttpServer, Responder};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
struct MyHandler(Cell<usize>);
|
#[derive(Clone)]
|
||||||
|
struct AppState {
|
||||||
impl<S> Handler<S> for MyHandler {
|
count: Cell<i32>,
|
||||||
type Result = HttpResponse;
|
|
||||||
|
|
||||||
/// Handle request
|
|
||||||
fn handle(&self, _req: &HttpRequest<S>) -> Self::Result {
|
|
||||||
let i = self.0.get();
|
|
||||||
self.0.set(i + 1);
|
|
||||||
HttpResponse::Ok().into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_count(data: web::Data<AppState>) -> impl Responder {
|
||||||
|
format!("count: {}", data.count.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_one(data: web::Data<AppState>) -> impl Responder {
|
||||||
|
let count = data.count.get();
|
||||||
|
data.count.set(count + 1);
|
||||||
|
|
||||||
|
format!("count: {}", data.count.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
server::new(|| App::new().resource("/", |r| r.h(MyHandler(Cell::new(0))))) //use r.h() to bind handler, not the r.f()
|
let data = AppState {
|
||||||
|
count: Cell::new(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
HttpServer::new(move || {
|
||||||
|
App::new()
|
||||||
|
.data(data.clone())
|
||||||
|
.route("/", web::to(show_count))
|
||||||
|
.route("/add", web::to(add_one))
|
||||||
|
})
|
||||||
.bind("127.0.0.1:8088")
|
.bind("127.0.0.1:8088")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.run();
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
// </handler>
|
// </data>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user