1
0
mirror of https://github.com/actix/actix-website synced 2024-11-27 18:12:57 +01:00

Intro: done-ish. Getting Started: done-ish. Application: done-ish.

This commit is contained in:
Cameron Dershem 2019-06-19 18:00:31 -04:00
parent da969fed1f
commit ea7bc84f8d
11 changed files with 145 additions and 66 deletions

View File

@ -10,16 +10,16 @@ weight: 140
It provides routing, middlewares, pre-processing of requests, post-processing of
responses, etc.
All actix web servers are built around the `App` instance. It is used for
All `actix-web` servers are built around the `App` instance. It is used for
registering routes for resources and middlewares. It also stores application
state shared across all handlers within same application.
state shared across all handlers within same scope.
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.
If a supplied prefix does not contain leading slash, it is automatically inserted.
The prefix should consist of value path segments.
An application's `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.
> For an application with prefix `/app`,
> 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.
@ -31,9 +31,9 @@ are created. This resource is available through the `/app/index.html` url.
> For more information, check the
> [URL Dispatch](/docs/url-dispatch/index.html#using-an-application-prefix-to-compose-applications) section.
Multiple applications can be served with one server:
Multiple application scopes can be served with one server:
{{< include-example example="application" file="main.rs" section="run_server" >}}
{{< include-example example="application" file="main.rs" section="multi" >}}
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 a more generic
@ -43,10 +43,10 @@ as the first application, it would match all incoming requests.
## State
Application state is shared with all routes and resources within the same application.
When using an http actor, state can be accessed with the `HttpRequest::state()` as read-only,
but interior mutability with `RefCell` can be used to achieve state mutability.
State is also available for route matching predicates and middlewares.
Application state is shared with all routes and resources within the same scope. State
can be accessed with `web::Data<State>` as read-only, but interior mutability with
`Cell` can be used to achieve state mutability. State is also available for route
matching guards and middlewares.
Let's write a simple application that uses shared state. We are going to store request count
in the state:
@ -57,10 +57,12 @@ When the app is initialized it needs to be passed the initial state:
{{< include-example example="application" file="state.rs" section="make_app" >}}
> **Note**: http server accepts an application factory rather than an application
> 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
> shared object should be used, e.g. `Arc`. There is also an [Example](https://github.com/actix/examples/blob/master/state/src/main.rs) using `Arc` for this. Application state does not need to be `Send` and `Sync`,
> **Note**: `HttpServer` accepts an application factory rather than an application
> instance. `HttpServer` 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 shared object should be used, e.g. `Arc`. There is also an
> [Example](https://github.com/actix/examples/blob/master/state/src/main.rs) using `Arc`
> for this. Application state does not need to be `Send` and `Sync`,
> but the application factory must be `Send` + `Sync`.
To start the previous app, create it into a closure:
@ -71,10 +73,6 @@ To start the previous app, create it into a closure:
Combining multiple applications with different state is possible as well.
[server::new](https://docs.rs/actix-web/*/actix_web/server/fn.new.html) requires the handler to have a single type.
This limitation can easily be overcome with the [App::boxed](https://docs.rs/actix-web/*/actix_web/struct.App.html#method.boxed) method, which converts an App into a boxed trait object.
{{< include-example example="application" file="combine.rs" section="combine" >}}
## Using an Application Scope to Compose Applications
@ -87,7 +85,7 @@ resource names.
For example:
{{< include-example example="url-dispatch" 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* instead of */show* because the application's scope argument will be prepended
@ -99,11 +97,31 @@ it will generate a URL with that same path.
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`](../actix_web/guard/trait.Guard.html) trait. Actix provides
several guards, you can check
[functions section](../../actix-web/actix_web/guard/index.html#functions) of api docs.
[`Guard`](https://docs.rs/actix-web/1.0.2/actix_web/guard/trait.Guard.html) trait. Actix-web
provides several guards, you can check
[functions section](https://docs.rs/actix-web/1.0.2/actix_web/guard/index.html#functions)
of api docs.
One of the provided guards is [`Host`](../actix_web/guard/fn.Host.html), it can be used
as application's filter based on request's host information.
One of the provided guards is [`Header`](https://docs.rs/actix-web/1.0.2/actix_web/guard/fn.Header.html),
it can be used as application's filter based on request's header information.
{{< include-example example="application" file="vh.rs" section="vh" >}}
# Configure
For simplicity and reusability both `App` and `web::scope` provide the `configure` method.
This function is useful for moving parts of configuration to a different module or even
library. For example, some of the resource's configuration could be moved to different
module.
{{< include-example example="application" file="config.rs" section="config" >}}
The result of the above example would be:
```
/ -> "/"
/app -> "app"
/api/test -> "test"
```
Each `ServiceConfig` can have it's own `data`, `routes`, and `services`

View File

@ -6,7 +6,7 @@ weight: 130
# Getting Started
Lets write our first actix web application!
Lets write our first `actix-web` application!
## Hello, world!
@ -27,17 +27,16 @@ actix-web = "{{< actix-version "actix-web" >}}"
In order to implement a web server, we first need to create a request handler.
A request handler is a function that accepts any type that can be extracted from a
request (ie, `impl FromRequest`) as its only parameter and returns a type that
can be converted into an `HttpResponse` (ie, `impl Responder`):
A request handler is a function that accepts zero or more parameters that can be
extracted from a request (ie, `impl FromRequest`) and returns a type that can be
converted into an `HttpResponse` (ie, `impl Responder`):
{{< include-example example="getting-started" section="setup" >}}
Next, create an `App` instance and register the request handler with
the application's `route` on a particular *HTTP method* and *path* and
after that, the application instance can be used with `HttpServer` to listen
for incoming connections. The server accepts a function that should return an
application factory.
Next, create an `App` instance and register the request handler with the application's
`route` on a *path* and with a particular *HTTP method*. After that, the application
instance can be used with `HttpServer` to listen for incoming connections. The server
accepts a function that should return an application factory.
{{< include-example example="getting-started" section="main" >}}

View File

@ -6,7 +6,7 @@ weight: 150
# The HTTP Server
The [**HttpServer**](../../actix-web/actix_web/server/struct.HttpServer.html) type is responsible for
The [**HttpServer**](https://docs.rs/actix-web/1.0.2/actix_web/struct.HttpServer.html) type is responsible for
serving http requests.
`HttpServer` accepts an application factory as a parameter, and the

View File

@ -5,7 +5,10 @@ fn index(_req: HttpRequest) -> impl Responder {
"Hello world!"
}
#[rustfmt::skip]
pub fn main() {
App::new().service(web::scope("/app").route("/index.html", web::get().to(index)));
App::new().service(
web::scope("/app")
.route("/index.html", web::get().to(index)));
}
// </setup>

View File

@ -8,13 +8,13 @@ struct State2;
pub fn main() {
HttpServer::new(|| {
App::new()
.data(State1)
.data(State2)
.service(
web::scope("/app1")
.data(State1)
.route("/", web::to(|| HttpResponse::Ok())))
.service(
web::scope("/app2")
.data(State2)
.route("/", web::to(|| HttpResponse::Ok())))
})
.bind("127.0.0.1:8088")

View File

@ -0,0 +1,34 @@
// <config>
use actix_web::{web, App, HttpResponse, HttpServer};
// this function could be located in different module
fn scoped_config(cfg: &mut web::ServiceConfig) {
cfg.service(
web::resource("/test")
.route(web::get().to(|| HttpResponse::Ok().body("test")))
.route(web::head().to(|| HttpResponse::MethodNotAllowed())),
);
}
// this function could be located in different module
fn config(cfg: &mut web::ServiceConfig) {
cfg.service(
web::resource("/app")
.route(web::get().to(|| HttpResponse::Ok().body("app")))
.route(web::head().to(|| HttpResponse::MethodNotAllowed())),
);
}
pub fn main() {
HttpServer::new(|| {
App::new()
.configure(config)
.service(web::scope("/api").configure(scoped_config))
.route("/", web::get().to(|| HttpResponse::Ok().body("/")))
})
.bind("127.0.0.1:8088")
.unwrap()
.run()
.unwrap();
}
// </config>

View File

@ -1,14 +1,15 @@
use actix_web::{web, App, HttpResponse, HttpServer};
use actix_web::{web, App, HttpResponse};
pub mod app;
pub mod combine;
pub mod config;
pub mod scope;
pub mod state;
pub mod vh;
#[rustfmt::skip]
// <run_server>
// <multi>
fn main() {
HttpServer::new(|| {
App::new()
.service(
web::scope("/app1")
@ -16,7 +17,6 @@ fn main() {
.service(
web::scope("/app2")
.route("/", web::to(|| HttpResponse::Ok())))
.route("/", web::to(|| HttpResponse::Ok()))
});
.route("/", web::to(|| HttpResponse::Ok()));
}
// </run_server>
// </multi>

View File

@ -0,0 +1,15 @@
use actix_web::{web, App, HttpRequest, Responder};
fn show_users(_req: HttpRequest) -> impl Responder {
unimplemented!()
}
#[rustfmt::skip]
// <scope>
pub fn main() {
App::new()
.service(
web::scope("/users")
.route("/show", web::get().to(show_users)));
}
// </scope>

View File

@ -4,7 +4,7 @@ use std::cell::Cell;
// This struct represents state
struct AppState {
counter: Cell<usize>,
counter: Cell<i32>,
}
fn index(data: web::Data<AppState>) -> String {

View File

@ -1,22 +1,24 @@
#![allow(unused)]
use actix_web::{guard, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
use actix_web::{guard, web, App, HttpResponse, HttpServer};
// <vh>
fn main() {
pub fn main() {
HttpServer::new(|| {
App::new()
.service(
web::scope("/")
.guard(guard::Header("Host", "www.rust-lang.org"))
.route("", web::to(|| HttpResponse::Ok())),
.route("", web::to(|| HttpResponse::Ok().body("www"))),
)
.service(
web::scope("/")
.guard(guard::Header("Host", "users.rust-lang.org"))
.route("", web::to(|| HttpResponse::Ok())),
.route("", web::to(|| HttpResponse::Ok().body("user"))),
)
.route("/", web::to(|| HttpResponse::Ok()))
})
.run();
.bind("127.0.0.1:8088")
.unwrap()
.run()
.unwrap();
}
// </vh>

View File

@ -1,14 +1,22 @@
// <setup>
use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer, Responder};
fn index(_req: HttpRequest) -> impl Responder {
fn index() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
fn index2(_req: HttpRequest) -> impl Responder {
HttpResponse::Ok().body("Hello world again!")
}
// </setup>
// <main>
fn main() {
HttpServer::new(|| App::new().route("/", web::get().to(index)))
HttpServer::new(|| {
App::new()
.route("/", web::get().to(index))
.route("/again", web::get().to(index2))
})
.bind("127.0.0.1:8088")
.unwrap()
.run()