mod cleartext;
mod mimetypes;
mod router;
mod services;
mod r#static;
#[cfg(test)]
mod tests;
use std::sync::Arc;
use anyhow::Result;
use async_trait::async_trait;
use http::StatusCode;
use pingora_core::{
ErrorType, listeners::tls::TlsSettings, server::Server as PingoraServer,
services::listening::Service,
};
use pingora_proxy::Session;
use tracing::info;
use crate::{
certificates::{
CertificateRuntime,
handler::{CertHandler, NoopCallbackHandler},
},
config::ProxyBackend,
RunContext,
proxy::{
cleartext::CleartextHandler,
services::Vicarian,
},
};
pub const E401: pingora_core::ErrorType = ErrorType::HTTPStatus(StatusCode::UNAUTHORIZED.as_u16());
pub const E404: pingora_core::ErrorType = ErrorType::HTTPStatus(StatusCode::NOT_FOUND.as_u16());
pub const E500: pingora_core::ErrorType = ErrorType::HTTPStatus(StatusCode::INTERNAL_SERVER_ERROR.as_u16());
pub const YEAR_IN_SECS: u64 = 31536000;
#[async_trait]
pub trait BackendHandler: Send + Sync {
async fn handle(&self, session: &mut Session) -> Result<bool>;
}
struct ProxyHandler;
impl ProxyHandler {
fn new(_backend: &ProxyBackend) -> Self {
ProxyHandler
}
}
#[async_trait]
impl BackendHandler for ProxyHandler {
async fn handle(&self, _session: &mut Session) -> Result<bool> {
Ok(false)
}
}
pub fn run_indefinitely(cert_runtime: Arc<CertificateRuntime>, context: Arc<RunContext>) -> Result<()> {
info!("Starting Proxy");
let mut pingora_server = PingoraServer::new(None)?;
pingora_server.bootstrap();
let vicarian_service = {
let vicarian = Vicarian::new(cert_runtime.certstore().clone(), context.clone());
let mut pingora_proxy = pingora_proxy::http_proxy_service(
&pingora_server.configuration,
vicarian);
for addr in &context.config.listen.addrs {
let cert_handler = CertHandler::new(cert_runtime.certstore().clone());
let dummy_callbacks = NoopCallbackHandler {};
let mut tls_settings = TlsSettings::with_callbacks(Box::new(dummy_callbacks))?;
tls_settings.enable_h2();
tls_settings.set_cert_resolver(Arc::new(cert_handler));
let mut addr_port = *addr;
addr_port.set_port(context.config.listen.tls_port);
let addr_port = addr_port.to_string();
info!("Binding to {addr_port}");
pingora_proxy.add_tls_with_settings(&addr_port, None, tls_settings);
}
pingora_proxy
};
pingora_server.add_service(vicarian_service);
let redirector = CleartextHandler::new(cert_runtime.acme().clone(), context.config.listen.tls_port);
let mut cleartext_service = Service::new("HTTP->HTTPS Redirector".to_string(), redirector);
for addr in &context.config.listen.addrs {
let mut addr_port = *addr;
addr_port.set_port(context.config.listen.insecure_port);
let addr_port = addr_port.to_string();
info!("Binding to {addr_port}");
cleartext_service.add_tcp(&addr_port);
}
pingora_server.add_service(cleartext_service);
pingora_server.run(pingora_core::server::RunArgs::default());
Ok(())
}