Rocket.rs: Optional PathBuf没有匹配的路由
Rocket.rs: Optional PathBuf has no matching routes
我正在创建一个投资组合网站,一些项目有静态 HTML 演示,我想根据 URL 中的 ID 提供这些演示。路线如下所示:
#[get("/demo/<id>/<pathbuf..>")]
fn site_demo(id: usize, pathbuf: Option<PathBuf>) -> Option<NamedFile> {
// set path according to id
let demo = format!{"static/projects/{:03}/demo/", id};
// if `pathbuf` is not provided, set file to `index.html`
let pathbuf = pathbuf.unwrap_or(PathBuf::from("index.html"));
let path = Path::new(&demo).join(pathbuf);
NamedFile::open(path).ok()
}
当我在浏览器中键入 localhost:5050/demo/003/index.html
时,演示(以及演示文件夹中的所有其他内容)将被加载。但是,一旦我只输入 localhost:5050/demo/003/
我就会收到此错误(最后没有 /
的相同结果):
GET /demo/003/ text/html:
=> Error: No matching routes for GET /demo/003/ text/html.
=> Warning: Responding with 404 Not Found catcher.
=> Response succeeded.
我希望路由匹配,因为 PathBuf
是可选的并且设置为 index.html
。对我来说有意义...
我是不是哪里出错了,还是应该开个 issue?
多段路径不能为空。
另一种方法是使用 2 条路线:
- 一个用于多段
/demo/<id>/<pathbuf..>
- 一个用于重定向到
/demo/<id>/index.html
的空段 /demo/<id>
使用 rust nightly 和 rocket 0.4 的示例:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
use std::path::{Path,PathBuf};
use rocket::response::{Redirect,NamedFile};
#[get("/demo/<id>/<pathbuf..>")]
fn site_demo(id: usize, pathbuf: PathBuf) -> Option<NamedFile> {
let demo = format!{"static/projects/{:03}/demo/", id};
NamedFile::open(Path::new(&demo).join(pathbuf)).ok()
}
#[get("/demo/<pathbuf..>", rank=2)]
fn redirect(pathbuf: PathBuf) -> Redirect {
Redirect::to(format!{"/demo/{}/index.html", pathbuf.display()})
}
fn main() {
rocket::ignite().mount("/", routes![site_demo,redirect]).launch();
}
使用 rust stable 和 rocket 0.5 的样本:
#[macro_use] extern crate rocket;
use std::path::{Path,PathBuf};
use rocket::response::{Redirect,NamedFile};
#[get("/demo/<id>/<pathbuf..>")]
async fn site_demo(id: usize, pathbuf: PathBuf) -> Option<NamedFile> {
let demo = format!{"static/projects/{:03}/demo/", id};
NamedFile::open(Path::new(&demo).join(pathbuf)).await.ok()
}
#[get("/demo/<pathbuf..>", rank=2)]
fn redirect(pathbuf: PathBuf) -> Redirect {
Redirect::to(format!{"/demo/{}/index.html", pathbuf.display()})
}
#[launch]
fn rocket() -> rocket::Rocket {
rocket::ignite().mount("/", routes![site_demo,redirect])
}
这样 localhost:5050/demo/003/
将重定向到 localhost:5050/demo/003/index.html
然后 localhost:5050/demo/003/index.html
将加载 static/projects/003/demo/index.html
我正在创建一个投资组合网站,一些项目有静态 HTML 演示,我想根据 URL 中的 ID 提供这些演示。路线如下所示:
#[get("/demo/<id>/<pathbuf..>")]
fn site_demo(id: usize, pathbuf: Option<PathBuf>) -> Option<NamedFile> {
// set path according to id
let demo = format!{"static/projects/{:03}/demo/", id};
// if `pathbuf` is not provided, set file to `index.html`
let pathbuf = pathbuf.unwrap_or(PathBuf::from("index.html"));
let path = Path::new(&demo).join(pathbuf);
NamedFile::open(path).ok()
}
当我在浏览器中键入 localhost:5050/demo/003/index.html
时,演示(以及演示文件夹中的所有其他内容)将被加载。但是,一旦我只输入 localhost:5050/demo/003/
我就会收到此错误(最后没有 /
的相同结果):
GET /demo/003/ text/html:
=> Error: No matching routes for GET /demo/003/ text/html.
=> Warning: Responding with 404 Not Found catcher.
=> Response succeeded.
我希望路由匹配,因为 PathBuf
是可选的并且设置为 index.html
。对我来说有意义...
我是不是哪里出错了,还是应该开个 issue?
多段路径不能为空。
另一种方法是使用 2 条路线:
- 一个用于多段
/demo/<id>/<pathbuf..>
- 一个用于重定向到
/demo/<id>/index.html
的空段
/demo/<id>
使用 rust nightly 和 rocket 0.4 的示例:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
use std::path::{Path,PathBuf};
use rocket::response::{Redirect,NamedFile};
#[get("/demo/<id>/<pathbuf..>")]
fn site_demo(id: usize, pathbuf: PathBuf) -> Option<NamedFile> {
let demo = format!{"static/projects/{:03}/demo/", id};
NamedFile::open(Path::new(&demo).join(pathbuf)).ok()
}
#[get("/demo/<pathbuf..>", rank=2)]
fn redirect(pathbuf: PathBuf) -> Redirect {
Redirect::to(format!{"/demo/{}/index.html", pathbuf.display()})
}
fn main() {
rocket::ignite().mount("/", routes![site_demo,redirect]).launch();
}
使用 rust stable 和 rocket 0.5 的样本:
#[macro_use] extern crate rocket;
use std::path::{Path,PathBuf};
use rocket::response::{Redirect,NamedFile};
#[get("/demo/<id>/<pathbuf..>")]
async fn site_demo(id: usize, pathbuf: PathBuf) -> Option<NamedFile> {
let demo = format!{"static/projects/{:03}/demo/", id};
NamedFile::open(Path::new(&demo).join(pathbuf)).await.ok()
}
#[get("/demo/<pathbuf..>", rank=2)]
fn redirect(pathbuf: PathBuf) -> Redirect {
Redirect::to(format!{"/demo/{}/index.html", pathbuf.display()})
}
#[launch]
fn rocket() -> rocket::Rocket {
rocket::ignite().mount("/", routes![site_demo,redirect])
}
这样 localhost:5050/demo/003/
将重定向到 localhost:5050/demo/003/index.html
然后 localhost:5050/demo/003/index.html
将加载 static/projects/003/demo/index.html