Как мне получить доступ к данным HttpRequest внутри будущего в Actix-web?

Я хотел бы иметь веб-обработчик Actix, который отвечает на запрос POST, выводя тело POST на консоль и создавая HTTP-ответ, содержащий текущий URL-адрес из объекта запроса.

При чтении тела запроса 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| {. Это также не будет компилироваться, потому что req перемещается при вызове req.body(), а затем захватывается после перемещения в ссылках, составляющих url.

Каков разумный способ создания области, в которой у меня есть доступ к данным, прикрепленным к объекту запроса (например, connection_info), одновременно с доступом к телу POST?


person Mala    schedule 07.07.2018    source источник
comment
Просмотрите, как создать минимальный воспроизводимый пример, а затем отредактируйте свой вопрос, чтобы включить его. Мы не можем сказать, какие ящики, типы, черты, поля и т. Д. Присутствуют в коде. В идеале создайте что-нибудь, воспроизводящее вашу ошибку, на Rust Playground. Также есть советы MCVE для Rust.   -  person Shepmaster    schedule 07.07.2018
comment
HttpReqauest реализует типаж Clone   -  person Nikolay Kim    schedule 08.07.2018


Ответы (1)


Самое простое решение - вообще не обращаться к нему в будущем:

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-адресов путем объединения строк - ужасная идея, поскольку оно не позволяет должным образом экранировать значения. Вы должны использовать шрифт, который сделает это за вас.

person Shepmaster    schedule 07.07.2018