如何在Actix-web的Future中访问HttpRequest数据?

时间:2018-07-07 17:07:28

标签: rust future lifetime rust-actix

我想拥有一个Actix Web处理程序,该处理程序通过将POST正文打印到控制台并构造一个包含请求对象当前URL的HTTP响应来响应POST请求。

在读取请求的POST正文时,似乎需要涉及期货。到目前为止,我得到的最接近的是:

fn handler(req: HttpRequest) -> FutureResponse<HttpResponse> {
    req.body()
        .from_err()
        .and_then(|bytes: Bytes| {
            println!("Body: {:?}", bytes);
            let url = format!("{scheme}://{host}",
                scheme = req.connection_info().scheme(),
                host = req.connection_info().host());
            Ok(HttpResponse::Ok().body(url).into())
        }).responder()
}

这不会编译,因为将来的处理程序将失效,因此我尝试读取req.connection_info()是非法的。编译器错误提示我在闭包定义中使用了move关键字,即.and_then(move |bytes: Bytes| {。这也不会编译,因为reqreq.body()调用中被移动,然后在移动后的构造url的引用中被捕获。

构建访问者可以在访问POST正文的同时访问附加到请求对象的数据(例如connection_info)的合理方式是什么?

1 个答案:

答案 0 :(得分:2)

最简单的解决方案是在将来完全不访问它:

extern crate actix_web; // 0.6.14
extern crate bytes;     // 0.4.8
extern crate futures;   // 0.1.21

use actix_web::{AsyncResponder, FutureResponse, HttpMessage, HttpRequest, HttpResponse};
use bytes::Bytes;
use futures::future::Future;

fn handler(req: HttpRequest) -> FutureResponse<HttpResponse> {
    let url = format!(
        "{scheme}://{host}",
        scheme = req.connection_info().scheme(),
        host = req.connection_info().host(),
    );

    req.body()
        .from_err()
        .and_then(move |bytes: Bytes| {
            println!("Body: {:?}", bytes);
            Ok(HttpResponse::Ok().body(url).into())
        })
        .responder()
}

如果这不是出于演示目的的快速技巧,那么通过串联字符串构造URL就是一个糟糕的主意,因为它不能正确地转义值。您应该使用适合您的类型。