use reqwest::Method;
pub(crate) static CREATE_KEY: Route = Route::new(Method::POST, "/keys.createKey");
pub(crate) static VERIFY_KEY: Route = Route::new(Method::POST, "/keys.verifyKey");
pub(crate) static REVOKE_KEY: Route = Route::new(Method::POST, "/keys.deleteKey");
pub(crate) static UPDATE_KEY: Route = Route::new(Method::POST, "/keys.updateKey");
pub(crate) static GET_KEY: Route = Route::new(Method::GET, "/keys.getKey");
pub(crate) static UPDATE_REMAINING: Route = Route::new(Method::POST, "/keys.updateRemaining");
pub(crate) static GET_API: Route = Route::new(Method::GET, "/apis.getApi");
pub(crate) static LIST_KEYS: Route = Route::new(Method::GET, "/apis.listKeys");
pub(crate) static DELETE_API: Route = Route::new(Method::POST, "/apis.deleteApi");
#[derive(Debug, Clone)]
pub(crate) struct Route {
pub method: Method,
pub uri: &'static str,
}
impl Route {
#[must_use]
pub const fn new(method: Method, uri: &'static str) -> Self {
Self { method, uri }
}
#[must_use]
pub fn compile(&self) -> CompiledRoute {
CompiledRoute::new(self)
}
}
#[derive(Debug, Clone)]
pub(crate) struct CompiledRoute {
pub uri: String,
pub method: Method,
pub params: Vec<(String, String)>,
}
impl CompiledRoute {
#[must_use]
#[rustfmt::skip]
pub fn new(route: &Route) -> Self {
let params = Vec::new();
let uri = route.uri.to_string();
let method = route.method.clone();
Self { uri, method, params }
}
#[allow(dead_code)] pub fn uri_insert<T: Into<String>>(&mut self, param: T) -> &mut Self {
self.uri = self.uri.replacen("{}", ¶m.into(), 1);
self
}
pub fn query_insert<T: Into<String>>(&mut self, name: T, value: T) -> &mut Self {
self.params.push((name.into(), value.into()));
self
}
#[must_use]
pub fn build_query(&self) -> String {
let mut query = self
.params
.iter()
.map(|(k, v)| format!("{k}={v}"))
.collect::<Vec<String>>()
.join("&");
if !query.is_empty() {
query.insert(0, '?');
}
query
}
}
#[cfg(test)]
mod test {
use crate::routes::CompiledRoute;
use crate::routes::Route;
use reqwest::Method;
#[test]
fn route_new() {
let r = Route::new(Method::GET, "/keys/owo");
assert_eq!(r.method, Method::GET);
assert_eq!(r.uri, "/keys/owo");
}
#[test]
fn route_compile() {
let r = Route::new(Method::GET, "/apis/woot").compile();
assert_eq!(r.params, vec![]);
assert_eq!(r.method, Method::GET);
assert_eq!(r.uri, String::from("/apis/woot"));
}
#[test]
fn compiled_route_new() {
let r = Route::new(Method::GET, "/apis/hi");
let c = CompiledRoute::new(&r);
assert_eq!(c.params, vec![]);
assert_eq!(c.method, Method::GET);
assert_eq!(c.uri, String::from("/apis/hi"));
}
#[test]
fn compiled_route_uri_insert() {
let r = Route::new(Method::GET, "/apis/{}/keys/{}");
let mut c = CompiledRoute::new(&r);
c.uri_insert("5").uri_insert("1");
assert_eq!(c.params, vec![]);
assert_eq!(c.method, Method::GET);
assert_eq!(c.uri, String::from("/apis/5/keys/1"));
}
#[test]
fn compiled_route_query_insert() {
let r = Route::new(Method::GET, "/apis/milk");
let mut c = CompiledRoute::new(&r);
c.query_insert("test", "value");
assert_eq!(c.method, Method::GET);
assert_eq!(c.uri, String::from("/apis/milk"));
assert_eq!(
c.params,
vec![(String::from("test"), String::from("value"))]
);
}
#[test]
fn compiled_route_build_query() {
let r = Route::new(Method::GET, "/apis/milk");
let mut c = CompiledRoute::new(&r);
c.query_insert("test", "value").query_insert("js", "bad");
assert_eq!(c.build_query(), String::from("?test=value&js=bad"));
}
}