2021-04-09 00:22:17 +00:00
|
|
|
use actix_cors::Cors;
|
|
|
|
use actix_web::{
|
2022-08-06 19:11:08 +00:00
|
|
|
http::header,
|
2021-04-09 00:22:17 +00:00
|
|
|
web,
|
|
|
|
App, HttpServer,
|
2022-06-02 20:00:56 +00:00
|
|
|
dev::Service,
|
2021-04-09 00:22:17 +00:00
|
|
|
middleware::Logger as ActixLogger,
|
|
|
|
};
|
2022-05-04 23:13:57 +00:00
|
|
|
use tokio::sync::Mutex;
|
2021-04-09 00:22:17 +00:00
|
|
|
|
2021-11-18 00:51:56 +00:00
|
|
|
use mitra::activitypub::views as activitypub;
|
2022-04-13 17:45:47 +00:00
|
|
|
use mitra::atom::views as atom;
|
2021-04-09 00:22:17 +00:00
|
|
|
use mitra::config::{Environment, parse_config};
|
2022-01-05 22:52:17 +00:00
|
|
|
use mitra::database::{get_database_client, create_pool};
|
2021-04-09 00:22:17 +00:00
|
|
|
use mitra::database::migrate::apply_migrations;
|
2022-06-14 10:29:14 +00:00
|
|
|
use mitra::ethereum::contracts::get_contracts;
|
2021-04-09 00:22:17 +00:00
|
|
|
use mitra::logger::configure_logger;
|
|
|
|
use mitra::mastodon_api::accounts::views::account_api_scope;
|
2021-11-07 08:52:57 +00:00
|
|
|
use mitra::mastodon_api::directory::views::directory_api_scope;
|
|
|
|
use mitra::mastodon_api::instance::views::instance_api_scope;
|
2021-11-03 12:03:56 +00:00
|
|
|
use mitra::mastodon_api::markers::views::marker_api_scope;
|
2021-04-09 00:22:17 +00:00
|
|
|
use mitra::mastodon_api::media::views::media_api_scope;
|
2021-10-12 16:11:47 +00:00
|
|
|
use mitra::mastodon_api::notifications::views::notification_api_scope;
|
2021-10-01 00:35:52 +00:00
|
|
|
use mitra::mastodon_api::oauth::auth::create_auth_error_handler;
|
|
|
|
use mitra::mastodon_api::oauth::views::oauth_api_scope;
|
2021-11-07 08:52:57 +00:00
|
|
|
use mitra::mastodon_api::search::views::search_api_scope;
|
2021-04-09 00:22:17 +00:00
|
|
|
use mitra::mastodon_api::statuses::views::status_api_scope;
|
2021-11-07 08:52:57 +00:00
|
|
|
use mitra::mastodon_api::timelines::views::timeline_api_scope;
|
2021-04-09 00:22:17 +00:00
|
|
|
use mitra::nodeinfo::views as nodeinfo;
|
|
|
|
use mitra::scheduler;
|
|
|
|
use mitra::webfinger::views as webfinger;
|
|
|
|
|
|
|
|
const MAX_UPLOAD_SIZE: usize = 1024 * 1024 * 10;
|
|
|
|
|
|
|
|
#[actix_web::main]
|
|
|
|
async fn main() -> std::io::Result<()> {
|
|
|
|
let config = parse_config();
|
2021-12-21 00:14:12 +00:00
|
|
|
configure_logger(config.log_level);
|
2022-05-04 19:44:38 +00:00
|
|
|
log::info!("config loaded from {}", config.config_path);
|
2022-06-14 10:29:14 +00:00
|
|
|
|
2021-04-09 00:22:17 +00:00
|
|
|
let db_pool = create_pool(&config.database_url);
|
2022-02-23 21:33:56 +00:00
|
|
|
let mut db_client = get_database_client(&db_pool).await.unwrap();
|
|
|
|
apply_migrations(&mut **db_client).await;
|
|
|
|
std::mem::drop(db_client);
|
2021-11-06 12:14:22 +00:00
|
|
|
if !config.media_dir().exists() {
|
|
|
|
std::fs::create_dir(config.media_dir())
|
2022-02-23 21:33:56 +00:00
|
|
|
.expect("failed to create media directory");
|
|
|
|
};
|
2021-04-09 00:22:17 +00:00
|
|
|
log::info!(
|
2021-11-13 17:49:04 +00:00
|
|
|
"app initialized; version {}, environment = '{:?}'",
|
|
|
|
config.version,
|
2021-04-09 00:22:17 +00:00
|
|
|
config.environment,
|
|
|
|
);
|
|
|
|
|
2022-06-23 20:48:05 +00:00
|
|
|
let maybe_blockchain = if let Some(blockchain_config) = &config.blockchain {
|
2022-06-14 10:29:14 +00:00
|
|
|
// Create blockchain interface
|
2022-06-14 18:55:04 +00:00
|
|
|
get_contracts(blockchain_config, &config.storage_dir).await
|
2022-06-23 20:48:05 +00:00
|
|
|
.map(Some).unwrap()
|
2022-06-14 10:29:14 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2022-06-24 23:27:09 +00:00
|
|
|
let maybe_contract_set = maybe_blockchain.clone()
|
|
|
|
.map(|blockchain| blockchain.contract_set);
|
2022-06-14 10:29:14 +00:00
|
|
|
|
2022-06-24 23:27:09 +00:00
|
|
|
scheduler::run(config.clone(), maybe_blockchain, db_pool.clone());
|
2021-04-09 00:22:17 +00:00
|
|
|
log::info!("scheduler started");
|
|
|
|
|
|
|
|
let http_socket_addr = format!(
|
|
|
|
"{}:{}",
|
|
|
|
config.http_host,
|
|
|
|
config.http_port,
|
|
|
|
);
|
|
|
|
let num_workers = std::cmp::max(num_cpus::get(), 4);
|
2022-05-04 23:13:57 +00:00
|
|
|
// Mutex is used to make server process incoming activities sequentially
|
|
|
|
let inbox_mutex = web::Data::new(Mutex::new(()));
|
|
|
|
|
2021-04-09 00:22:17 +00:00
|
|
|
HttpServer::new(move || {
|
|
|
|
let cors_config = match config.environment {
|
|
|
|
Environment::Development => {
|
|
|
|
Cors::permissive()
|
|
|
|
},
|
|
|
|
Environment::Production => {
|
2022-02-10 23:34:58 +00:00
|
|
|
let mut cors_config = Cors::default();
|
|
|
|
for origin in config.http_cors_allowlist.iter() {
|
2022-02-11 20:44:23 +00:00
|
|
|
cors_config = cors_config.allowed_origin(origin);
|
2022-02-10 23:34:58 +00:00
|
|
|
};
|
|
|
|
cors_config
|
|
|
|
.allowed_origin(&config.instance_url())
|
2022-02-08 13:16:38 +00:00
|
|
|
.allowed_origin_fn(|origin, _req_head| {
|
|
|
|
origin.as_bytes().starts_with(b"http://localhost:")
|
|
|
|
})
|
2021-04-09 00:22:17 +00:00
|
|
|
.allow_any_method()
|
|
|
|
.allow_any_header()
|
|
|
|
},
|
|
|
|
};
|
2022-08-06 19:11:08 +00:00
|
|
|
let cors_config = cors_config
|
|
|
|
// Link header needs to be explicitly exposed
|
|
|
|
// because expose_any_header doesn't work
|
|
|
|
// https://github.com/actix/actix-extras/issues/192
|
|
|
|
.expose_headers(vec![header::LINK]);
|
2021-11-05 23:41:30 +00:00
|
|
|
let mut app = App::new()
|
2021-04-09 00:22:17 +00:00
|
|
|
.wrap(cors_config)
|
2022-06-02 20:00:56 +00:00
|
|
|
.wrap(ActixLogger::new("%r : %s : %{r}a"))
|
|
|
|
.wrap_fn(|req, srv| {
|
|
|
|
// Always log server errors (500-599)
|
|
|
|
let fut = srv.call(req);
|
|
|
|
async {
|
|
|
|
let res = fut.await?;
|
|
|
|
if let Some(error) = res.response().error() {
|
|
|
|
if error.as_response_error().status_code().is_server_error() {
|
|
|
|
log::warn!(
|
|
|
|
"{} {} : {}",
|
|
|
|
res.request().method(),
|
|
|
|
res.request().path(),
|
|
|
|
error,
|
|
|
|
);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
})
|
2021-10-01 00:35:52 +00:00
|
|
|
.wrap(create_auth_error_handler())
|
2022-04-08 18:52:13 +00:00
|
|
|
.app_data(web::PayloadConfig::default().limit(MAX_UPLOAD_SIZE))
|
|
|
|
.app_data(web::JsonConfig::default().limit(MAX_UPLOAD_SIZE))
|
|
|
|
.app_data(web::Data::new(config.clone()))
|
|
|
|
.app_data(web::Data::new(db_pool.clone()))
|
2022-06-24 23:27:09 +00:00
|
|
|
.app_data(web::Data::new(maybe_contract_set.clone()))
|
2022-05-04 23:13:57 +00:00
|
|
|
.app_data(web::Data::clone(&inbox_mutex))
|
2021-04-09 00:22:17 +00:00
|
|
|
.service(actix_files::Files::new(
|
|
|
|
"/media",
|
|
|
|
config.media_dir(),
|
|
|
|
))
|
2021-10-01 00:35:52 +00:00
|
|
|
.service(oauth_api_scope())
|
2021-04-09 00:22:17 +00:00
|
|
|
.service(account_api_scope())
|
2021-11-07 08:52:57 +00:00
|
|
|
.service(directory_api_scope())
|
|
|
|
.service(instance_api_scope())
|
2021-11-03 12:03:56 +00:00
|
|
|
.service(marker_api_scope())
|
2021-04-09 00:22:17 +00:00
|
|
|
.service(media_api_scope())
|
2021-10-12 16:11:47 +00:00
|
|
|
.service(notification_api_scope())
|
2021-04-09 00:22:17 +00:00
|
|
|
.service(status_api_scope())
|
2021-11-07 08:52:57 +00:00
|
|
|
.service(search_api_scope())
|
|
|
|
.service(timeline_api_scope())
|
2021-04-09 00:22:17 +00:00
|
|
|
.service(webfinger::get_descriptor)
|
2021-11-18 00:51:56 +00:00
|
|
|
.service(activitypub::actor_scope())
|
2021-11-20 21:07:03 +00:00
|
|
|
.service(activitypub::instance_actor_scope())
|
2021-11-18 00:51:56 +00:00
|
|
|
.service(activitypub::object_view)
|
2022-04-13 17:45:47 +00:00
|
|
|
.service(atom::get_atom_feed)
|
2021-04-09 00:22:17 +00:00
|
|
|
.service(nodeinfo::get_nodeinfo)
|
2021-11-05 23:41:30 +00:00
|
|
|
.service(nodeinfo::get_nodeinfo_2_0);
|
2022-01-25 22:17:28 +00:00
|
|
|
if let Some(blockchain_config) = &config.blockchain {
|
2021-11-05 23:41:30 +00:00
|
|
|
// Serve artifacts if available
|
|
|
|
app = app.service(actix_files::Files::new(
|
|
|
|
"/contracts",
|
2022-01-25 22:17:28 +00:00
|
|
|
&blockchain_config.contract_dir,
|
2021-11-05 23:41:30 +00:00
|
|
|
));
|
|
|
|
}
|
|
|
|
app
|
2021-04-09 00:22:17 +00:00
|
|
|
})
|
|
|
|
.workers(num_workers)
|
|
|
|
.bind(http_socket_addr)?
|
|
|
|
.run()
|
|
|
|
.await
|
|
|
|
}
|