From 3ffd36eee21dcb8fea595a8091ef240d666f6a05 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 1 Dec 2017 23:06:15 -0800 Subject: [PATCH] some more guide --- guide/src/SUMMARY.md | 5 +- guide/src/qs_3.md | 180 +------------------------------------------ 2 files changed, 5 insertions(+), 180 deletions(-) diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index 345b29f00..ae94193ed 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -2,4 +2,7 @@ [Quickstart](./qs_1.md) - [Getting Started](./qs_2.md) -- [Actix web overview](./qs_3.md) +- [Actix application](./qs_3.md) +- [Handler](./qs_4.md) +- [Resources and Routes](./qs_5.md) +- [Application state](./qs_6.md) diff --git a/guide/src/qs_3.md b/guide/src/qs_3.md index 60b16f533..faedb9483 100644 --- a/guide/src/qs_3.md +++ b/guide/src/qs_3.md @@ -1,12 +1,9 @@ -# [WIP] Overview +# Application Actix web provides some primitives to build web servers and applications with Rust. It provides routing, middlewares, pre-processing of requests, and post-processing of responses, websocket protcol handling, multipart streams, etc. - -## Application - All actix web server is built around `Application` instance. It is used for registering handlers for routes and resources, middlewares. Also it stores applicationspecific state that is shared accross all handlers @@ -23,178 +20,3 @@ has same url path prefix: In this example application with `/prefix` prefix and `index.html` resource get created. This resource is available as on `/prefix/index.html` url. - -### Application state - -Application state is shared with all routes within same application. -State could be accessed with `HttpRequest::state()` method. It is read-only -but interior mutability pattern with `RefCell` could be used to archive state mutability. -State could be accessed with `HttpRequest::state()` method or -`HttpContext::state()` in case of http actor. - -Let's write simple application that uses shared state. We are going to store requests count -in the state: - -```rust -extern crate actix; -extern crate actix_web; - -use std::cell::Cell; -use actix_web::*; - -// This struct represents state -struct AppState { - counter: Cell, -} - -fn index(req: HttpRequest) -> String { - let count = req.state().counter.get() + 1; // <- get count - req.state().counter.set(count); // <- store new count in state - - format!("Request number: {}", count) // <- response with count -} - -fn main() { - Application::build("/", AppState{counter: Cell::new(0)}) - .resource("/", |r| r.handler(Method::GET, index)) - .finish(); -} -``` - -## [WIP] Handler - -A request handler can by any object that implements -[`Handler` trait](../actix_web/struct.HttpResponse.html#implementations). - -By default actix provdes several `Handler` implementations: - -* Simple function that accepts `HttpRequest` and returns any object that - can be converted to `HttpResponse` -* Function that accepts `HttpRequest` and returns `Result>` object. -* Function that accepts `HttpRequest` and return actor that has `HttpContext`as a context. - -Actix provides response conversion into `HttpResponse` for some standard types, -like `&'static str`, `String`, etc. -For complete list of implementations check -[HttpResponse documentation](../actix_web/struct.HttpResponse.html#implementations). - -Examples: - -```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> { - ... -} -``` - -### Custom conversion - -Let's create response for custom type that serializes to `application/json` response: - -```rust -extern crate actix; -extern crate actix_web; -extern crate serde; -extern crate serde_json; -#[macro_use] extern crate serde_derive; -use actix_web::*; - -#[derive(Serialize)] -struct MyObj { - name: String, -} - -/// we have to convert Error into HttpResponse as well, but with -/// specialization this could be handled genericly. -impl Into for MyObj { - fn into(self) -> HttpResponse { - let body = match serde_json::to_string(&self) { - Err(err) => return Error::from(err).into(), - Ok(body) => body, - }; - - // Create response and set content type - HttpResponse::Ok() - .content_type("application/json") - .body(body).unwrap() - } -} - -fn main() { - let sys = actix::System::new("example"); - - HttpServer::new( - Application::default("/") - .resource("/", |r| r.handler( - Method::GET, |req| {MyObj{name: "user".to_owned()}}))) - .serve::<_, ()>("127.0.0.1:8088").unwrap(); - - println!("Started http server: 127.0.0.1:8088"); - actix::Arbiter::system().send(actix::msgs::SystemExit(0)); // <- remove this line, this code stops system during testing - - let _ = sys.run(); -} -``` - -If `specialization` is enabled, conversion could be simplier: - -```rust,ignore -impl Into> for MyObj { - fn into(self) -> Result { - let body = serde_json::to_string(&self)?; - - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(body)?) - } -} -``` - -### Async handlers - -There are two different types of async handlers. - -Response object could be generated asynchronously. In this case handle must -return `Future` object that resolves to `HttpResponse`, i.e: - -```rust,ignore -fn index(req: HttpRequest) -> Box> { - ... -} -``` - -This handler can be registered with `ApplicationBuilder::async()` and -`Resource::async()` methods. - -Or response body can be generated asynchronously. In this case body -must implement stream trait `Stream`, i.e: - - -```rust,ignore -fn index(req: HttpRequest) -> HttpResponse { - let body: Box> = Box::new(SomeStream::new()); - - HttpResponse::Ok(). - .content_type("application/json") - .body(Body::Streaming(body)).unwrap() -} -``` - -Both methods could be combined. (i.e Async response with streaming body)