Skip to content
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
20 changes: 10 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ categories = ["network-programming", "web-programming"]
exclude.workspace = true

[workspace.package]
version = "21.11.0"
version = "21.12.0"
readme = "README.md"
edition = "2024"
authors = ["root@ltpp.vip"]
Expand All @@ -25,15 +25,15 @@ resolver = "2"
members = ["compress", "constant", "type", "request", "core", "macros", "cli", "plugin/websocket"]

[workspace.dependencies]
hyperlane = { path = ".", version = "21.11.0" }
http-type = { path = "type", version = "21.11.0" }
hyperlane-cli = { path = "cli", version = "21.11.0" }
hyperlane-core = { path = "core", version = "21.11.0" }
http-request = { path = "request", version = "21.11.0" }
http-compress = { path = "compress", version = "21.11.0" }
http-constant = { path = "constant", version = "21.11.0" }
hyperlane-macros = { path = "macros", version = "21.11.0" }
hyperlane-plugin-websocket = { path = "plugin/websocket", version = "21.11.0" }
hyperlane = { path = ".", version = "21.12.0" }
http-type = { path = "type", version = "21.12.0" }
hyperlane-cli = { path = "cli", version = "21.12.0" }
hyperlane-core = { path = "core", version = "21.12.0" }
http-request = { path = "request", version = "21.12.0" }
http-compress = { path = "compress", version = "21.12.0" }
http-constant = { path = "constant", version = "21.12.0" }
hyperlane-macros = { path = "macros", version = "21.12.0" }
hyperlane-plugin-websocket = { path = "plugin/websocket", version = "21.12.0" }

hex = "0.4.3"
md5 = "0.8.1"
Expand Down
5 changes: 2 additions & 3 deletions core/src/server/impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,16 +406,15 @@ impl Server {
///
/// # Arguments
///
/// - `P` - The route path pattern.
/// - `impl AsRef<str>` - The route path pattern.
///
/// # Returns
///
/// - `&mut Self` - Reference to self for method chaining.
#[inline(always)]
pub fn route<S, P>(&mut self, path: P) -> &mut Self
pub fn route<S>(&mut self, path: impl AsRef<str>) -> &mut Self
where
S: ServerHook,
P: AsRef<str>,
{
self.get_mut_route_matcher()
.add(path.as_ref(), Hook::factory::<S>())
Expand Down
57 changes: 36 additions & 21 deletions core/tests/route/fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,39 @@ use super::*;
#[tokio::test]
#[should_panic(expected = "EmptyPattern")]
async fn empty_route() {
let _server: &Server = Server::default().route::<TestRoute, &str>(EMPTY_STR);
let _server: &Server = Server::default().route::<TestRoute>(EMPTY_STR);
}

#[tokio::test]
#[should_panic(expected = "DuplicatePattern")]
async fn duplicate_route() {
let _server: &Server = Server::default()
.route::<TestRoute, &str>(ROOT_PATH)
.route::<TestRoute, &str>(ROOT_PATH);
.route::<TestRoute>(ROOT_PATH)
.route::<TestRoute>(ROOT_PATH);
}

#[test]
fn route_path_type_inference() {
let mut server: Server = Server::default();
server.route::<TestRoute>("/infer/str");
let owned_path: String = "/infer/string".to_string();
server.route::<TestRoute>(owned_path);
let ref_path: String = "/infer/ref".to_string();
server.route::<TestRoute>(&ref_path);
server
.route::<TestRoute>("/infer/chain/a")
.route::<TestRoute>("/infer/chain/b");
let route_matcher: RouteMatcher = server.get_route_matcher().clone();
assert_eq!(route_matcher.get_static_route().len(), 5);
}

#[test]
fn get_route() {
let mut server: Server = Server::default();
server
.route::<TestRoute, &str>(ROOT_PATH)
.route::<TestRoute, &str>("/dynamic/{routing}")
.route::<TestRoute, &str>("/regex/{file:^.*$}");
.route::<TestRoute>(ROOT_PATH)
.route::<TestRoute>("/dynamic/{routing}")
.route::<TestRoute>("/regex/{file:^.*$}");
let route_matcher: RouteMatcher = server.get_route_matcher().clone();
for key in route_matcher.get_static_route().keys() {
println!("Static route: {key}");
Expand All @@ -40,10 +55,10 @@ fn get_route() {
#[test]
fn segment_count_optimization() {
let mut server: Server = Server::default();
server.route::<TestRoute, &str>("/users/{id}");
server.route::<TestRoute, &str>("/users/{id}/posts");
server.route::<TestRoute, &str>("/users/{id}/posts/{post_id}");
server.route::<TestRoute, &str>("/api/v1/users/{id}");
server.route::<TestRoute>("/users/{id}");
server.route::<TestRoute>("/users/{id}/posts");
server.route::<TestRoute>("/users/{id}/posts/{post_id}");
server.route::<TestRoute>("/api/v1/users/{id}");
let route_matcher: RouteMatcher = server.get_route_matcher().clone();
assert!(
route_matcher.get_dynamic_route().contains_key(&2),
Expand All @@ -65,9 +80,9 @@ fn segment_count_optimization() {
#[test]
fn regex_route_segment_count() {
let mut server: Server = Server::default();
server.route::<TestRoute, &str>("/files/{path:.*}");
server.route::<TestRoute, &str>("/api/{version:\\d+}/users");
server.route::<TestRoute, &str>("/api/{version:\\d+}/posts/{id:\\d+}");
server.route::<TestRoute>("/files/{path:.*}");
server.route::<TestRoute>("/api/{version:\\d+}/users");
server.route::<TestRoute>("/api/{version:\\d+}/posts/{id:\\d+}");
let route_matcher: RouteMatcher = server.get_route_matcher().clone();
assert!(
route_matcher.get_regex_route().contains_key(&2),
Expand All @@ -86,11 +101,11 @@ fn regex_route_segment_count() {
#[test]
fn mixed_route_types() {
let mut server: Server = Server::default();
server.route::<TestRoute, &str>("/");
server.route::<TestRoute, &str>("/about");
server.route::<TestRoute, &str>("/users/{id}");
server.route::<TestRoute, &str>("/posts/{slug}");
server.route::<TestRoute, &str>("/files/{path:.*}");
server.route::<TestRoute>("/");
server.route::<TestRoute>("/about");
server.route::<TestRoute>("/users/{id}");
server.route::<TestRoute>("/posts/{slug}");
server.route::<TestRoute>("/files/{path:.*}");
let route_matcher: RouteMatcher = server.get_route_matcher().clone();
assert_eq!(route_matcher.get_static_route().len(), 2);
assert!(route_matcher.get_dynamic_route().contains_key(&2));
Expand All @@ -104,7 +119,7 @@ fn large_dynamic_routes() {
let start_insert: Instant = Instant::now();
for i in 0..ROUTE_COUNT {
let path: String = format!("/api/resource{i}/{{id}}");
server.route::<TestRoute, &String>(&path);
server.route::<TestRoute>(&path);
}
let insert_duration: Duration = start_insert.elapsed();
println!(
Expand Down Expand Up @@ -137,7 +152,7 @@ fn large_regex_routes() {
let start_insert: Instant = Instant::now();
for i in 0..ROUTE_COUNT {
let path: String = format!("/api/resource{i}/{{id:[0-9]+}}");
server.route::<TestRoute, &String>(&path);
server.route::<TestRoute>(&path);
}
let insert_duration: Duration = start_insert.elapsed();
println!(
Expand Down Expand Up @@ -170,7 +185,7 @@ fn large_tail_regex_routes() {
let start_insert: Instant = Instant::now();
for i in 0..ROUTE_COUNT {
let path: String = format!("/api/resource{i}/{{path:.*}}");
server.route::<TestRoute, &String>(&path);
server.route::<TestRoute>(&path);
}
let insert_duration: Duration = start_insert.elapsed();
println!(
Expand Down
38 changes: 19 additions & 19 deletions core/tests/server/fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn server_send_sync() {
#[tokio::test]
async fn server_clone_across_threads() {
let mut server: Server = Server::default();
server.route::<TestSendRoute, &str>("/test");
server.route::<TestSendRoute>("/test");
let server_clone: Server = server.clone();
let handle: JoinHandle<&'static str> = spawn(async move {
let _server_in_thread: Server = server_clone;
Expand All @@ -159,7 +159,7 @@ async fn server_clone_across_threads() {
#[tokio::test]
async fn server_share_across_threads() {
let mut server: Server = Server::default();
server.route::<TestSendRoute, &str>("/test");
server.route::<TestSendRoute>("/test");
let server: Arc<Server> = Arc::new(server);
let server1: Arc<Server> = server.clone();
let server2: Arc<Server> = server.clone();
Expand Down Expand Up @@ -190,12 +190,12 @@ async fn main() {
server.request_middleware::<RequestMiddleware>();
server.request_middleware::<UpgradeMiddleware>();
server.response_middleware::<ResponseMiddleware>();
server.route::<RootRoute, &str>("/");
server.route::<SseRoute, &str>("/sse");
server.route::<WebsocketRoute, &str>("/websocket");
server.route::<GetAllRoutes, &str>("/get/all/routes");
server.route::<DynamicRoute, &str>("/dynamic/{routing}");
server.route::<DynamicRoute, &str>("/regex/{file:^.*$}");
server.route::<RootRoute>("/");
server.route::<SseRoute>("/sse");
server.route::<WebsocketRoute>("/websocket");
server.route::<GetAllRoutes>("/get/all/routes");
server.route::<DynamicRoute>("/dynamic/{routing}");
server.route::<DynamicRoute>("/regex/{file:^.*$}");
let _: Result<(), Server> = SERVER_REF.set(server.clone());
let server_control_hook_1: ServerControlHook = server.run().await.unwrap_or_default();
let server_control_hook_2: ServerControlHook = server_control_hook_1.clone();
Expand Down Expand Up @@ -328,7 +328,7 @@ async fn client_handle_hook_dispatches_to_correct_handler_list() {
#[tokio::test]
async fn client_route_basic_serial_e2e() {
let (control, port) = start_server_with(|register: &mut Server| {
register.route::<RootRoute, &str>("/");
register.route::<RootRoute>("/");
})
.await;
let request: &[u8] = b"GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n";
Expand All @@ -340,7 +340,7 @@ async fn client_route_basic_serial_e2e() {
#[tokio::test]
async fn client_dynamic_route_serial_e2e() {
let (control, port) = start_server_with(|register: &mut Server| {
register.route::<DynamicRoute, &str>("/dynamic/:id");
register.route::<DynamicRoute>("/dynamic/:id");
})
.await;
let request: &[u8] =
Expand All @@ -353,7 +353,7 @@ async fn client_dynamic_route_serial_e2e() {
#[tokio::test]
async fn client_regex_route_serial_e2e() {
let (control, port) = start_server_with(|register: &mut Server| {
register.route::<WebsocketRoute, &str>("/ws");
register.route::<WebsocketRoute>("/ws");
})
.await;
let request: &[u8] = b"GET /ws HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n";
Expand All @@ -365,7 +365,7 @@ async fn client_regex_route_serial_e2e() {
#[tokio::test]
async fn client_request_error_404_serial_e2e() {
let (control, port) = start_server_with(|register: &mut Server| {
register.route::<RootRoute, &str>("/");
register.route::<RootRoute>("/");
register.request_error::<RequestErrorHook>();
})
.await;
Expand All @@ -378,7 +378,7 @@ async fn client_request_error_404_serial_e2e() {
#[tokio::test]
async fn client_request_middleware_serial_e2e() {
let (control, port) = start_server_with(|register: &mut Server| {
register.route::<RootRoute, &str>("/");
register.route::<RootRoute>("/");
register.request_middleware::<RequestMiddleware>();
})
.await;
Expand All @@ -391,7 +391,7 @@ async fn client_request_middleware_serial_e2e() {
#[tokio::test]
async fn client_response_middleware_serial_e2e() {
let (control, port) = start_server_with(|register: &mut Server| {
register.route::<RootRoute, &str>("/");
register.route::<RootRoute>("/");
register.response_middleware::<ResponseMiddleware>();
})
.await;
Expand All @@ -404,7 +404,7 @@ async fn client_response_middleware_serial_e2e() {
#[tokio::test]
async fn client_task_panic_handler_serial_e2e() {
let (control, port) = start_server_with(|register: &mut Server| {
register.route::<DynamicRoute, &str>("/panic/:msg");
register.route::<DynamicRoute>("/panic/:msg");
register.task_panic::<TaskPanicHook>();
})
.await;
Expand All @@ -418,15 +418,15 @@ async fn client_task_panic_handler_serial_e2e() {
#[tokio::test]
async fn client_two_servers_on_distinct_ports_serial_e2e() {
let (control_a, port_a) = start_server_with(|register: &mut Server| {
register.route::<RootRoute, &str>("/");
register.route::<RootRoute>("/");
})
.await;
let request: &[u8] = b"GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n";
client_write_request(port_a, request).await;
control_a.shutdown().await;
control_a.wait().await;
let (control_b, port_b) = start_server_with(|register: &mut Server| {
register.route::<RootRoute, &str>("/");
register.route::<RootRoute>("/");
})
.await;
assert_ne!(port_a, port_b);
Expand All @@ -438,11 +438,11 @@ async fn client_two_servers_on_distinct_ports_serial_e2e() {
#[tokio::test]
async fn client_concurrent_servers_on_distinct_ports_e2e() {
let (control_a, port_a) = start_server_with(|register: &mut Server| {
register.route::<RootRoute, &str>("/");
register.route::<RootRoute>("/");
})
.await;
let (control_b, port_b) = start_server_with(|register: &mut Server| {
register.route::<RootRoute, &str>("/");
register.route::<RootRoute>("/");
})
.await;
assert_ne!(port_a, port_b);
Expand Down
4 changes: 2 additions & 2 deletions plugin/websocket/tests/websocket/fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ async fn main() {
server.request_error::<RequestErrorHook>();
server.request_middleware::<RequestMiddleware>();
server.request_middleware::<UpgradeHook>();
server.route::<GroupChat, &str>("/{group_name}");
server.route::<PrivateChat, &str>("/{my_name}/{your_name}");
server.route::<GroupChat>("/{group_name}");
server.route::<PrivateChat>("/{my_name}/{your_name}");
let server_control_hook_1: ServerControlHook = server.run().await.unwrap_or_default();
let server_control_hook_2: ServerControlHook = server_control_hook_1.clone();
spawn(async move {
Expand Down
Loading