relay/src/main.rs

171 lines
4.5 KiB
Rust
Raw Normal View History

2020-03-23 00:07:36 +00:00
use actix::Arbiter;
2020-03-20 18:40:18 +00:00
use actix_web::{
http::header::{ContentType, Expires},
middleware::Logger,
web, App, HttpResponse, HttpServer,
};
use log::error;
use std::{
io::BufWriter,
time::{Duration, SystemTime},
};
2020-03-15 02:05:40 +00:00
mod actor;
2020-03-15 02:05:40 +00:00
mod apub;
mod args;
mod config;
mod db;
2020-03-16 03:36:46 +00:00
mod error;
2020-03-15 02:05:40 +00:00
mod inbox;
mod jobs;
2020-03-19 19:05:16 +00:00
mod nodeinfo;
mod notify;
mod rehydrate;
mod requests;
mod responses;
2020-03-15 02:05:40 +00:00
mod state;
2020-03-16 04:15:50 +00:00
mod verifier;
2020-03-16 03:36:46 +00:00
mod webfinger;
2020-03-15 02:05:40 +00:00
2020-03-20 18:40:18 +00:00
use self::{
args::Args,
config::Config,
db::Db,
error::MyError,
jobs::{create_server, create_workers},
state::State,
templates::statics::StaticFile,
webfinger::RelayResolver,
2020-03-20 18:40:18 +00:00
};
2020-03-20 04:06:16 +00:00
2020-03-20 18:40:18 +00:00
async fn index(
state: web::Data<State>,
config: web::Data<Config>,
) -> Result<HttpResponse, MyError> {
2020-03-20 04:06:16 +00:00
let listeners = state.listeners().await;
2020-03-20 18:40:18 +00:00
let mut buf = BufWriter::new(Vec::new());
templates::index(&mut buf, &listeners, &config)?;
let buf = buf.into_inner().map_err(|e| {
error!("Error rendering template, {}", e.error());
MyError::FlushBuffer
})?;
2020-03-20 04:06:16 +00:00
2020-03-20 18:40:18 +00:00
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()
}
2020-03-15 02:05:40 +00:00
}
#[actix_rt::main]
async fn main() -> Result<(), anyhow::Error> {
dotenv::dotenv().ok();
let config = Config::build()?;
2020-03-15 22:37:53 +00:00
if config.debug() {
2020-03-22 21:18:36 +00:00
std::env::set_var("RUST_LOG", "debug,tokio_postgres=info")
} else {
std::env::set_var("RUST_LOG", "info")
}
if config.pretty_log() {
pretty_env_logger::init();
} else {
env_logger::init();
}
2020-03-22 23:21:40 +00:00
let db = Db::build(&config).await?;
2020-03-15 02:05:40 +00:00
let args = Args::new();
2020-03-23 00:07:36 +00:00
if args.jobs_only() && args.no_jobs() {
return Err(anyhow::Error::msg(
"Either the server or the jobs must be run",
));
}
if !args.blocks().is_empty() || !args.whitelists().is_empty() {
if args.undo() {
db.remove_blocks(args.blocks()).await?;
db.remove_whitelists(args.whitelists()).await?;
} else {
db.add_blocks(args.blocks()).await?;
db.add_whitelists(args.whitelists()).await?;
}
return Ok(());
}
let state = State::hydrate(config.clone(), &db).await?;
2020-03-15 02:05:40 +00:00
rehydrate::spawn(db.clone(), state.clone());
2020-03-22 23:21:40 +00:00
notify::spawn(state.clone(), &config)?;
2020-03-22 21:18:36 +00:00
let job_server = create_server(db.clone());
2020-03-23 00:07:36 +00:00
if args.jobs_only() {
for _ in 0..num_cpus::get() {
let state = state.clone();
let job_server = job_server.clone();
Arbiter::new().exec_fn(move || {
create_workers(state, job_server);
});
}
actix_rt::signal::ctrl_c().await?;
return Ok(());
}
let no_jobs = args.no_jobs();
let bind_address = config.bind_address();
2020-03-15 02:05:40 +00:00
HttpServer::new(move || {
2020-03-23 00:07:36 +00:00
if !no_jobs {
create_workers(state.clone(), job_server.clone());
}
2020-03-15 02:05:40 +00:00
App::new()
2020-03-15 22:37:53 +00:00
.wrap(Logger::default())
2020-03-19 22:19:05 +00:00
.data(db.clone())
2020-03-15 02:05:40 +00:00
.data(state.clone())
2020-03-18 04:35:20 +00:00
.data(state.requests())
.data(config.clone())
.data(job_server.clone())
2020-03-15 02:05:40 +00:00
.service(web::resource("/").route(web::get().to(index)))
.service(
web::resource("/inbox")
.wrap(config.digest_middleware())
.wrap(config.signature_middleware(state.requests()))
.route(web::post().to(inbox::inbox)),
)
.service(web::resource("/actor").route(web::get().to(actor::route)))
2020-03-20 20:35:08 +00:00
.service(web::resource("/nodeinfo/2.0.json").route(web::get().to(nodeinfo::route)))
2020-03-19 19:05:16 +00:00
.service(
web::scope("/.well-known")
.service(actix_webfinger::scoped::<_, RelayResolver>())
.service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))),
)
2020-03-20 18:40:18 +00:00
.service(web::resource("/static/{filename}").route(web::get().to(static_file)))
2020-03-15 02:05:40 +00:00
})
.bind(bind_address)?
2020-03-15 02:05:40 +00:00
.run()
.await?;
Ok(())
}
2020-03-20 18:40:18 +00:00
include!(concat!(env!("OUT_DIR"), "/templates.rs"));