Do a bit of reorganizing

This commit is contained in:
asonix 2020-03-23 12:38:39 -05:00
parent f44df38ea1
commit 9925e41673
14 changed files with 123 additions and 110 deletions

View file

@ -1,4 +1,4 @@
use crate::{error::MyError, requests::Requests, verifier::MyVerify}; use crate::{error::MyError, middleware::MyVerify, requests::Requests};
use config::Environment; use config::Environment;
use http_signature_normalization_actix::prelude::{VerifyDigest, VerifySignature}; use http_signature_normalization_actix::prelude::{VerifyDigest, VerifySignature};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};

View file

@ -1,77 +1,29 @@
use actix::Arbiter; use actix::Arbiter;
use actix_web::{ use actix_web::{middleware::Logger, web, App, HttpServer};
http::header::{ContentType, Expires},
middleware::Logger,
web, App, HttpResponse, HttpServer,
};
use log::error;
use std::{
io::BufWriter,
time::{Duration, SystemTime},
};
mod actor;
mod apub; mod apub;
mod args; mod args;
mod config; mod config;
mod db; mod db;
mod error; mod error;
mod inbox;
mod jobs; mod jobs;
mod middleware;
mod node; mod node;
mod nodeinfo;
mod notify; mod notify;
mod rehydrate;
mod requests; mod requests;
mod responses; mod routes;
mod state; mod state;
mod verifier;
mod webfinger;
use self::{ use self::{
args::Args, args::Args,
config::Config, config::Config,
db::Db, db::Db,
error::MyError,
jobs::{create_server, create_workers}, jobs::{create_server, create_workers},
middleware::RelayResolver,
routes::{actor, inbox, index, nodeinfo, nodeinfo_meta, statics},
state::State, state::State,
templates::statics::StaticFile,
webfinger::RelayResolver,
}; };
async fn index(
state: web::Data<State>,
config: web::Data<Config>,
) -> Result<HttpResponse, MyError> {
let nodes = state.node_cache().nodes().await;
let mut buf = BufWriter::new(Vec::new());
templates::index(&mut buf, &nodes, &config)?;
let buf = buf.into_inner().map_err(|e| {
error!("Error rendering template, {}", e.error());
MyError::FlushBuffer
})?;
Ok(HttpResponse::Ok().content_type("text/html").body(buf))
}
static FAR: Duration = Duration::from_secs(60 * 60 * 24);
async fn static_file(filename: web::Path<String>) -> HttpResponse {
if let Some(data) = StaticFile::get(&filename.into_inner()) {
let far_expires = SystemTime::now() + FAR;
HttpResponse::Ok()
.set(Expires(far_expires.into()))
.set(ContentType(data.mime.clone()))
.body(data.content)
} else {
HttpResponse::NotFound()
.reason("No such static file.")
.finish()
}
}
#[actix_rt::main] #[actix_rt::main]
async fn main() -> Result<(), anyhow::Error> { async fn main() -> Result<(), anyhow::Error> {
dotenv::dotenv().ok(); dotenv::dotenv().ok();
@ -114,7 +66,6 @@ async fn main() -> Result<(), anyhow::Error> {
let state = State::hydrate(config.clone(), &db).await?; let state = State::hydrate(config.clone(), &db).await?;
let job_server = create_server(db.clone()); let job_server = create_server(db.clone());
rehydrate::spawn(db.clone(), state.clone());
notify::spawn(state.clone(), job_server.clone(), &config)?; notify::spawn(state.clone(), job_server.clone(), &config)?;
if args.jobs_only() { if args.jobs_only() {
@ -150,16 +101,16 @@ async fn main() -> Result<(), anyhow::Error> {
web::resource("/inbox") web::resource("/inbox")
.wrap(config.digest_middleware()) .wrap(config.digest_middleware())
.wrap(config.signature_middleware(state.requests())) .wrap(config.signature_middleware(state.requests()))
.route(web::post().to(inbox::inbox)), .route(web::post().to(inbox)),
) )
.service(web::resource("/actor").route(web::get().to(actor::route))) .service(web::resource("/actor").route(web::get().to(actor)))
.service(web::resource("/nodeinfo/2.0.json").route(web::get().to(nodeinfo::route))) .service(web::resource("/nodeinfo/2.0.json").route(web::get().to(nodeinfo)))
.service( .service(
web::scope("/.well-known") web::scope("/.well-known")
.service(actix_webfinger::scoped::<_, RelayResolver>()) .service(actix_webfinger::scoped::<_, RelayResolver>())
.service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))), .service(web::resource("/nodeinfo").route(web::get().to(nodeinfo_meta))),
) )
.service(web::resource("/static/{filename}").route(web::get().to(static_file))) .service(web::resource("/static/{filename}").route(web::get().to(statics)))
}) })
.bind(bind_address)? .bind(bind_address)?
.run() .run()

5
src/middleware/mod.rs Normal file
View file

@ -0,0 +1,5 @@
mod verifier;
mod webfinger;
pub use verifier::MyVerify;
pub use webfinger::RelayResolver;

View file

@ -1,24 +0,0 @@
use crate::{db::Db, state::State};
use actix::{
clock::{interval_at, Duration, Instant},
Arbiter,
};
use log::error;
pub fn spawn(db: Db, state: State) {
Arbiter::spawn(async move {
let start = Instant::now();
let duration = Duration::from_secs(60 * 10);
let mut interval = interval_at(start, duration);
loop {
interval.tick().await;
match state.rehydrate(&db).await {
Err(e) => error!("Error rehydrating, {}", e),
_ => (),
}
}
});
}

View file

@ -1,20 +0,0 @@
use actix_web::HttpResponse;
use serde::ser::Serialize;
static CONTENT_TYPE: &str = "application/activity+json";
pub fn ok<T>(item: T) -> HttpResponse
where
T: Serialize,
{
HttpResponse::Ok().content_type(CONTENT_TYPE).json(item)
}
pub fn accepted<T>(item: T) -> HttpResponse
where
T: Serialize,
{
HttpResponse::Accepted()
.content_type(CONTENT_TYPE)
.json(item)
}

View file

@ -2,7 +2,7 @@ use crate::{
apub::PublicKey, apub::PublicKey,
config::{Config, UrlKind}, config::{Config, UrlKind},
error::MyError, error::MyError,
responses::ok, routes::ok,
state::State, state::State,
}; };
use activitystreams::{ use activitystreams::{

View file

@ -6,7 +6,7 @@ use crate::{
jobs::JobServer, jobs::JobServer,
jobs::{Deliver, DeliverMany}, jobs::{Deliver, DeliverMany},
requests::Requests, requests::Requests,
responses::accepted, routes::accepted,
state::State, state::State,
}; };
use activitystreams::{ use activitystreams::{
@ -22,7 +22,7 @@ use http_signature_normalization_actix::prelude::{DigestVerified, SignatureVerif
use log::error; use log::error;
use std::convert::TryInto; use std::convert::TryInto;
pub async fn inbox( pub async fn route(
db: web::Data<Db>, db: web::Data<Db>,
state: web::Data<State>, state: web::Data<State>,
config: web::Data<Config>, config: web::Data<Config>,

21
src/routes/index.rs Normal file
View file

@ -0,0 +1,21 @@
use crate::{config::Config, error::MyError, state::State};
use actix_web::{web, HttpResponse};
use log::error;
use std::io::BufWriter;
pub async fn route(
state: web::Data<State>,
config: web::Data<Config>,
) -> Result<HttpResponse, MyError> {
let nodes = state.node_cache().nodes().await;
let mut buf = BufWriter::new(Vec::new());
crate::templates::index(&mut buf, &nodes, &config)?;
let buf = buf.into_inner().map_err(|e| {
error!("Error rendering template, {}", e.error());
MyError::FlushBuffer
})?;
Ok(HttpResponse::Ok().content_type("text/html").body(buf))
}

34
src/routes/mod.rs Normal file
View file

@ -0,0 +1,34 @@
mod actor;
mod inbox;
mod index;
mod nodeinfo;
mod statics;
pub use self::{
actor::route as actor,
inbox::route as inbox,
index::route as index,
nodeinfo::{route as nodeinfo, well_known as nodeinfo_meta},
statics::route as statics,
};
use actix_web::HttpResponse;
use serde::ser::Serialize;
static CONTENT_TYPE: &str = "application/activity+json";
fn ok<T>(item: T) -> HttpResponse
where
T: Serialize,
{
HttpResponse::Ok().content_type(CONTENT_TYPE).json(item)
}
fn accepted<T>(item: T) -> HttpResponse
where
T: Serialize,
{
HttpResponse::Accepted()
.content_type(CONTENT_TYPE)
.json(item)
}

22
src/routes/statics.rs Normal file
View file

@ -0,0 +1,22 @@
use crate::templates::statics::StaticFile;
use actix_web::{
http::header::{ContentType, Expires},
web, HttpResponse,
};
use std::time::{Duration, SystemTime};
static FAR: Duration = Duration::from_secs(60 * 60 * 24);
pub async fn route(filename: web::Path<String>) -> HttpResponse {
if let Some(data) = StaticFile::get(&filename.into_inner()) {
let far_expires = SystemTime::now() + FAR;
HttpResponse::Ok()
.set(Expires(far_expires.into()))
.set(ContentType(data.mime.clone()))
.body(data.content)
} else {
HttpResponse::NotFound()
.reason("No such static file.")
.finish()
}
}

View file

@ -7,9 +7,10 @@ use crate::{
requests::Requests, requests::Requests,
}; };
use activitystreams::primitives::XsdAnyUri; use activitystreams::primitives::XsdAnyUri;
use actix::clock::{interval_at, Duration, Instant};
use actix_web::web; use actix_web::web;
use futures::{join, try_join}; use futures::{join, try_join};
use log::info; use log::{error, info};
use lru::LruCache; use lru::LruCache;
use rand::thread_rng; use rand::thread_rng;
use rsa::{RSAPrivateKey, RSAPublicKey}; use rsa::{RSAPrivateKey, RSAPublicKey};
@ -199,7 +200,7 @@ impl State {
let public_key = private_key.to_public_key(); let public_key = private_key.to_public_key();
let listeners = Arc::new(RwLock::new(listeners)); let listeners = Arc::new(RwLock::new(listeners));
Ok(State { let state = State {
public_key, public_key,
private_key, private_key,
config, config,
@ -209,6 +210,29 @@ impl State {
whitelists: Arc::new(RwLock::new(whitelists)), whitelists: Arc::new(RwLock::new(whitelists)),
listeners: listeners.clone(), listeners: listeners.clone(),
node_cache: NodeCache::new(listeners), node_cache: NodeCache::new(listeners),
}) };
state.spawn_rehydrate(db.clone());
Ok(state)
}
fn spawn_rehydrate(&self, db: Db) {
let state = self.clone();
actix::spawn(async move {
let start = Instant::now();
let duration = Duration::from_secs(60 * 10);
let mut interval = interval_at(start, duration);
loop {
interval.tick().await;
match state.rehydrate(&db).await {
Err(e) => error!("Error rehydrating, {}", e),
_ => (),
}
}
});
} }
} }