无法将 HTTP URL 作为 Rocket 中的查询参数处理

Cannot handle a HTTP URL as a query parameter in Rocket

我正在使用 Rocket 创建一个基本的 Web api 来练习和提高我的 Rust 编程技能。

这里我卡住了。

#[post("/make/<link>")]
fn shorten_link(link: String) -> String {
    // Some other code
}

问题是当我 post 让我们说 http://localhost:8000/make/https://youtube.com/ 我被重定向到 Rocket 404 页面但是当我做类似 http://localhost:8000/make/hello 的事情时一切正常。我不明白我在这里做错了什么,所以任何帮助将不胜感激,谢谢。

问题是 url https://youtube.com/ 中的 / 被误解了。具体来说,它们被解释为路径的新部分。例如,如果我请求 /seg1/seg2/seg3,我不希望用 #[get("/seg1/<arg>")] 注释的处理程序匹配该路径,因为它的末尾有一个额外的段。同样,https://youtube.com/ 中的 / 被解释为新的路径段,因此不会影响您的处理程序。

我想到的第一个解决方案是像这样重写处理程序:

#[post("/make/<link..>")]
fn shorten_link(link: PathBuf) -> String {
    let link = link.to_str().unwrap(); // Don't actually unwrap

    // Other code
}

我认为这行得通,因为它需要一大堆路径段,并将其变成一个字符串,但这没有用,因为 Rocket 抱怨说你不能用 :.

所以我只是尝试了 URL-格式化 https://youtube.com/,它在没有对处理程序进行任何修改的情况下工作。 URL-formatting 是您使用对 HTTP 不安全或具有不同含义的符号(在我们的例子中,/:),并用特殊符号替换它们没问题的代码。例如,https://youtube.com/ 的 URL 编码版本是 https%3A%2F%2Fyoutube.com%2F。最后一个请求是 POST 请求 /make/https%3A%2F%2Fyoutube.com%2F:

client.post(format!(
    "/make/{}",
    urlencoding::encode("https://youtube.com/"),
));

您可以使用 urlencoding crate 为您编码 URLS。

编辑: 我的完整代码如下所示(这只是一个简单的测试):

#![feature(decl_macro)]

use rocket::{local::Client, post, routes};

#[post("/make/<link>")]
fn shorten_link(link: String) -> String {
    link
}

fn main() {
    let rocket = rocket::ignite().mount("/", routes![shorten_link]);
    let client = Client::new(rocket).expect("valid rocket instance");
    let req = client.post(format!(
        "/make/{}",
        urlencoding::encode("https://youtube.com/"),
    ));
    let mut resp = req.dispatch();
    println!("{}", resp.body_string().unwrap());
}