mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-22 17:11:09 +00:00
add basic api call with test
This commit is contained in:
parent
df9da3784b
commit
1098ecd4a1
8 changed files with 108 additions and 48 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -464,6 +464,7 @@ dependencies = [
|
||||||
"enum_delegate",
|
"enum_delegate",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"rand",
|
"rand",
|
||||||
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
@ -18,3 +18,6 @@ serde_json = "1.0.108"
|
||||||
tokio = { version = "1.34.0", features = ["full"] }
|
tokio = { version = "1.34.0", features = ["full"] }
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
url = "2.4.1"
|
url = "2.4.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
reqwest = "0.11.22"
|
||||||
|
|
13
src/api.rs
Normal file
13
src/api.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use crate::error::MyResult;
|
||||||
|
use crate::federation::objects::article::DbArticle;
|
||||||
|
use crate::federation::objects::instance::DbInstance;
|
||||||
|
use axum::extract::Path;
|
||||||
|
use axum::Json;
|
||||||
|
use axum_macros::debug_handler;
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
pub async fn api_get_article(Path(title): Path<String>) -> MyResult<Json<DbArticle>> {
|
||||||
|
let instance = DbInstance::new("localhost")?;
|
||||||
|
let article = DbArticle::new(title, "dummy".to_string(), instance.ap_id)?;
|
||||||
|
Ok(Json(article))
|
||||||
|
}
|
|
@ -11,8 +11,9 @@ use activitypub_federation::{
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct DbArticle {
|
pub struct DbArticle {
|
||||||
|
pub title: String,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
pub ap_id: ObjectId<DbArticle>,
|
pub ap_id: ObjectId<DbArticle>,
|
||||||
pub instance: ObjectId<DbInstance>,
|
pub instance: ObjectId<DbInstance>,
|
||||||
|
@ -20,9 +21,14 @@ pub struct DbArticle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DbArticle {
|
impl DbArticle {
|
||||||
pub fn new(text: String, attributed_to: ObjectId<DbInstance>) -> Result<DbArticle, Error> {
|
pub fn new(
|
||||||
|
title: String,
|
||||||
|
text: String,
|
||||||
|
attributed_to: ObjectId<DbInstance>,
|
||||||
|
) -> Result<DbArticle, Error> {
|
||||||
let ap_id = generate_object_id(attributed_to.inner())?.into();
|
let ap_id = generate_object_id(attributed_to.inner())?.into();
|
||||||
Ok(DbArticle {
|
Ok(DbArticle {
|
||||||
|
title,
|
||||||
text,
|
text,
|
||||||
ap_id,
|
ap_id,
|
||||||
instance: attributed_to,
|
instance: attributed_to,
|
||||||
|
@ -41,6 +47,7 @@ pub struct Article {
|
||||||
#[serde(deserialize_with = "deserialize_one_or_many")]
|
#[serde(deserialize_with = "deserialize_one_or_many")]
|
||||||
pub(crate) to: Vec<Url>,
|
pub(crate) to: Vec<Url>,
|
||||||
content: String,
|
content: String,
|
||||||
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
|
@ -69,6 +76,7 @@ impl Object for DbArticle {
|
||||||
attributed_to: self.instance,
|
attributed_to: self.instance,
|
||||||
to: vec![public(), instance.followers_url()?],
|
to: vec![public(), instance.followers_url()?],
|
||||||
content: self.text,
|
content: self.text,
|
||||||
|
name: self.title,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +91,7 @@ impl Object for DbArticle {
|
||||||
|
|
||||||
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
||||||
let post = DbArticle {
|
let post = DbArticle {
|
||||||
|
title: json.name,
|
||||||
text: json.content,
|
text: json.content,
|
||||||
ap_id: json.id,
|
ap_id: json.id,
|
||||||
instance: json.attributed_to,
|
instance: json.attributed_to,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::database::DatabaseHandle;
|
use crate::database::DatabaseHandle;
|
||||||
use crate::error::Error;
|
use crate::error::MyResult;
|
||||||
use crate::federation::objects::person::{DbUser, Person, PersonAcceptedActivities};
|
use crate::federation::objects::person::{DbUser, Person, PersonAcceptedActivities};
|
||||||
use activitypub_federation::axum::inbox::{receive_activity, ActivityData};
|
use activitypub_federation::axum::inbox::{receive_activity, ActivityData};
|
||||||
use activitypub_federation::axum::json::FederationJson;
|
use activitypub_federation::axum::json::FederationJson;
|
||||||
|
@ -14,7 +14,7 @@ use axum_macros::debug_handler;
|
||||||
pub async fn http_get_user(
|
pub async fn http_get_user(
|
||||||
Path(name): Path<String>,
|
Path(name): Path<String>,
|
||||||
data: Data<DatabaseHandle>,
|
data: Data<DatabaseHandle>,
|
||||||
) -> Result<FederationJson<WithContext<Person>>, Error> {
|
) -> MyResult<FederationJson<WithContext<Person>>> {
|
||||||
let db_user = data.read_user(&name)?;
|
let db_user = data.read_user(&name)?;
|
||||||
let json_user = db_user.into_json(&data).await?;
|
let json_user = db_user.into_json(&data).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(json_user)))
|
Ok(FederationJson(WithContext::new_default(json_user)))
|
||||||
|
|
52
src/lib.rs
Normal file
52
src/lib.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::utils::generate_object_id;
|
||||||
|
use tracing::log::LevelFilter;
|
||||||
|
|
||||||
|
use activitypub_federation::config::FederationMiddleware;
|
||||||
|
use axum::{
|
||||||
|
routing::{get, post},
|
||||||
|
Router, Server,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::api::api_get_article;
|
||||||
|
use crate::error::MyResult;
|
||||||
|
use crate::federation::routes::http_get_user;
|
||||||
|
use crate::federation::routes::http_post_user_inbox;
|
||||||
|
use federation::federation_config;
|
||||||
|
use std::net::ToSocketAddrs;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
mod api;
|
||||||
|
mod database;
|
||||||
|
pub mod error;
|
||||||
|
pub mod federation;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
pub async fn start(hostname: &str) -> MyResult<()> {
|
||||||
|
env_logger::builder()
|
||||||
|
.filter_level(LevelFilter::Warn)
|
||||||
|
.filter_module("activitypub_federation", LevelFilter::Info)
|
||||||
|
.filter_module("fediwiki", LevelFilter::Info)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
let config = federation_config(hostname).await?;
|
||||||
|
|
||||||
|
info!("Listening with axum on {hostname}");
|
||||||
|
let config = config.clone();
|
||||||
|
let app = Router::new()
|
||||||
|
// federation routes
|
||||||
|
.route("/:user/inbox", post(http_post_user_inbox))
|
||||||
|
.route("/:user", get(http_get_user))
|
||||||
|
// api routes
|
||||||
|
.route("/api/v1/article/:title", get(api_get_article))
|
||||||
|
.layer(FederationMiddleware::new(config));
|
||||||
|
|
||||||
|
let addr = hostname
|
||||||
|
.to_socket_addrs()?
|
||||||
|
.next()
|
||||||
|
.expect("Failed to lookup domain name");
|
||||||
|
let server = Server::bind(&addr).serve(app.into_make_service());
|
||||||
|
|
||||||
|
tokio::spawn(server);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
48
src/main.rs
48
src/main.rs
|
@ -1,48 +1,8 @@
|
||||||
use crate::utils::generate_object_id;
|
use fediwiki::error::MyResult;
|
||||||
use error::Error;
|
use fediwiki::start;
|
||||||
use tracing::log::LevelFilter;
|
|
||||||
|
|
||||||
use activitypub_federation::config::FederationMiddleware;
|
|
||||||
use axum::{
|
|
||||||
routing::{get, post},
|
|
||||||
Router, Server,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::federation::routes::http_get_user;
|
|
||||||
use crate::federation::routes::http_post_user_inbox;
|
|
||||||
use federation::federation_config;
|
|
||||||
use std::net::ToSocketAddrs;
|
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
mod database;
|
|
||||||
mod error;
|
|
||||||
mod federation;
|
|
||||||
mod utils;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Error> {
|
pub async fn main() -> MyResult<()> {
|
||||||
env_logger::builder()
|
start("localhost:8131").await?;
|
||||||
.filter_level(LevelFilter::Warn)
|
|
||||||
.filter_module("activitypub_federation", LevelFilter::Info)
|
|
||||||
.filter_module("fediwiki", LevelFilter::Info)
|
|
||||||
.init();
|
|
||||||
|
|
||||||
let config = federation_config("localhost:8001").await?;
|
|
||||||
|
|
||||||
let hostname = config.domain();
|
|
||||||
info!("Listening with axum on {hostname}");
|
|
||||||
let config = config.clone();
|
|
||||||
let app = Router::new()
|
|
||||||
.route("/:user/inbox", post(http_post_user_inbox))
|
|
||||||
.route("/:user", get(http_get_user))
|
|
||||||
.layer(FederationMiddleware::new(config));
|
|
||||||
|
|
||||||
let addr = hostname
|
|
||||||
.to_socket_addrs()?
|
|
||||||
.next()
|
|
||||||
.expect("Failed to lookup domain name");
|
|
||||||
let server = Server::bind(&addr).serve(app.into_make_service());
|
|
||||||
|
|
||||||
tokio::spawn(server);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
22
tests/test.rs
Normal file
22
tests/test.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
extern crate fediwiki;
|
||||||
|
use fediwiki::federation::objects::article::DbArticle;
|
||||||
|
use fediwiki::start;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_article() {
|
||||||
|
let hostname = "localhost:8131";
|
||||||
|
let join = tokio::task::spawn(async {
|
||||||
|
start(hostname).await.unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
let title = "Manu_Chao";
|
||||||
|
let res: DbArticle = reqwest::get(format!("http://{hostname}/api/v1/article/{title}"))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.json()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(title, res.title);
|
||||||
|
assert!(res.local);
|
||||||
|
join.abort();
|
||||||
|
}
|
Loading…
Reference in a new issue