#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum HttpMethod {
Get,
Post,
Delete,
}
#[derive(Debug)]
pub(super) struct Route {
pub(super) http_method: HttpMethod,
pub(super) path_template: &'static str,
pub(super) path_params: &'static [&'static str],
#[allow(dead_code)]
pub(super) streaming: bool,
}
#[allow(clippy::too_many_lines)]
pub(super) fn route_for(method: &str) -> Option<Route> {
match method {
"SendMessage" => Some(Route {
http_method: HttpMethod::Post,
path_template: "/message:send",
path_params: &[],
streaming: false,
}),
"SendStreamingMessage" => Some(Route {
http_method: HttpMethod::Post,
path_template: "/message:stream",
path_params: &[],
streaming: true,
}),
"GetTask" => Some(Route {
http_method: HttpMethod::Get,
path_template: "/tasks/{id}",
path_params: &["id"],
streaming: false,
}),
"CancelTask" => Some(Route {
http_method: HttpMethod::Post,
path_template: "/tasks/{id}:cancel",
path_params: &["id"],
streaming: false,
}),
"ListTasks" => Some(Route {
http_method: HttpMethod::Get,
path_template: "/tasks",
path_params: &[],
streaming: false,
}),
"SubscribeToTask" => Some(Route {
http_method: HttpMethod::Post,
path_template: "/tasks/{id}:subscribe",
path_params: &["id"],
streaming: true,
}),
"CreateTaskPushNotificationConfig" => Some(Route {
http_method: HttpMethod::Post,
path_template: "/tasks/{taskId}/pushNotificationConfigs",
path_params: &["taskId"],
streaming: false,
}),
"GetTaskPushNotificationConfig" => Some(Route {
http_method: HttpMethod::Get,
path_template: "/tasks/{taskId}/pushNotificationConfigs/{id}",
path_params: &["taskId", "id"],
streaming: false,
}),
"ListTaskPushNotificationConfigs" => Some(Route {
http_method: HttpMethod::Get,
path_template: "/tasks/{taskId}/pushNotificationConfigs",
path_params: &["taskId"],
streaming: false,
}),
"DeleteTaskPushNotificationConfig" => Some(Route {
http_method: HttpMethod::Delete,
path_template: "/tasks/{taskId}/pushNotificationConfigs/{id}",
path_params: &["taskId", "id"],
streaming: false,
}),
"GetExtendedAgentCard" => Some(Route {
http_method: HttpMethod::Get,
path_template: "/extendedAgentCard",
path_params: &[],
streaming: false,
}),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn route_for_known_methods() {
let send_msg = route_for("SendMessage").expect("SendMessage should have a route");
assert_eq!(send_msg.http_method, HttpMethod::Post);
assert_eq!(send_msg.path_template, "/message:send");
let get_task = route_for("GetTask").expect("GetTask should have a route");
assert_eq!(get_task.http_method, HttpMethod::Get);
assert_eq!(get_task.path_template, "/tasks/{id}");
let list_tasks = route_for("ListTasks").expect("ListTasks should have a route");
assert_eq!(list_tasks.http_method, HttpMethod::Get);
assert_eq!(list_tasks.path_template, "/tasks");
let stream_msg =
route_for("SendStreamingMessage").expect("SendStreamingMessage should have a route");
assert!(stream_msg.streaming);
assert_eq!(stream_msg.path_template, "/message:stream");
}
#[test]
fn route_for_unknown_method_returns_none() {
assert!(route_for("unknown/method").is_none());
}
#[test]
fn all_routes_match_spec_url_patterns() {
let spec_table: &[(&str, HttpMethod, &str, bool)] = &[
("SendMessage", HttpMethod::Post, "/message:send", false),
(
"SendStreamingMessage",
HttpMethod::Post,
"/message:stream",
true,
),
("GetTask", HttpMethod::Get, "/tasks/{id}", false),
("ListTasks", HttpMethod::Get, "/tasks", false),
("CancelTask", HttpMethod::Post, "/tasks/{id}:cancel", false),
(
"SubscribeToTask",
HttpMethod::Post,
"/tasks/{id}:subscribe",
true,
),
(
"CreateTaskPushNotificationConfig",
HttpMethod::Post,
"/tasks/{taskId}/pushNotificationConfigs",
false,
),
(
"GetTaskPushNotificationConfig",
HttpMethod::Get,
"/tasks/{taskId}/pushNotificationConfigs/{id}",
false,
),
(
"ListTaskPushNotificationConfigs",
HttpMethod::Get,
"/tasks/{taskId}/pushNotificationConfigs",
false,
),
(
"DeleteTaskPushNotificationConfig",
HttpMethod::Delete,
"/tasks/{taskId}/pushNotificationConfigs/{id}",
false,
),
(
"GetExtendedAgentCard",
HttpMethod::Get,
"/extendedAgentCard",
false,
),
];
for (method, want_verb, want_path, want_streaming) in spec_table {
let route = route_for(method).unwrap_or_else(|| panic!("{method} must have a route"));
assert_eq!(&route.http_method, want_verb, "{method}: wrong verb");
assert_eq!(&route.path_template, want_path, "{method}: wrong path");
assert_eq!(
route.streaming, *want_streaming,
"{method}: wrong streaming flag"
);
}
}
#[test]
fn route_for_cancel_task() {
let r = route_for("CancelTask").expect("CancelTask should have a route");
assert_eq!(r.http_method, HttpMethod::Post);
assert_eq!(r.path_template, "/tasks/{id}:cancel");
assert_eq!(r.path_params, &["id"]);
assert!(!r.streaming);
}
#[test]
fn route_for_subscribe_to_task() {
let r = route_for("SubscribeToTask").expect("SubscribeToTask should have a route");
assert_eq!(r.http_method, HttpMethod::Post);
assert_eq!(r.path_template, "/tasks/{id}:subscribe");
assert_eq!(r.path_params, &["id"]);
assert!(r.streaming);
}
#[test]
fn route_for_create_task_push_notification_config() {
let r = route_for("CreateTaskPushNotificationConfig")
.expect("CreateTaskPushNotificationConfig should have a route");
assert_eq!(r.http_method, HttpMethod::Post);
assert_eq!(r.path_template, "/tasks/{taskId}/pushNotificationConfigs");
assert_eq!(r.path_params, &["taskId"]);
assert!(!r.streaming);
}
#[test]
fn route_for_get_task_push_notification_config() {
let r = route_for("GetTaskPushNotificationConfig")
.expect("GetTaskPushNotificationConfig should have a route");
assert_eq!(r.http_method, HttpMethod::Get);
assert_eq!(
r.path_template,
"/tasks/{taskId}/pushNotificationConfigs/{id}"
);
assert_eq!(r.path_params, &["taskId", "id"]);
assert!(!r.streaming);
}
#[test]
fn route_for_list_task_push_notification_configs() {
let r = route_for("ListTaskPushNotificationConfigs")
.expect("ListTaskPushNotificationConfigs should have a route");
assert_eq!(r.http_method, HttpMethod::Get);
assert_eq!(r.path_template, "/tasks/{taskId}/pushNotificationConfigs");
assert_eq!(r.path_params, &["taskId"]);
assert!(!r.streaming);
}
#[test]
fn route_for_delete_task_push_notification_config() {
let r = route_for("DeleteTaskPushNotificationConfig")
.expect("DeleteTaskPushNotificationConfig should have a route");
assert_eq!(r.http_method, HttpMethod::Delete);
assert_eq!(
r.path_template,
"/tasks/{taskId}/pushNotificationConfigs/{id}"
);
assert_eq!(r.path_params, &["taskId", "id"]);
assert!(!r.streaming);
}
#[test]
fn route_for_get_extended_agent_card() {
let r =
route_for("GetExtendedAgentCard").expect("GetExtendedAgentCard should have a route");
assert_eq!(r.http_method, HttpMethod::Get);
assert_eq!(r.path_template, "/extendedAgentCard");
assert!(r.path_params.is_empty());
assert!(!r.streaming);
}
}