Implement HTTP API using generics (fixes #380)
This commit is contained in:
parent
05f2bfc83c
commit
c41082f98f
4 changed files with 66 additions and 2 deletions
|
@ -6,7 +6,7 @@ use actix::prelude::*;
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
use diesel::r2d2::{ConnectionManager, Pool};
|
use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
use diesel::PgConnection;
|
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::settings::Settings;
|
||||||
use lemmy_server::websocket::server::*;
|
use lemmy_server::websocket::server::*;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -44,6 +44,7 @@ async fn main() -> io::Result<()> {
|
||||||
.data(pool.clone())
|
.data(pool.clone())
|
||||||
.data(server.clone())
|
.data(server.clone())
|
||||||
// The routes
|
// The routes
|
||||||
|
.configure(api::config)
|
||||||
.configure(federation::config)
|
.configure(federation::config)
|
||||||
.configure(feeds::config)
|
.configure(feeds::config)
|
||||||
.configure(index::config)
|
.configure(index::config)
|
||||||
|
|
62
server/src/routes/api.rs
Normal file
62
server/src/routes/api.rs
Normal file
|
@ -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)
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod api;
|
||||||
pub mod federation;
|
pub mod federation;
|
||||||
pub mod feeds;
|
pub mod feeds;
|
||||||
pub mod index;
|
pub mod index;
|
||||||
|
|
Reference in a new issue