forked from mirrors/relay
Do a bit of reorganizing
This commit is contained in:
parent
f44df38ea1
commit
9925e41673
14 changed files with 123 additions and 110 deletions
|
@ -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};
|
||||||
|
|
69
src/main.rs
69
src/main.rs
|
@ -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
5
src/middleware/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
mod verifier;
|
||||||
|
mod webfinger;
|
||||||
|
|
||||||
|
pub use verifier::MyVerify;
|
||||||
|
pub use webfinger::RelayResolver;
|
|
@ -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),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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::{
|
|
@ -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
21
src/routes/index.rs
Normal 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
34
src/routes/mod.rs
Normal 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
22
src/routes/statics.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
30
src/state.rs
30
src/state.rs
|
@ -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),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue