request handler(请求处理程序)是一个async function(异步函数),它接受零个或多个可以从请求中提取的参数(即impl FromRequest),并返回可以转换为HttpResponse的类型(即impl Responder)。
请求处理分为两个阶段。
首先,调用handler对象,返回实现Responder特性的任何对象。
然后,在返回的对象上调用respond_to()
,将其自身转换为HttpResponse
或Error
。
默认情况下,actix-web
为某些标准类型(例如&'static str
, String
等)提供Responder
实现。
有关implementations的完整列表,请查看Responder 文档。
有效处理程序的示例:
async fn index(_req: HttpRequest) -> &'static str {
"Hello world!"
}
async fn index(_req: HttpRequest) -> String {
"Hello world!".to_owned()
}
您还可以将签名更改为return impl Responder
,如果涉及到更复杂的类型,它可以很好地工作。
async fn index(_req: HttpRequest) -> impl Responder {
Bytes::from_static(b"Hello world!")
}
async fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
...
}
要直接从handler函数返回自定义类型,该类型需要实现Responder
特性。
让我们为自定义类型创建一个response(响应),该response序列化为application/json
response:
use actix_web::{Error, HttpRequest, HttpResponse, Responder};
use serde::Serialize;
use futures::future::{ready, Ready};
#[derive(Serialize)]
struct MyObj {
name: &'static str,
}
// Responder
impl Responder for MyObj {
type Error = Error;
type Future = Ready<Result<HttpResponse, Error>>;
fn respond_to(self, _req: &HttpRequest) -> Self::Future {
let body = serde_json::to_string(&self).unwrap();
// Create response and set content type
ready(Ok(HttpResponse::Ok()
.content_type("application/json")
.body(body)))
}
}
async fn index() -> impl Responder {
MyObj { name: "user" }
}
Response body(响应体)可以异步生成。
在这种情况下,body必须实现stream特征Stream<Item=Bytes, Error=Error>
,即:
use actix_web::{web, App, HttpServer, Error, HttpResponse};
use bytes::Bytes;
use futures::stream::once;
use futures::future::ok;
async fn index() -> HttpResponse {
let body = once(ok::<_, Error>(Bytes::from_static(b"test")));
HttpResponse::Ok()
.content_type("application/json")
.streaming(body)
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().route("/async", web::to(index)))
.bind("127.0.0.1:8088")?
.run()
.await
}
有时,您需要返回不同类型的responses。 例如,您可以进行错误检查并返回错误,返回异步responses或需要两种不同类型的任何结果。
在这种情况下,可以使用Either类型。 可以将两种不同的responder(响应者)类型组合为一个类型。
use actix_web::{Either, Error, HttpResponse};
type RegisterResult = Either<HttpResponse, Result<&'static str, Error>>;
fn index() -> RegisterResult {
if is_a_variant() {
// <- choose variant A
Either::A(HttpResponse::BadRequest().body("Bad data"))
} else {
// <- variant B
Either::B(Ok("Hello!"))
}
}