use actix_web::{client::Client, http::header::HeaderName, middleware, web, App, HttpServer};
use limitation_actix_middleware::{Limiter, RateLimiter};
use std::error;
use std::net::SocketAddr;
use std::time::Duration;
use typed_builder::TypedBuilder;
use url::Url;
mod handlers;
pub type Error = Box<dyn error::Error>;
#[derive(Clone, Debug, TypedBuilder)]
pub struct Config {
pub(crate) bind_addr: SocketAddr,
pub(crate) redis_url: Url,
pub(crate) proxy_to: Url,
pub(crate) header: HeaderName,
pub(crate) rate_limit: usize,
pub(crate) rate_period: Duration,
}
pub fn run(config: Config) -> Result<(), Error> {
let sys = actix_rt::System::new(env!("CARGO_PKG_NAME"));
start_server(config)?;
Ok(sys.run()?)
}
fn start_server(config: Config) -> Result<(), Error> {
let addr = config.bind_addr;
let proxy_to = web::Data::new(config.proxy_to);
let limiter = web::Data::new(
Limiter::build(config.redis_url.as_str())
.limit(config.rate_limit)
.period(config.rate_period)
.finish()?,
);
let header = web::Data::new(config.header);
HttpServer::new(move || {
App::new()
.register_data(limiter.clone())
.register_data(proxy_to.clone())
.register_data(header.clone())
.data(Client::new())
.wrap(RateLimiter)
.wrap(middleware::Logger::default())
.default_service(web::route().to_async(handlers::forward))
})
.bind(addr)?
.start();
Ok(())
}