mirror of
https://github.com/tuono-labs/tuono
synced 2026-07-25 12:52:47 -07:00
feat: update axum to v0.8.1 (#595)
This commit is contained in:
@@ -362,7 +362,7 @@ mod tests {
|
|||||||
("/about", "/about"),
|
("/about", "/about"),
|
||||||
("/posts/index", "/posts"),
|
("/posts/index", "/posts"),
|
||||||
("/posts/any-post", "/posts/any-post"),
|
("/posts/any-post", "/posts/any-post"),
|
||||||
("/posts/[post]", "/posts/:post"),
|
("/posts/[post]", "/posts/{post}"),
|
||||||
];
|
];
|
||||||
|
|
||||||
results.into_iter().for_each(|(path, expected_path)| {
|
results.into_iter().for_each(|(path, expected_path)| {
|
||||||
|
|||||||
@@ -46,6 +46,20 @@ impl AxumInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if route.is_dynamic {
|
if route.is_dynamic {
|
||||||
|
let dyn_re = Regex::new(r"\[(.*?)\]").expect("Failed to create dyn regex");
|
||||||
|
let catch_all_re =
|
||||||
|
Regex::new(r"\{\.\.\.(.*?)\}").expect("Failed to create catch all regex");
|
||||||
|
|
||||||
|
let dyn_result = dyn_re.replace_all(&axum_route, |caps: ®ex::Captures| {
|
||||||
|
format!("{{{}}}", &caps[1])
|
||||||
|
});
|
||||||
|
|
||||||
|
let axum_route = catch_all_re
|
||||||
|
.replace_all(&dyn_result, |caps: ®ex::Captures| {
|
||||||
|
format!("{{*{}}}", &caps[1])
|
||||||
|
})
|
||||||
|
.to_string();
|
||||||
|
|
||||||
return AxumInfo {
|
return AxumInfo {
|
||||||
module_import: module
|
module_import: module
|
||||||
.as_str()
|
.as_str()
|
||||||
@@ -55,10 +69,7 @@ impl AxumInfo {
|
|||||||
.replace('[', "dyn_")
|
.replace('[', "dyn_")
|
||||||
.replace("...", "catch_all_")
|
.replace("...", "catch_all_")
|
||||||
.replace(']', ""),
|
.replace(']', ""),
|
||||||
axum_route: axum_route
|
axum_route,
|
||||||
.replace("[...", "*")
|
|
||||||
.replace('[', ":")
|
|
||||||
.replace(']', ""),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +307,7 @@ mod tests {
|
|||||||
|
|
||||||
let dyn_info = AxumInfo::new(&Route::new("/[posts]".to_string()));
|
let dyn_info = AxumInfo::new(&Route::new("/[posts]".to_string()));
|
||||||
|
|
||||||
assert_eq!(dyn_info.axum_route, "/:posts");
|
assert_eq!(dyn_info.axum_route, "/{posts}");
|
||||||
assert_eq!(dyn_info.module_import, "dyn_posts");
|
assert_eq!(dyn_info.module_import, "dyn_posts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,19 +127,19 @@ fn it_successfully_create_catch_all_routes() {
|
|||||||
assert!(temp_main_rs_content.contains("mod dyn_catch_all_all_routes;"));
|
assert!(temp_main_rs_content.contains("mod dyn_catch_all_all_routes;"));
|
||||||
|
|
||||||
assert!(temp_main_rs_content.contains(
|
assert!(temp_main_rs_content.contains(
|
||||||
r#".route("/api/*all_apis", post(api_dyn_catch_all_all_apis::post_tuono_internal_api))"#
|
r#".route("/api/{*all_apis}", post(api_dyn_catch_all_all_apis::post_tuono_internal_api))"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(temp_main_rs_content.contains(
|
assert!(temp_main_rs_content.contains(
|
||||||
r#".route("/*all_routes", get(dyn_catch_all_all_routes::tuono_internal_route))"#
|
r#".route("/{*all_routes}", get(dyn_catch_all_all_routes::tuono_internal_route))"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(temp_main_rs_content.contains(
|
assert!(temp_main_rs_content.contains(
|
||||||
r#".route("/*all_routes", get(dyn_catch_all_all_routes::tuono_internal_route))"#
|
r#".route("/{*all_routes}", get(dyn_catch_all_all_routes::tuono_internal_route))"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(temp_main_rs_content.contains(
|
assert!(temp_main_rs_content.contains(
|
||||||
r#".route("/__tuono/data/*all_routes", get(dyn_catch_all_all_routes::tuono_internal_api))"#
|
r#".route("/__tuono/data/{*all_routes}", get(dyn_catch_all_all_routes::tuono_internal_api))"#
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ include = [
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ssr_rs = "0.8.1"
|
ssr_rs = "0.8.1"
|
||||||
axum = {version = "0.7.5", features = ["json", "ws"]}
|
axum = {version = "0.8.1", features = ["json", "ws"]}
|
||||||
axum-extra = {version = "0.9.6", features = ["cookie"]}
|
axum-extra = {version = "0.10.0", features = ["cookie"]}
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
serde = { version = "1.0.202", features = ["derive"] }
|
serde = { version = "1.0.202", features = ["derive"] }
|
||||||
erased-serde = "0.4.5"
|
erased-serde = "0.4.5"
|
||||||
@@ -35,9 +35,9 @@ colored = "2.1.0"
|
|||||||
tuono_lib_macros = {path = "../tuono_lib_macros", version = "0.17.8"}
|
tuono_lib_macros = {path = "../tuono_lib_macros", version = "0.17.8"}
|
||||||
tuono_internal = {path = "../tuono_internal", version = "0.17.8"}
|
tuono_internal = {path = "../tuono_internal", version = "0.17.8"}
|
||||||
# Match the same version used by axum
|
# Match the same version used by axum
|
||||||
tokio-tungstenite = "0.24.0"
|
tokio-tungstenite = "0.26.0"
|
||||||
futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] }
|
futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] }
|
||||||
tungstenite = "0.24.0"
|
tungstenite = "0.26.0"
|
||||||
http = "1.1.0"
|
http = "1.1.0"
|
||||||
pin-project = "1.1.7"
|
pin-project = "1.1.7"
|
||||||
tower = "0.5.1"
|
tower = "0.5.1"
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ impl Server {
|
|||||||
.to_owned()
|
.to_owned()
|
||||||
.layer(LoggerLayer::new())
|
.layer(LoggerLayer::new())
|
||||||
.route("/vite-server/", get(vite_websocket_proxy))
|
.route("/vite-server/", get(vite_websocket_proxy))
|
||||||
.route("/vite-server/*path", get(vite_reverse_proxy))
|
.route("/vite-server/{*path}", get(vite_reverse_proxy))
|
||||||
.fallback_service(
|
.fallback_service(
|
||||||
ServeDir::new(DEV_PUBLIC_DIR)
|
ServeDir::new(DEV_PUBLIC_DIR)
|
||||||
.fallback(get(catch_all).layer(LoggerLayer::new())),
|
.fallback(get(catch_all).layer(LoggerLayer::new())),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::config::GLOBAL_CONFIG;
|
use crate::config::GLOBAL_CONFIG;
|
||||||
use axum::extract::ws::{self, WebSocket, WebSocketUpgrade};
|
use axum::extract::ws::{self, Utf8Bytes as AxumUtf8Bytes, WebSocket, WebSocketUpgrade};
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
use futures_util::{SinkExt, StreamExt};
|
use futures_util::{SinkExt, StreamExt};
|
||||||
use tokio_tungstenite::connect_async;
|
use tokio_tungstenite::connect_async;
|
||||||
@@ -64,7 +64,7 @@ async fn handle_socket(mut tuono_socket: WebSocket) {
|
|||||||
while let Some(msg) = tuono_receiver.next().await {
|
while let Some(msg) = tuono_receiver.next().await {
|
||||||
if let Ok(msg) = msg {
|
if let Ok(msg) = msg {
|
||||||
let msg_to_vite = match msg.clone() {
|
let msg_to_vite = match msg.clone() {
|
||||||
ws::Message::Text(str) => Message::Text(str),
|
ws::Message::Text(str) => Message::Text(str.to_string().into()),
|
||||||
ws::Message::Pong(payload) => Message::Pong(payload),
|
ws::Message::Pong(payload) => Message::Pong(payload),
|
||||||
ws::Message::Ping(payload) => Message::Ping(payload),
|
ws::Message::Ping(payload) => Message::Ping(payload),
|
||||||
ws::Message::Binary(payload) => Message::Binary(payload),
|
ws::Message::Binary(payload) => Message::Binary(payload),
|
||||||
@@ -91,7 +91,7 @@ async fn handle_socket(mut tuono_socket: WebSocket) {
|
|||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
while let Some(Ok(msg)) = vite_receiver.next().await {
|
while let Some(Ok(msg)) = vite_receiver.next().await {
|
||||||
let msg_to_browser = match msg {
|
let msg_to_browser = match msg {
|
||||||
Message::Text(str) => ws::Message::Text(str),
|
Message::Text(str) => ws::Message::Text(AxumUtf8Bytes::from(str.to_string())),
|
||||||
Message::Ping(payload) => ws::Message::Ping(payload),
|
Message::Ping(payload) => ws::Message::Ping(payload),
|
||||||
Message::Pong(payload) => ws::Message::Pong(payload),
|
Message::Pong(payload) => ws::Message::Pong(payload),
|
||||||
Message::Binary(payload) => ws::Message::Binary(payload),
|
Message::Binary(payload) => ws::Message::Binary(payload),
|
||||||
@@ -100,7 +100,7 @@ async fn handle_socket(mut tuono_socket: WebSocket) {
|
|||||||
Message::Close(_) => ws::Message::Close(None),
|
Message::Close(_) => ws::Message::Close(None),
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("Unexpected message from the vite WebSocket to the browser: {msg:?}");
|
eprintln!("Unexpected message from the vite WebSocket to the browser: {msg:?}");
|
||||||
ws::Message::Text("Unhandled".to_string())
|
ws::Message::Text("Unhandled".to_string().into())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -103,3 +103,47 @@ async fn api_route_route() {
|
|||||||
"{\"data\":\"{}\",\"info\":{\"redirect_destination\":null}}"
|
"{\"data\":\"{}\",\"info\":{\"redirect_destination\":null}}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
#[serial]
|
||||||
|
async fn it_reads_the_catch_all_path_parameter() {
|
||||||
|
let app = MockTuonoServer::spawn().await;
|
||||||
|
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.redirect(reqwest::redirect::Policy::none())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let server_url = format!("http://{}:{}", &app.address, &app.port);
|
||||||
|
|
||||||
|
let response = client
|
||||||
|
.get(format!("{server_url}/catch_all/url_parameter"))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.expect("Failed to execute request.");
|
||||||
|
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
assert_eq!(response.text().await.unwrap(), "url_parameter");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
#[serial]
|
||||||
|
async fn it_reads_the_path_parameter() {
|
||||||
|
let app = MockTuonoServer::spawn().await;
|
||||||
|
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.redirect(reqwest::redirect::Policy::none())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let server_url = format!("http://{}:{}", &app.address, &app.port);
|
||||||
|
|
||||||
|
let response = client
|
||||||
|
.get(format!("{server_url}/dynamic/url_parameter"))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.expect("Failed to execute request.");
|
||||||
|
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
assert_eq!(response.text().await.unwrap(), "url_parameter");
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
use tuono_lib::Request;
|
||||||
|
|
||||||
|
#[tuono_lib::api(GET)]
|
||||||
|
async fn read_catch_all_parameter(req: Request) -> String {
|
||||||
|
let param = req
|
||||||
|
.params
|
||||||
|
.get("catch_all")
|
||||||
|
.expect("Failed to get the catch_all param");
|
||||||
|
|
||||||
|
param.to_string()
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
use tuono_lib::Request;
|
||||||
|
|
||||||
|
#[tuono_lib::api(GET)]
|
||||||
|
async fn read_dynamic_parameter(req: Request) -> String {
|
||||||
|
let param = req
|
||||||
|
.params
|
||||||
|
.get("parameter")
|
||||||
|
.expect("Failed to get the catch_all param");
|
||||||
|
|
||||||
|
param.to_string()
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ use tempfile::{tempdir, TempDir};
|
|||||||
use tuono_lib::axum::routing::get;
|
use tuono_lib::axum::routing::get;
|
||||||
use tuono_lib::{axum::Router, tuono_internal_init_v8_platform, Mode, Server};
|
use tuono_lib::{axum::Router, tuono_internal_init_v8_platform, Mode, Server};
|
||||||
|
|
||||||
|
use crate::utils::catch_all::get_tuono_internal_api as catch_all;
|
||||||
|
use crate::utils::dynamic_parameter::get_tuono_internal_api as dynamic_parameter;
|
||||||
use crate::utils::health_check::get_tuono_internal_api as health_check;
|
use crate::utils::health_check::get_tuono_internal_api as health_check;
|
||||||
use crate::utils::route as html_route;
|
use crate::utils::route as html_route;
|
||||||
use crate::utils::route::tuono_internal_api as route_api;
|
use crate::utils::route::tuono_internal_api as route_api;
|
||||||
@@ -76,7 +78,9 @@ impl MockTuonoServer {
|
|||||||
.route("/", get(html_route::tuono_internal_route))
|
.route("/", get(html_route::tuono_internal_route))
|
||||||
.route("/tuono/data", get(html_route::tuono_internal_api))
|
.route("/tuono/data", get(html_route::tuono_internal_api))
|
||||||
.route("/health_check", get(health_check))
|
.route("/health_check", get(health_check))
|
||||||
.route("/route-api", get(route_api));
|
.route("/route-api", get(route_api))
|
||||||
|
.route("/catch_all/{*catch_all}", get(catch_all))
|
||||||
|
.route("/dynamic/{parameter}", get(dynamic_parameter));
|
||||||
|
|
||||||
let server = Server::init(router, Mode::Prod).await;
|
let server = Server::init(router, Mode::Prod).await;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
pub mod catch_all;
|
||||||
|
pub mod dynamic_parameter;
|
||||||
pub mod health_check;
|
pub mod health_check;
|
||||||
pub mod mock_server;
|
pub mod mock_server;
|
||||||
pub mod route;
|
pub mod route;
|
||||||
|
|||||||
Reference in New Issue
Block a user