summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorFelix <me@nutomic.com>2020-01-15 16:37:25 +0100
committerFelix <me@nutomic.com>2020-01-18 14:23:43 +0100
commit1e60e1e35106157bcf7ca52d25bacf8b6a7e15b0 (patch)
tree8ff5da5f42ae188e3687223b838ac747149b0ead /server
parent8604c1d257ed68527ce345e6886eabfa929cbc87 (diff)
Implement HTTP API using generics (fixes #380)
Diffstat (limited to 'server')
-rw-r--r--server/.rustfmt.toml2
-rw-r--r--server/src/main.rs3
-rw-r--r--server/src/routes/api.rs62
-rw-r--r--server/src/routes/mod.rs1
4 files changed, 66 insertions, 2 deletions
diff --git a/server/.rustfmt.toml b/server/.rustfmt.toml
index b1fce9c9..684a7f8a 100644
--- a/server/.rustfmt.toml
+++ b/server/.rustfmt.toml
@@ -1,2 +1,2 @@
tab_spaces = 2
-edition="2018"
+edition="2018" \ No newline at end of file
diff --git a/server/src/main.rs b/server/src/main.rs
index 636182aa..601c2e0d 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -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
index 00000000..edf1ead6
--- /dev/null
+++ b/server/src/routes/api.rs
@@ -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)
+}
diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs
index 6556c8d5..27d9ea1b 100644
--- a/server/src/routes/mod.rs
+++ b/server/src/routes/mod.rs
@@ -1,3 +1,4 @@
+pub mod api;
pub mod federation;
pub mod feeds;
pub mod index;