]> Untitled Git - lemmy.git/commitdiff
Implement HTTP API using generics (fixes #380)
authorFelix <me@nutomic.com>
Wed, 15 Jan 2020 15:37:25 +0000 (16:37 +0100)
committerFelix <me@nutomic.com>
Sat, 18 Jan 2020 13:23:43 +0000 (14:23 +0100)
server/.rustfmt.toml
server/src/main.rs
server/src/routes/api.rs [new file with mode: 0644]
server/src/routes/mod.rs

index b1fce9c9a5718f2922ca5593fdd64b58d1920da8..684a7f8a27ae738ba679bcbdc8a3fc4ac1b9c305 100644 (file)
@@ -1,2 +1,2 @@
 tab_spaces = 2
-edition="2018"
+edition="2018"
\ No newline at end of file
index 636182aa45c5b1a7a86348fe285a7b72ced9b064..601c2e0dc019f8edabf3af57fef1cfe683466760 100644 (file)
@@ -6,7 +6,7 @@ use actix::prelude::*;
 use actix_web::*;
 use diesel::r2d2::{ConnectionManager, Pool};
 use diesel::PgConnection;
-use lemmy_server::routes::{federation, feeds, index, nodeinfo, webfinger, websocket};
+use lemmy_server::routes::{api, federation, feeds, index, nodeinfo, webfinger, websocket};
 use lemmy_server::settings::Settings;
 use lemmy_server::websocket::server::*;
 use std::io;
@@ -44,6 +44,7 @@ async fn main() -> io::Result<()> {
       .data(pool.clone())
       .data(server.clone())
       // The routes
+      .configure(api::config)
       .configure(federation::config)
       .configure(feeds::config)
       .configure(index::config)
diff --git a/server/src/routes/api.rs b/server/src/routes/api.rs
new file mode 100644 (file)
index 0000000..edf1ead
--- /dev/null
@@ -0,0 +1,62 @@
+use crate::api::community::{
+  GetCommunity, GetCommunityResponse, ListCommunities, ListCommunitiesResponse,
+};
+use crate::api::UserOperation;
+use crate::api::{Oper, Perform};
+use actix_web::{web, HttpResponse};
+use diesel::r2d2::{ConnectionManager, Pool};
+use diesel::PgConnection;
+use failure::Error;
+use serde::Serialize;
+
+type DbParam = web::Data<Pool<ConnectionManager<PgConnection>>>;
+
+pub fn config(cfg: &mut web::ServiceConfig) {
+  cfg
+    // TODO: need to repeat this for every endpoint
+    .route(
+      "/api/v1/list_communities",
+      web::get().to(|info, db| {
+        route::<ListCommunities, ListCommunitiesResponse>(UserOperation::ListCommunities, info, db)
+      }),
+    )
+    .route(
+      "/api/v1/get_community",
+      web::get().to(|info, db| {
+        route::<GetCommunity, GetCommunityResponse>(UserOperation::GetCommunity, info, db)
+      }),
+    );
+}
+
+fn perform<Request, Response>(
+  op: UserOperation,
+  data: Request,
+  db: DbParam,
+) -> Result<HttpResponse, Error>
+where
+  Response: Serialize,
+  Oper<Request>: Perform<Response>,
+{
+  let conn = match db.get() {
+    Ok(c) => c,
+    Err(e) => return Err(format_err!("{}", e)),
+  };
+  let oper: Oper<Request> = Oper::new(op, data);
+  let response = oper.perform(&conn);
+  Ok(HttpResponse::Ok().json(response?))
+}
+
+async fn route<Data, Response>(
+  op: UserOperation,
+  info: web::Query<Data>,
+  db: DbParam,
+) -> Result<HttpResponse, Error>
+where
+  Data: Serialize,
+  Response: Serialize,
+  Oper<Data>: Perform<Response>,
+{
+  // TODO: want an implementation like this, where useroperation is passed without explicitly passing the other params
+  //       maybe with a higher order functions? (but that would probably have worse performance)
+  perform::<Data, Response>(op, info.0, db)
+}
index 6556c8d58850f595f248324c22b5006e07324747..27d9ea1be59dd7d575d7e8541bfe1a44c1180d9e 100644 (file)
@@ -1,3 +1,4 @@
+pub mod api;
 pub mod federation;
 pub mod feeds;
 pub mod index;