0

我正在用 warp 和 rust 进行一些代码培训,我想做如下的事情:

let route = warp::path("my")
    .and(warp::path::param())
    .map(|filename: String| {
        match fs::read_to_string(filename) {
            Ok(value) => {
                warp::http::Response::builder()
                    .header("content-type", "text/html; charset=utf-8")
                    .body(value)
            },
            Err(_) => warp::redirect::see_other(Uri::from_static("/404"))
        }
    });

let to_404 = warp::path("404").map(|| "File not found!");

warp::serve(warp::get().and(to_404.or(route))).run(([127, 0, 0, 1], 3030)).await

这段代码的问题在于,由于同一路径中有两种不同的返回类型,代码无法编译。有没有合适的方法来完成我想要的行为?提前致谢!

TL; DR:我想实现一个路径,该路径/my/:file显示 HTML 文件的内容(如果存在)或重定向到/404以防出现错误。

编辑:添加Uri::from_static了一些小错别字,以便在编译时得到正确的错误。

error[E0308]: `match` arms have incompatible types
  --> src/main.rs:23:23
   |
17 |           match fs::read_to_string(filename) {
   |           ---------------------------------- `match` arms have incompatible types
18 |               Ok(value) => {
19 | /                 warp::http::Response::builder()
20 | |                     .header("content-type", "text/html; charset=utf-8")
21 | |                     .body(value)
   | |________________________________- this is found to be of type `Result<Response<String>, warp::http::Error>`
22 |               },
23 |               Err(_) => warp::redirect::see_other(Uri::from_static("/404"))
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found opaque type
4

1 回答 1

0

我不确定这是否是正确的方法,但这就是我解决它的方法(我不喜欢它,TBH)。

我创建了两个构建 Response 对象的函数 ( a_response& a_redirect):

use warp::{Filter, http::Response};

fn a_response(status: u16, content_type: &str, body: &str) -> Result<Response<String>, warp::http::Error> {
    warp::http::Response::builder()
        .header("content-type", content_type.to_string())
        .status(status)
        .body(body.to_string())
}

fn a_redirect(status: u16, location: &str) -> Result<Response<String>, warp::http::Error> {
    let final_status : u16;

    match status {
        301 | 302 | 303 | 307 | 308 => final_status = status,
        _ => final_status = 302
    }

    warp::http::Response::builder()
        .header("Location", location)
        .status(final_status)
        .body("".to_string())
}

然后我只在需要时使用它:

let root = warp::path::end().map(|| {
        match fs::read_to_string("index.html") {
            Ok(body) => {
                a_response(200, "text/html; charset=utf-8", &body)
            },
            Err(_) => {
                a_redirect(303, "/500")
            }
        }
    });

就像我说的,我不喜欢它,但它确实有效。

于 2022-01-08T19:32:49.337 回答