diff options
author | Felix <me@nutomic.com> | 2020-01-15 16:37:25 +0100 |
---|---|---|
committer | Felix <me@nutomic.com> | 2020-01-18 14:23:43 +0100 |
commit | 1e60e1e35106157bcf7ca52d25bacf8b6a7e15b0 (patch) | |
tree | 8ff5da5f42ae188e3687223b838ac747149b0ead /server | |
parent | 8604c1d257ed68527ce345e6886eabfa929cbc87 (diff) |
Implement HTTP API using generics (fixes #380)
Diffstat (limited to 'server')
-rw-r--r-- | server/.rustfmt.toml | 2 | ||||
-rw-r--r-- | server/src/main.rs | 3 | ||||
-rw-r--r-- | server/src/routes/api.rs | 62 | ||||
-rw-r--r-- | server/src/routes/mod.rs | 1 |
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; |