这是indexloc提供的服务,不要输入任何密码
Skip to content

feat: update axum to v0.8.1 #595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/tuono/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ mod tests {
("/about", "/about"),
("/posts/index", "/posts"),
("/posts/any-post", "/posts/any-post"),
("/posts/[post]", "/posts/:post"),
("/posts/[post]", "/posts/{post}"),
];

results.into_iter().for_each(|(path, expected_path)| {
Expand Down
21 changes: 16 additions & 5 deletions crates/tuono/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ impl AxumInfo {
}

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: &regex::Captures| {
format!("{{{}}}", &caps[1])
});

let axum_route = catch_all_re
.replace_all(&dyn_result, |caps: &regex::Captures| {
format!("{{*{}}}", &caps[1])
})
.to_string();

return AxumInfo {
module_import: module
.as_str()
Expand All @@ -55,10 +69,7 @@ impl AxumInfo {
.replace('[', "dyn_")
.replace("...", "catch_all_")
.replace(']', ""),
axum_route: axum_route
.replace("[...", "*")
.replace('[', ":")
.replace(']', ""),
axum_route,
};
}

Expand Down Expand Up @@ -296,7 +307,7 @@ mod tests {

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");
}

Expand Down
8 changes: 4 additions & 4 deletions crates/tuono/tests/cli_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
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(
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(
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(
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))"#
));
}

Expand Down
8 changes: 4 additions & 4 deletions crates/tuono_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ include = [

[dependencies]
ssr_rs = "0.8.1"
axum = {version = "0.7.5", features = ["json", "ws"]}
axum-extra = {version = "0.9.6", features = ["cookie"]}
axum = {version = "0.8.1", features = ["json", "ws"]}
axum-extra = {version = "0.10.0", features = ["cookie"]}
tokio = { version = "1.37.0", features = ["full"] }
serde = { version = "1.0.202", features = ["derive"] }
erased-serde = "0.4.5"
Expand All @@ -35,9 +35,9 @@ colored = "2.1.0"
tuono_lib_macros = {path = "../tuono_lib_macros", version = "0.17.8"}
tuono_internal = {path = "../tuono_internal", version = "0.17.8"}
# 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"] }
tungstenite = "0.24.0"
tungstenite = "0.26.0"
http = "1.1.0"
pin-project = "1.1.7"
tower = "0.5.1"
Expand Down
2 changes: 1 addition & 1 deletion crates/tuono_lib/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Server {
.to_owned()
.layer(LoggerLayer::new())
.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(
ServeDir::new(DEV_PUBLIC_DIR)
.fallback(get(catch_all).layer(LoggerLayer::new())),
Expand Down
8 changes: 4 additions & 4 deletions crates/tuono_lib/src/vite_websocket_proxy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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 futures_util::{SinkExt, StreamExt};
use tokio_tungstenite::connect_async;
Expand Down Expand Up @@ -64,7 +64,7 @@ async fn handle_socket(mut tuono_socket: WebSocket) {
while let Some(msg) = tuono_receiver.next().await {
if let Ok(msg) = msg {
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::Ping(payload) => Message::Ping(payload),
ws::Message::Binary(payload) => Message::Binary(payload),
Expand All @@ -91,7 +91,7 @@ async fn handle_socket(mut tuono_socket: WebSocket) {
tokio::spawn(async move {
while let Some(Ok(msg)) = vite_receiver.next().await {
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::Pong(payload) => ws::Message::Pong(payload),
Message::Binary(payload) => ws::Message::Binary(payload),
Expand All @@ -100,7 +100,7 @@ async fn handle_socket(mut tuono_socket: WebSocket) {
Message::Close(_) => ws::Message::Close(None),
_ => {
eprintln!("Unexpected message from the vite WebSocket to the browser: {msg:?}");
ws::Message::Text("Unhandled".to_string())
ws::Message::Text("Unhandled".to_string().into())
}
};

Expand Down
44 changes: 44 additions & 0 deletions crates/tuono_lib/tests/server_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,47 @@ async fn api_route_route() {
"{\"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");
}
11 changes: 11 additions & 0 deletions crates/tuono_lib/tests/utils/catch_all.rs
Original file line number Diff line number Diff line change
@@ -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()
}
11 changes: 11 additions & 0 deletions crates/tuono_lib/tests/utils/dynamic_parameter.rs
Original file line number Diff line number Diff line change
@@ -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()
}
6 changes: 5 additions & 1 deletion crates/tuono_lib/tests/utils/mock_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use tempfile::{tempdir, TempDir};
use tuono_lib::axum::routing::get;
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::route as html_route;
use crate::utils::route::tuono_internal_api as route_api;
Expand Down Expand Up @@ -76,7 +78,9 @@ impl MockTuonoServer {
.route("/", get(html_route::tuono_internal_route))
.route("/tuono/data", get(html_route::tuono_internal_api))
.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;

Expand Down
2 changes: 2 additions & 0 deletions crates/tuono_lib/tests/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod catch_all;
pub mod dynamic_parameter;
pub mod health_check;
pub mod mock_server;
pub mod route;
Loading