148 lines
4.8 KiB
Rust
148 lines
4.8 KiB
Rust
mod auth;
|
|
mod endpoints;
|
|
mod error;
|
|
mod middleware;
|
|
mod user;
|
|
mod validate;
|
|
|
|
use std::env;
|
|
|
|
use actix_web::{
|
|
App, HttpServer,
|
|
middleware::from_fn,
|
|
rt::System,
|
|
web::{self},
|
|
};
|
|
use aws_config::BehaviorVersion;
|
|
use sqlx::PgPool;
|
|
use tracing::level_filters::LevelFilter;
|
|
use tracing_subscriber::{
|
|
EnvFilter, fmt::format::FmtSpan, layer::SubscriberExt, util::SubscriberInitExt,
|
|
};
|
|
|
|
use crate::{
|
|
auth::{Auth, JWT},
|
|
user::UserRepository,
|
|
};
|
|
|
|
struct AppState {
|
|
reqwest_client: reqwest::Client,
|
|
auth: Auth,
|
|
user: UserRepository,
|
|
}
|
|
|
|
async fn run() -> std::io::Result<()> {
|
|
let reqwest_client = reqwest::Client::builder()
|
|
.user_agent(concat!(
|
|
env!("CARGO_PKG_NAME"),
|
|
"/",
|
|
env!("CARGO_PKG_VERSION")
|
|
))
|
|
.build()
|
|
.expect("failed to create reqwest client");
|
|
let config = aws_config::load_defaults(BehaviorVersion::v2026_01_12()).await;
|
|
let dynamodb_client = aws_sdk_dynamodb::Client::new(&config);
|
|
|
|
let app_data = web::Data::new(AppState {
|
|
reqwest_client: reqwest_client.clone(),
|
|
auth: Auth::JWT(JWT::new(reqwest_client.clone())),
|
|
user: UserRepository::new(
|
|
PgPool::connect(
|
|
&env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"),
|
|
)
|
|
.await
|
|
.expect("error connecting to db"),
|
|
dynamodb_client,
|
|
),
|
|
});
|
|
|
|
HttpServer::new(move || {
|
|
App::new()
|
|
.app_data(app_data.clone())
|
|
.wrap(
|
|
sentry::integrations::actix::Sentry::builder()
|
|
.capture_server_errors(true)
|
|
.start_transaction(true)
|
|
.finish(),
|
|
)
|
|
.wrap(tracing_actix_web::TracingLogger::default())
|
|
.wrap(actix_cors::Cors::permissive())
|
|
.route(
|
|
"/",
|
|
web::get()
|
|
.to(async || concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"))),
|
|
)
|
|
.service(
|
|
web::scope("/api").service(
|
|
web::scope("/v0")
|
|
.service(
|
|
web::scope("/user")
|
|
.route("/repos", web::get().to(endpoints::get_repos::get_repos))
|
|
.wrap(from_fn(middleware::protected))
|
|
.route(
|
|
"/repos/search",
|
|
web::get().to(endpoints::search_repos::search_repos),
|
|
)
|
|
.wrap(from_fn(middleware::protected))
|
|
.route("/repo/add", web::post().to(endpoints::add_repo::add_repo))
|
|
.wrap(from_fn(middleware::protected)),
|
|
)
|
|
.route(
|
|
"/repos",
|
|
web::get().to(endpoints::global_repos::global_repos),
|
|
)
|
|
.route(
|
|
"/repos/{repo_id}/files/{file:.*}",
|
|
web::get().to(endpoints::proxy_file::proxy_file),
|
|
),
|
|
),
|
|
)
|
|
})
|
|
.bind((env::var("ADDRESS").unwrap_or("0.0.0.0".to_string()), 8080))?
|
|
.run()
|
|
.await
|
|
}
|
|
|
|
// cant use #[actix_web::main] because of Sentry
|
|
// Note: "Macros like #[tokio::main] and #[actix_web::main] are not supported. The Sentry client must be initialized before the async runtime is started."
|
|
// https://docs.sentry.io/platforms/rust/guides/actix-web/
|
|
fn main() -> std::io::Result<()> {
|
|
let tracing_env_filter = EnvFilter::builder()
|
|
.with_default_directive(LevelFilter::INFO.into())
|
|
.from_env_lossy()
|
|
.add_directive("reqwest=info".parse().unwrap())
|
|
.add_directive("hyper=info".parse().unwrap())
|
|
.add_directive("h2=info".parse().unwrap())
|
|
.add_directive("rustls=info".parse().unwrap())
|
|
.add_directive("aws=info".parse().unwrap());
|
|
|
|
tracing_subscriber::registry()
|
|
.with(tracing_env_filter)
|
|
.with(
|
|
tracing_subscriber::fmt::layer()
|
|
.compact()
|
|
.with_span_events(FmtSpan::CLOSE),
|
|
)
|
|
.with(sentry::integrations::tracing::layer())
|
|
.init();
|
|
|
|
let guard = sentry::init((
|
|
env::var("SENTRY_DSN").ok(),
|
|
sentry::ClientOptions {
|
|
release: sentry::release_name!(),
|
|
traces_sample_rate: 1.0,
|
|
session_mode: sentry::SessionMode::Request,
|
|
debug: true,
|
|
..Default::default()
|
|
},
|
|
));
|
|
|
|
if guard.is_enabled() {
|
|
tracing::info!("sentry initialized");
|
|
} else {
|
|
tracing::info!("sentry **NOT** initialized")
|
|
};
|
|
|
|
System::new().block_on(run())
|
|
}
|