我很难理解如何使用rust-embed和axum嵌入SPA (单页应用程序)文件。
在没有rust-embed的情况下,使用axum (从这里开始)的一行代码是没有问题的:
app.fallback(get_service(ServeDir::new("./app/static")).handle_error(error_handler))它可以工作,因为所有文件都正确下载。但是:
第一个问题
如果用户在SPA嵌套路由上重新加载页面,那么正确的SPA处理所缺少的是index.html上的重定向。
示例:我在页面上:/home/customers,它不是一个文件,也不是一个dir,而是一个假的javascript路径,如果我重新加载这个页面,axum就会给我404 (找不到)。
第二个问题
我需要将这些文件嵌入到我的最终可执行文件中。在Golang中,这是使用embed:指令的“本机”。
我在Rust中看到了这一点,这在rust-embed中做得很好,但我无法完成我的SPA任务。
需要的是,用户键入的每一条路径(这不是一个存在的文件,比如.js或.css显然必须由浏览器下载)就会导致static dir根目录中的"index.html“文件。
如果我使用axum代码示例,我可以看到路线:
.route("/dist/*file", static_handler.into_service())其中有/dist/*file,而我不需要这个/dist,因为index.html调用了许多具有自定义路径的文件,例如/_works、menu、images。
如果删除dist部件,则会得到以下错误:
thread 'main' panicked at 'Invalid route: insertion failed due to conflict with previously registered route: /index.html'你能帮我理解如何正确地完成这项任务吗?
谢谢。
发布于 2022-10-28 02:26:57
我也有过类似的问题,用Vue和Axum/Rust建造房子。下面是我解决第一个问题的方法
tower_http机箱axum::routing::get_service为构建SPA服务。//example implementation
...
//static file mounting
let assets_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("views");
let static_files_service = get_service(
ServeDir::new(assets_dir).append_index_html_on_directories(true),
)
.handle_error(|error: std::io::Error| async move {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Unhandled internal error: {}", error),
)
});
... //mount the app routes and middleware
let app = Router::new()
.fallback(static_files_service)
.nest("/api/v1/", routes::root::router())
.layer(cors)
.layer(TraceLayer::new_for_http())
.layer(Extension(database));查看完整的源代码这里。另一件事是,正如我发现的这里一样,Axum在后续版本中似乎发生了急剧变化,因此您可能需要检查与您正在使用的Axum版本相对应的doc/示例:)
https://stackoverflow.com/questions/73464479
复制相似问题