diff --git a/src/server/mod.rs b/src/server/mod.rs
index a0a2255..071b840 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -1,4 +1,8 @@
+/// Routes
+pub mod route;
/// Services
pub mod service;
/// Traits
pub mod traits;
+/// Version
+pub mod version;
diff --git a/src/server/route.rs b/src/server/route.rs
new file mode 100644
index 0000000..05dd1fc
--- /dev/null
+++ b/src/server/route.rs
@@ -0,0 +1,29 @@
+use super::traits::MatchRoute;
+use super::traits::ResponseFor;
+use super::version::VersionRoute;
+use hyper::Body;
+use hyper::Request;
+
+pub type RouteType = dyn MatchRoute
+ Send + Sync;
+pub type ResponseForType = dyn ResponseFor + Send + Sync;
+
+pub struct ServerRoutes {
+ routes: Vec>,
+}
+
+impl ServerRoutes {
+ pub fn new() -> Self {
+ let mut routes: Vec> = Vec::new();
+ routes.push(Box::new(VersionRoute::new()));
+ Self { routes }
+ }
+
+ pub fn match_route(&self, req: &Request) -> Option> {
+ for i in self.routes.iter() {
+ if i.match_route(req) {
+ return Some(i.get_route());
+ }
+ }
+ None
+ }
+}
diff --git a/src/server/service.rs b/src/server/service.rs
index ed5b86c..09362b3 100644
--- a/src/server/service.rs
+++ b/src/server/service.rs
@@ -1,3 +1,4 @@
+use super::route::ServerRoutes;
use hyper::server::conn::AddrIncoming;
use hyper::server::Server;
use hyper::service::Service;
@@ -7,16 +8,17 @@ use hyper::Response;
use std::future::Future;
use std::net::SocketAddr;
use std::pin::Pin;
+use std::sync::Arc;
use std::task::Context;
use std::task::Poll;
pub struct PixivDownloaderSvc {
- _unused: [u8; 0],
+ routes: Arc,
}
impl PixivDownloaderSvc {
- pub fn new() -> Self {
- Self { _unused: [] }
+ pub fn new(routes: Arc) -> Self {
+ Self { routes }
}
}
@@ -30,17 +32,35 @@ impl Service> for PixivDownloaderSvc {
}
fn call(&mut self, req: Request) -> Self::Future {
- Box::pin(async { Ok(Response::builder().body(Body::from("hello world")).unwrap()) })
+ match self.routes.match_route(&req) {
+ Some(route) => Box::pin(async move {
+ match route.response(req) {
+ Ok(data) => Ok(data),
+ Err(e) => {
+ println!("{}", e);
+ Ok(Response::builder()
+ .status(500)
+ .body(Body::from("Internal server error"))
+ .unwrap())
+ }
+ }
+ }),
+ None => {
+ Box::pin(async { Ok(Response::builder().body(Body::from("hello world")).unwrap()) })
+ }
+ }
}
}
pub struct PixivDownloaderMakeSvc {
- _unused: [u8; 0],
+ routes: Arc,
}
impl PixivDownloaderMakeSvc {
pub fn new() -> Self {
- Self { _unused: [] }
+ Self {
+ routes: Arc::new(ServerRoutes::new()),
+ }
}
}
@@ -54,7 +74,8 @@ impl Service for PixivDownloaderMakeSvc {
}
fn call(&mut self, _: T) -> Self::Future {
- let fut = async move { Ok(PixivDownloaderSvc::new()) };
+ let routes = Arc::clone(&self.routes);
+ let fut = async move { Ok(PixivDownloaderSvc::new(routes)) };
Box::pin(fut)
}
}
diff --git a/src/server/traits.rs b/src/server/traits.rs
index 734d2c9..e5d368d 100644
--- a/src/server/traits.rs
+++ b/src/server/traits.rs
@@ -4,20 +4,25 @@ use hyper::Request;
use hyper::Response;
use json::JsonValue;
+pub trait MatchRoute {
+ fn get_route(&self) -> Box + Send + Sync>;
+ fn match_route(&self, req: &Request) -> bool;
+}
+
pub trait ResponseFor {
- fn response(&self, res: Request) -> Result, PixivDownloaderError>;
+ fn response(&self, req: Request) -> Result, PixivDownloaderError>;
}
pub trait ResponseJsonFor {
- fn response_json(&self, res: Request) -> Result;
+ fn response_json(&self, req: Request) -> Result;
}
-impl ResponseFor for T
+impl ResponseFor for U
where
- T: ResponseJsonFor,
+ U: ResponseJsonFor,
{
- fn response(&self, res: Request) -> Result, PixivDownloaderError> {
- let re = self.response_json(res)?;
+ fn response(&self, req: Request) -> Result, PixivDownloaderError> {
+ let re = self.response_json(req)?;
Ok(Response::new(Body::from(re.to_string())))
}
}
diff --git a/src/server/version.rs b/src/server/version.rs
new file mode 100644
index 0000000..9422c4f
--- /dev/null
+++ b/src/server/version.rs
@@ -0,0 +1,46 @@
+use super::route::ResponseForType;
+use super::traits::MatchRoute;
+use super::traits::ResponseJsonFor;
+use crate::error::PixivDownloaderError;
+use hyper::Body;
+use hyper::Request;
+use json::JsonValue;
+use regex::Regex;
+
+pub struct VersionContext {
+ _unused: [u8; 0],
+}
+
+impl VersionContext {
+ pub fn new() -> Self {
+ Self { _unused: [] }
+ }
+}
+
+impl ResponseJsonFor for VersionContext {
+ fn response_json(&self, _req: Request) -> Result {
+ Ok(json::object! {"version": [0, 0, 1, 0]})
+ }
+}
+
+pub struct VersionRoute {
+ regex: Regex,
+}
+
+impl VersionRoute {
+ pub fn new() -> Self {
+ Self {
+ regex: Regex::new(r"^(/api)?/version(/.*)?$").unwrap(),
+ }
+ }
+}
+
+impl MatchRoute for VersionRoute {
+ fn get_route(&self) -> Box {
+ Box::new(VersionContext::new())
+ }
+
+ fn match_route(&self, req: &http::Request) -> bool {
+ self.regex.is_match(req.uri().path())
+ }
+}