Черта будущего не реализована при использовании Warp's and_then - PullRequest
1 голос
/ 23 февраля 2020

Я пытаюсь добавить применение HTTPS к моему веб-приложению на основе Warp в GKE.

Платформа GKE в основном не имеет значения; громоздкая деталь заключается в том, что балансировщик нагрузки завершает соединения SSL / TLS, поэтому в заголовке X-Forwarded-Proto указана «реальная» схема. Анализируемая Warp буквальная схема всегда будет HTTP.

Лог c выглядит следующим образом:

  1. Если схема HTTPS, обрабатывает запросы обычно.
  2. Если используется схема HTTP, отправьте перенаправление 301 на эквивалентный HTTPS URL.
  3. Если в схеме используется что-то еще, отправьте ошибку 421 (неверный запрос).
  4. Если заголовок X-Forwarded-Proto отсутствует (или возникает какой-либо другой реально невозможный сценарий), отправьте ошибку 400 (неверный запрос).

Ответы об ошибках не содержат содержимого тела в этот пример, и все HTTPS-запросы должны отвечать текстом Hello, world!.

Проблема:

error[E0277]: the trait bound `std::result::Result<(), warp::reject::Rejection>: core::future::future::Future` is not satisfied
  --> src/main.rs:23:10
   |
23 |         .and_then(|scheme_header: Option<String>, host: String, path: FullPath| {
   |          ^^^^^^^^ the trait `core::future::future::Future` is not implemented for `std::result::Result<(), warp::reject::Rejection>`
   |
   = note: required because of the requirements on the impl of `futures_core::future::TryFuture` for `std::result::Result<(), warp::reject::Rejection>`

error[E0599]: no method named `and` found for type `warp::filter::and_then::AndThen<warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, impl warp::filter::Filter+std::marker::Copy>, impl warp::filter::Filter+std::marker::Copy>, [closure@src/main.rs:23:19: 43:10]>` in the current scope
  --> src/main.rs:44:10
   |
44 |         .and(filter)
   |          ^^^ method not found in `warp::filter::and_then::AndThen<warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, impl warp::filter::Filter+std::marker::Copy>, impl warp::filter::Filter+std::marker::Copy>, [closure@src/main.rs:23:19: 43:10]>`
   |
   = note: the method `and` exists but the following trait bounds were not satisfied:
           `&mut warp::filter::and_then::AndThen<warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, impl warp::filter::Filter+std::marker::Copy>, impl warp::filter::Filter+std::marker::Copy>, [closure@src/main.rs:23:19: 43:10]> : warp::filter::Filter`
           `&warp::filter::and_then::AndThen<warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, impl warp::filter::Filter+std::marker::Copy>, impl warp::filter::Filter+std::marker::Copy>, [closure@src/main.rs:23:19: 43:10]> : warp::filter::Filter`
           `warp::filter::and_then::AndThen<warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, impl warp::filter::Filter+std::marker::Copy>, impl warp::filter::Filter+std::marker::Copy>, [closure@src/main.rs:23:19: 43:10]> : warp::filter::Filter`

Очевидно, я упускаю что-то очевидное здесь, поэтому я надеюсь, что кто-то может подтолкни меня в правильном направлении!

use futures::{FutureExt, StreamExt};
use warp::{Filter, Rejection};
use warp::filters::path::{FullPath};
use warp::http::{StatusCode, Uri};
use warp::http::uri::{Parts, Scheme};
use warp::reply::Reply;

enum SchemeError {
    InsecureScheme(Uri),
    UnknownScheme,
    MissingScheme,
}

impl warp::reject::Reject for SchemeError {}

async fn requires_https(filter: impl Filter<Extract = (Scheme,), Error = Rejection> + Copy) -> impl Filter<Extract = (), Error = Rejection> + Copy {
    warp::header::optional("X-Forwarded-Proto")
        .and(warp::header("Host"))
        .and(warp::path::full())
        .and_then(|scheme_header: Option<String>, host: String, path: FullPath| {
            if let Some(scheme) = scheme_header {
                match scheme.to_ascii_lowercase().as_str() {
                    "https" => Ok(()),
                    "http" => {
                        let mut uri_parts = Parts::default();
                        uri_parts.scheme = Some(Scheme::HTTPS);
                        uri_parts.authority = Some(host.parse().unwrap());
                        uri_parts.path_and_query = Some(path.as_str().parse().unwrap());
                        let uri_parts = uri_parts;

                        let new_uri = Uri::from_parts(uri_parts).unwrap();
                        println!("Redirecting to secure URL: {}", new_uri);
                        Err(warp::reject::custom(SchemeError::InsecureScheme(new_uri)))
                    },
                    _ => Err(warp::reject::custom(SchemeError::UnknownScheme)),
                }
            } else {
                Err(warp::reject::custom(SchemeError::MissingScheme))
            }
        })
        .and(filter)
        .recover(|err: Rejection| {
            if let Some(scheme_error) = err.find::<SchemeError>() {
                match scheme_error {
                    SchemeError::InsecureScheme(new_uri) => Ok(warp::redirect(new_uri)),
                    SchemeError::UnknownScheme => Ok(StatusCode::MISDIRECTED_REQUEST),
                    SchemeError::MissingScheme => Ok(StatusCode::BAD_REQUEST),
                }
            } else {
                Err(err)
            }
        })
}

#[tokio::main]
async fn main() {
    let routes = requires_https(warp::any().map(|| "Hello, world!"));

    warp::serve(routes)
        .run(([0, 0, 0, 0], 8080))
        .await;
}

1 Ответ

0 голосов
/ 30 марта 2020

Я ржавый новичок ie, но столкнулся с похожей ошибкой компилятора

Моя проблема была при просмотре документа warp 0.1, хотя при использовании warp 0.2 https://docs.rs/warp/0.2.0/warp/trait.Filter.html#example -3

Мне нужно было поставить async move после труб закрытия в and_then

Если это не так, может быть похоже на Ошибка понимания: trait `futures :: future :: Future` is not реализовано для `()`

, где std::result::Result<(), warp::reject::Rejection> указывает, что вы возвращаете тип объекта в виде левого результата, который может не реализоваться в будущем.

...