1
0
mirror of https://github.com/actix/actix-website synced 2025-02-17 10:13:31 +01:00

update user guide

This commit is contained in:
Nikolay Kim 2018-07-21 05:40:42 -07:00
parent 5cd8d2edc8
commit 4a41b92cc7
14 changed files with 62 additions and 69 deletions

View File

@ -15,5 +15,5 @@ baseURL = "https://actix.rs"
weight = 1 weight = 1
[params] [params]
actixVersion = "0.5" actixVersion = "0.7"
actixWebVersion = "0.6" actixWebVersion = "0.7"

View File

@ -46,7 +46,7 @@ extern crate listenfd;
use listenfd::ListenFd; use listenfd::ListenFd;
use actix_web::{server, App, HttpRequest, Responder}; use actix_web::{server, App, HttpRequest, Responder};
fn index(_req: HttpRequest) -> impl Responder { fn index(_req: &HttpRequest) -> impl Responder {
"Hello World!" "Hello World!"
} }

View File

@ -79,7 +79,7 @@ can access it.
```rust ```rust
/// This is state where we will store *DbExecutor* address. /// This is state where we will store *DbExecutor* address.
struct State { struct State {
db: Addr<Syn, DbExecutor>, db: Addr<DbExecutor>,
} }
fn main() { fn main() {
@ -109,7 +109,7 @@ thus, we receive the message response asynchronously.
```rust ```rust
/// Async handler /// Async handler
fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>> { fn index(req: &HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>> {
let name = &req.match_info()["name"]; let name = &req.match_info()["name"];
// Send message to `DbExecutor` actor // Send message to `DbExecutor` actor
@ -129,4 +129,4 @@ fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>>
> [examples directory](https://github.com/actix/examples/tree/master/diesel/). > [examples directory](https://github.com/actix/examples/tree/master/diesel/).
> More information on sync actors can be found in the > More information on sync actors can be found in the
> [actix documentation](https://docs.rs/actix/0.5.0/actix/sync/index.html). > [actix documentation](https://docs.rs/actix/0.7.0/actix/sync/index.html).

View File

@ -40,7 +40,7 @@ converted into an `HttpInternalServerError`:
```rust ```rust
use std::io; use std::io;
fn index(req: HttpRequest) -> io::Result<fs::NamedFile> { fn index(req: &HttpRequest) -> io::Result<fs::NamedFile> {
Ok(fs::NamedFile::open("static/index.html")?) Ok(fs::NamedFile::open("static/index.html")?)
} }
``` ```
@ -64,7 +64,7 @@ struct MyError {
// Use default implementation for `error_response()` method // Use default implementation for `error_response()` method
impl error::ResponseError for MyError {} impl error::ResponseError for MyError {}
fn index(req: HttpRequest) -> Result<&'static str, MyError> { fn index(req: &HttpRequest) -> Result<&'static str, MyError> {
Err(MyError{name: "test"}) Err(MyError{name: "test"})
} }
``` ```
@ -102,7 +102,7 @@ impl error::ResponseError for MyError {
} }
} }
fn index(req: HttpRequest) -> Result<&'static str, MyError> { fn index(req: &HttpRequest) -> Result<&'static str, MyError> {
Err(MyError::BadClientData) Err(MyError::BadClientData)
} }
``` ```
@ -123,7 +123,7 @@ struct MyError {
name: &'static str name: &'static str
} }
fn index(req: HttpRequest) -> Result<&'static str> { fn index(req: &HttpRequest) -> Result<&'static str> {
let result: Result<&'static str, MyError> = Err(MyError{name: "test"}); let result: Result<&'static str, MyError> = Err(MyError{name: "test"});
Ok(result.map_err(|e| error::ErrorBadRequest(e.name))?) Ok(result.map_err(|e| error::ErrorBadRequest(e.name))?)
@ -220,7 +220,7 @@ impl error::ResponseError for UserError {
} }
} }
fn index(_req: HttpRequest) -> Result<&'static str, UserError> { fn index(_: &HttpRequest) -> Result<&'static str, UserError> {
fs::NamedFile::open("static/index.html").map_err(|_e| UserError::InternalError)?; fs::NamedFile::open("static/index.html").map_err(|_e| UserError::InternalError)?;
Ok("success!") Ok("success!")
} }

View File

@ -31,9 +31,9 @@ fn index((params, info): (Path<(String, String,)>, Json<MyInfo>)) -> HttpRespons
use actix_web::FromRequest; use actix_web::FromRequest;
fn index(req: HttpRequest) -> HttpResponse { fn index(req: &HttpRequest) -> HttpResponse {
let params = Path::<(String, String)>::extract(&req); let params = Path::<(String, String)>::extract(req);
let info = Json::<MyInfo>::extract(&req); let info = Json::<MyInfo>::extract(req);
... ...
} }
@ -55,9 +55,9 @@ impl<S> Handler<S> for MyHandler {
type Result = HttpResponse; type Result = HttpResponse;
/// Handle request /// Handle request
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result { fn handle(&self, req: &HttpRequest<S>) -> Self::Result {
let params = Path::<(String, String)>::extract(&req); let params = Path::<(String, String)>::extract(req);
let info = Json::<MyInfo>::extract(&req); let info = Json::<MyInfo>::extract(req);
... ...
@ -204,11 +204,12 @@ fn main() {
let app = App::new().resource( let app = App::new().resource(
"/index.html", |r| { "/index.html", |r| {
r.method(http::Method::POST) r.method(http::Method::POST)
.with(index) .with_config(index, |cfg| {
.limit(4096) // <- change json extractor configuration cfg.limit(4096) // <- change json extractor configuration
.error_handler(|err, req| { // <- create custom error response cfg.error_handler(|err, req| { // <- create custom error response
error::InternalError::from_response( error::InternalError::from_response(
err, HttpResponse::Conflict().finish()).into() err, HttpResponse::Conflict().finish()).into()
})
}); });
}); });
} }

View File

@ -23,13 +23,13 @@ such as `&'static str`, `String`, etc.
Examples of valid handlers: Examples of valid handlers:
```rust ```rust
fn index(req: HttpRequest) -> &'static str { fn index(req: &HttpRequest) -> &'static str {
"Hello world!" "Hello world!"
} }
``` ```
```rust ```rust
fn index(req: HttpRequest) -> String { fn index(req: &HttpRequest) -> String {
"Hello world!".to_owned() "Hello world!".to_owned()
} }
``` ```
@ -38,13 +38,13 @@ You can also change the signature to return `impl Responder` which works well if
complex types are involved. complex types are involved.
```rust ```rust
fn index(req: HttpRequest) -> impl Responder { fn index(req: &HttpRequest) -> impl Responder {
Bytes::from_static("Hello world!") Bytes::from_static("Hello world!")
} }
``` ```
```rust,ignore ```rust,ignore
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> { fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
... ...
} }
``` ```
@ -54,8 +54,8 @@ Application state is accessible from the handler with the `HttpRequest::state()`
however, state is accessible as a read-only reference. If you need mutable access to state, however, state is accessible as a read-only reference. If you need mutable access to state,
it must be implemented. it must be implemented.
> **Note**: Alternatively, the handler can mutably access its own state because the `handle` method takes > **Note**: Alternatively, the handler can use interior mutably to access its own
> mutable reference to *self*. **Beware**, actix creates multiple copies > state. **Beware**, actix creates multiple copies
> of the application state and the handlers, unique for each thread. If you run your > 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 > application in several threads, actix will create the same amount as number of threads
> of application state objects and handler objects. > of application state objects and handler objects.
@ -65,14 +65,15 @@ Here is an example of a handler that stores the number of processed requests:
```rust ```rust
use actix_web::{App, HttpRequest, HttpResponse, dev::Handler}; use actix_web::{App, HttpRequest, HttpResponse, dev::Handler};
struct MyHandler(usize); struct MyHandler(Cell<usize>);
impl<S> Handler<S> for MyHandler { impl<S> Handler<S> for MyHandler {
type Result = HttpResponse; type Result = HttpResponse;
/// Handle request /// Handle request
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result { fn handle(&self, req: &HttpRequest<S>) -> Self::Result {
self.0 += 1; let i = self.0.get();
self.0.set(i + 1);
HttpResponse::Ok().into() HttpResponse::Ok().into()
} }
} }
@ -92,7 +93,7 @@ impl<S> Handler<S> for MyHandler {
type Result = HttpResponse; type Result = HttpResponse;
/// Handle request /// Handle request
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result { fn handle(&self, req: &HttpRequest<S>) -> Self::Result {
self.0.fetch_add(1, Ordering::Relaxed); self.0.fetch_add(1, Ordering::Relaxed);
HttpResponse::Ok().into() HttpResponse::Ok().into()
} }
@ -156,7 +157,7 @@ impl Responder for MyObj {
} }
} }
fn index(req: HttpRequest) -> impl Responder { fn index(req: &HttpRequest) -> impl Responder {
MyObj { name: "user" } MyObj { name: "user" }
} }
@ -187,7 +188,7 @@ use bytes::Bytes;
use futures::stream::once; use futures::stream::once;
use futures::future::{Future, result}; use futures::future::{Future, result};
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> { fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
result(Ok(HttpResponse::Ok() result(Ok(HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
@ -195,7 +196,7 @@ fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
.responder() .responder()
} }
fn index2(req: HttpRequest) -> Box<Future<Item=&'static str, Error=Error>> { fn index2(req: &HttpRequest) -> Box<Future<Item=&'static str, Error=Error>> {
result(Ok("Welcome!")) result(Ok("Welcome!"))
.responder() .responder()
} }
@ -216,7 +217,7 @@ use actix_web::*;
use bytes::Bytes; use bytes::Bytes;
use futures::stream::once; use futures::stream::once;
fn index(req: HttpRequest) -> HttpResponse { fn index(req: &HttpRequest) -> HttpResponse {
let body = once(Ok(Bytes::from_static(b"test"))); let body = once(Ok(Bytes::from_static(b"test")));
HttpResponse::Ok() HttpResponse::Ok()
@ -243,7 +244,7 @@ use bytes::Bytes;
use futures::stream::once; use futures::stream::once;
use futures::future::{Future, result}; use futures::future::{Future, result};
fn index(req: HttpRequest) -> Result<Box<Future<Item=HttpResponse, Error=Error>>, Error> { fn index(req: &HttpRequest) -> Result<Box<Future<Item=HttpResponse, Error=Error>>, Error> {
if is_error() { if is_error() {
Err(error::ErrorBadRequest("bad request")) Err(error::ErrorBadRequest("bad request"))
} else { } else {
@ -269,7 +270,7 @@ use actix_web::{Either, Error, HttpResponse};
type RegisterResult = Either<HttpResponse, Box<Future<Item=HttpResponse, Error=Error>>>; type RegisterResult = Either<HttpResponse, Box<Future<Item=HttpResponse, Error=Error>>>;
fn index(req: HttpRequest) -> impl Responder { fn index(req: &HttpRequest) -> impl Responder {
if is_a_variant() { // <- choose variant A if is_a_variant() { // <- choose variant A
Either::A( Either::A(
HttpResponse::BadRequest().body("Bad data")) HttpResponse::BadRequest().body("Bad data"))
@ -281,12 +282,3 @@ fn index(req: HttpRequest) -> impl Responder {
} }
} }
``` ```
## Tokio core handle
Any `actix-web` handler runs within a properly configured
[actix system](https://actix.github.io/actix/actix/struct.System.html)
and [arbiter](https://actix.github.io/actix/actix/struct.Arbiter.html).
You can always get access to the tokio handle via the
[Arbiter::handle()](https://actix.github.io/actix/actix/struct.Arbiter.html#method.handle)
method.

View File

@ -40,15 +40,13 @@ impl<S> Middleware<S> for Headers {
/// Method is called when request is ready. It may return /// Method is called when request is ready. It may return
/// future, which should resolve before next middleware get called. /// future, which should resolve before next middleware get called.
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> { fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
req.headers_mut().insert(
header::CONTENT_TYPE, header::HeaderValue::from_static("text/plain"));
Ok(Started::Done) Ok(Started::Done)
} }
/// Method is called when handler returns response, /// Method is called when handler returns response,
/// but before sending http message to peer. /// but before sending http message to peer.
fn response(&self, req: &mut HttpRequest<S>, mut resp: HttpResponse) fn response(&self, req: &HttpRequest<S>, mut resp: HttpResponse)
-> Result<Response> -> Result<Response>
{ {
resp.headers_mut().insert( resp.headers_mut().insert(
@ -190,7 +188,7 @@ session data.
use actix_web::{server, App, HttpRequest, Result}; use actix_web::{server, App, HttpRequest, Result};
use actix_web::middleware::session::{RequestSession, SessionStorage, CookieSessionBackend}; use actix_web::middleware::session::{RequestSession, SessionStorage, CookieSessionBackend};
fn index(mut req: HttpRequest) -> Result<&'static str> { fn index(req: &HttpRequest) -> Result<&'static str> {
// access session data // access session data
if let Some(count) = req.session().get::<i32>("counter")? { if let Some(count) = req.session().get::<i32>("counter")? {
println!("SESSION value: {}", count); println!("SESSION value: {}", count);
@ -230,7 +228,7 @@ use actix_web::{
App, HttpRequest, HttpResponse, Result, App, HttpRequest, HttpResponse, Result,
http, middleware::Response, middleware::ErrorHandlers}; http, middleware::Response, middleware::ErrorHandlers};
fn render_500<S>(_: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> { fn render_500<S>(_: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
let mut builder = resp.into_builder(); let mut builder = resp.into_builder();
builder.header(http::header::CONTENT_TYPE, "application/json"); builder.header(http::header::CONTENT_TYPE, "application/json");
Ok(Response::Done(builder.into())) Ok(Response::Done(builder.into()))

View File

@ -58,7 +58,7 @@ struct MyObj {
number: i32, number: i32,
} }
fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> { fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
req.json().from_err() req.json().from_err()
.and_then(|val: MyObj| { .and_then(|val: MyObj| {
println!("model: {:?}", val); println!("model: {:?}", val);
@ -80,7 +80,7 @@ use futures::{Future, Stream};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct MyObj {name: String, number: i32} struct MyObj {name: String, number: i32}
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> { fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
// `concat2` will asynchronously read each chunk of the request body and // `concat2` will asynchronously read each chunk of the request body and
// return a single, concatenated, chunk // return a single, concatenated, chunk
req.concat2() req.concat2()
@ -120,7 +120,7 @@ The following demonstrates multipart stream handling for a simple form:
```rust ```rust
use actix_web::*; use actix_web::*;
fn index(req: HttpRequest) -> Box<Future<...>> { fn index(req: &HttpRequest) -> Box<Future<...>> {
// get multipart and iterate over multipart items // get multipart and iterate over multipart items
req.multipart() req.multipart()
.and_then(|item| { .and_then(|item| {
@ -171,7 +171,7 @@ struct FormData {
username: String, username: String,
} }
fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> { fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
req.urlencoded::<FormData>() // <- get UrlEncoded future req.urlencoded::<FormData>() // <- get UrlEncoded future
.from_err() .from_err()
.and_then(|data| { // <- deserialized instance .and_then(|data| { // <- deserialized instance
@ -195,8 +195,10 @@ use actix_web::*;
use futures::{Future, Stream}; use futures::{Future, Stream};
fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> { fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
req.from_err() req
.payload()
.from_err()
.fold((), |_, chunk| { .fold((), |_, chunk| {
println!("Chunk: {:?}", chunk); println!("Chunk: {:?}", chunk);
result::<_, error::PayloadError>(Ok(())) result::<_, error::PayloadError>(Ok(()))

View File

@ -20,7 +20,7 @@ builder instance multiple times, the builder will panic.
```rust ```rust
use actix_web::{HttpRequest, HttpResponse, http::ContentEncoding}; use actix_web::{HttpRequest, HttpResponse, http::ContentEncoding};
fn index(req: HttpRequest) -> HttpResponse { fn index(req: &HttpRequest) -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok()
.content_encoding(ContentEncoding::Br) .content_encoding(ContentEncoding::Br)
.content_type("plain/text") .content_type("plain/text")
@ -107,7 +107,7 @@ struct MyObj {
name: String, name: String,
} }
fn index(req: HttpRequest) -> Result<Json<MyObj>> { fn index(req: &HttpRequest) -> Result<Json<MyObj>> {
Ok(Json(MyObj{name: req.match_info().query("name")?})) Ok(Json(MyObj{name: req.match_info().query("name")?}))
} }

View File

@ -13,7 +13,7 @@ match a path tail, we can use a `[.*]` regex.
use std::path::PathBuf; use std::path::PathBuf;
use actix_web::{App, HttpRequest, Result, http::Method, fs::NamedFile}; use actix_web::{App, HttpRequest, Result, http::Method, fs::NamedFile};
fn index(req: HttpRequest) -> Result<NamedFile> { fn index(req: &HttpRequest) -> Result<NamedFile> {
let path: PathBuf = req.match_info().query("tail")?; let path: PathBuf = req.match_info().query("tail")?;
Ok(NamedFile::open(path)?) Ok(NamedFile::open(path)?)
} }

View File

@ -20,7 +20,7 @@ run your handler with `run()` or `run_async()`.
```rust ```rust
use actix_web::{http, test, HttpRequest, HttpResponse, HttpMessage}; use actix_web::{http, test, HttpRequest, HttpResponse, HttpMessage};
fn index(req: HttpRequest) -> HttpResponse { fn index(req: &HttpRequest) -> HttpResponse {
if let Some(hdr) = req.headers().get(http::header::CONTENT_TYPE) { if let Some(hdr) = req.headers().get(http::header::CONTENT_TYPE) {
if let Ok(s) = hdr.to_str() { if let Ok(s) = hdr.to_str() {
return HttpResponse::Ok().into() return HttpResponse::Ok().into()
@ -87,7 +87,7 @@ function the same way as you would for real http server configuration.
```rust ```rust
use actix_web::{http, test, App, HttpRequest, HttpResponse}; use actix_web::{http, test, App, HttpRequest, HttpResponse};
fn index(req: HttpRequest) -> HttpResponse { fn index(req: &HttpRequest) -> HttpResponse {
HttpResponse::Ok().into() HttpResponse::Ok().into()
} }

View File

@ -82,7 +82,7 @@ builder-like pattern. Following configuration methods are available:
Usually handler registration Usually handler registration
is the last config operation. Handler function can be a function or closure is the last config operation. Handler function can be a function or closure
and has the type and has the type
`Fn(HttpRequest<S>) -> R + 'static` `Fn(&HttpRequest<S>) -> R + 'static`
* [*Route::h()*](../../actix-web/actix_web/dev/struct.Route.html#method.h) registers * [*Route::h()*](../../actix-web/actix_web/dev/struct.Route.html#method.h) registers
a handler object that implements the `Handler` trait. This is a handler object that implements the `Handler` trait. This is
similar to `f()` method - only one handler can similar to `f()` method - only one handler can
@ -91,7 +91,7 @@ builder-like pattern. Following configuration methods are available:
an async handler function for this route. Only one handler can be registered. an async handler function for this route. Only one handler can be registered.
Handler registration is the last config operation. Handler function can Handler registration is the last config operation. Handler function can
be a function or closure and has the type be a function or closure and has the type
`Fn(HttpRequest<S>) -> Future<Item = HttpResponse, Error = Error> + 'static` `Fn(&HttpRequest<S>) -> Future<Item = HttpResponse, Error = Error> + 'static`
# Route matching # Route matching

View File

@ -23,5 +23,5 @@ server `actix-web` is powerful enough to provide HTTP 1 and HTTP 2 support as
well as SSL/TLS. This makes it useful for building small services ready for well as SSL/TLS. This makes it useful for building small services ready for
distribution. distribution.
Most importantly: `actix-web` runs on Rust 1.24 or later and it works with Most importantly: `actix-web` runs on Rust 1.26 or later and it works with
stable releases. stable releases.

View File

@ -42,7 +42,7 @@
{{ highlight `extern crate actix_web; {{ highlight `extern crate actix_web;
use actix_web::{server, App, HttpRequest, Responder}; use actix_web::{server, App, HttpRequest, Responder};
fn greet(req: HttpRequest) -> impl Responder { fn greet(req: &HttpRequest) -> impl Responder {
let to = req.match_info().get("name").unwrap_or("World"); let to = req.match_info().get("name").unwrap_or("World");
format!("Hello {}!", to) format!("Hello {}!", to)
} }