feat(proxy): implement Nginx configuration handling and rendering logic
This commit is contained in:
@@ -6,7 +6,12 @@ pub(crate) mod repo;
|
|||||||
pub mod service;
|
pub mod service;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
#[cfg_attr(test, mockall::automock)]
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait ProxyServiceTrait: Send + Sync + 'static {
|
pub trait ProxyServiceTrait: Send + Sync + 'static {
|
||||||
async fn get_proxy_config(&self, proxy_id: uuid::Uuid) -> ProxyServiceResult<ProxyConfig>;
|
async fn get_proxy_config(&self, proxy_id: uuid::Uuid) -> ProxyServiceResult<ProxyConfig>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ProxyConfigRenderer: Send + Sync + 'static {
|
||||||
|
fn render(&self, config: &ProxyConfig) -> String;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::db::entities::access_rule::Model as AccessRule;
|
use crate::service::proxy::types::AccessRuleConfig;
|
||||||
|
|
||||||
impl std::fmt::Display for AccessRule {
|
impl std::fmt::Display for AccessRuleConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{} {};", self.r#type.clone(), self.ip_cidr.clone())
|
write!(f, "{} {};", self.r#type, self.ip_cidr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use crate::db::entities::cache_zone::Model as CacheZone;
|
use crate::service::proxy::types::CacheZoneConfig;
|
||||||
|
|
||||||
impl std::fmt::Display for CacheZone {
|
impl std::fmt::Display for CacheZoneConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"proxy_cache_path {} levels=1:2 keys_zone={}:{};",
|
"proxy_cache_path {} levels=1:2 keys_zone={}:{};",
|
||||||
self.path, self.name, self.size_limit
|
self.path, self.name, self.size
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use crate::db::entities::limit_rule::Model as LimitRule;
|
use crate::service::proxy::types::LimitRuleConfig;
|
||||||
|
|
||||||
pub struct LimitRuleRender {
|
pub struct LimitRuleRender<'a> {
|
||||||
pub rule: LimitRule,
|
pub rule: &'a LimitRuleConfig,
|
||||||
pub zone_name: String,
|
pub zone_name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for LimitRuleRender {
|
impl std::fmt::Display for LimitRuleRender<'_> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "limit_req zone={}", self.zone_name)?;
|
write!(f, "limit_req zone={}", self.zone_name)?;
|
||||||
if let Some(burst) = self.rule.burst {
|
if let Some(burst) = self.rule.burst {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::db::entities::limit_zone::Model as LimitZone;
|
use crate::service::proxy::types::LimitZoneConfig;
|
||||||
|
|
||||||
impl std::fmt::Display for LimitZone {
|
impl std::fmt::Display for LimitZoneConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
use crate::db::entities::location_block::Model as LocationBlock;
|
use crate::service::proxy::types::LocationBlockConfig;
|
||||||
|
|
||||||
pub struct LocationBlockRender {
|
pub struct LocationBlockRender<'a> {
|
||||||
pub block: LocationBlock,
|
pub block: &'a LocationBlockConfig,
|
||||||
pub upstream_name: Option<String>,
|
pub upstream_name: Option<&'a str>,
|
||||||
pub access_rules: Vec<String>,
|
pub access_rules: &'a [String],
|
||||||
pub rewrite_rules: Vec<String>,
|
pub rewrite_rules: &'a [String],
|
||||||
pub proxy_setting: Option<String>,
|
pub proxy_setting: Option<&'a str>,
|
||||||
pub limit_rules: Vec<String>,
|
pub limit_rules: &'a [String],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for LocationBlockRender {
|
impl std::fmt::Display for LocationBlockRender<'_> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
writeln!(f, " location {} {{", self.block.path_pattern)?;
|
writeln!(f, " location {} {{", self.block.path_pattern)?;
|
||||||
|
|
||||||
if let Some(ref upstream) = self.upstream_name {
|
if let Some(upstream) = self.upstream_name {
|
||||||
writeln!(f, " proxy_pass http://{};", upstream)?;
|
writeln!(f, " proxy_pass http://{};", upstream)?;
|
||||||
writeln!(f, " proxy_set_header Host $host;")?;
|
writeln!(f, " proxy_set_header Host $host;")?;
|
||||||
writeln!(f, " proxy_set_header X-Real-IP $remote_addr;")?;
|
writeln!(f, " proxy_set_header X-Real-IP $remote_addr;")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref settings) = self.proxy_setting {
|
if let Some(settings) = self.proxy_setting {
|
||||||
for line in settings.lines() {
|
for line in settings.lines() {
|
||||||
if !line.is_empty() {
|
if !line.is_empty() {
|
||||||
writeln!(f, "{}", line)?;
|
writeln!(f, "{}", line)?;
|
||||||
@@ -27,15 +27,15 @@ impl std::fmt::Display for LocationBlockRender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for rule in &self.access_rules {
|
for rule in self.access_rules {
|
||||||
writeln!(f, " {}", rule)?;
|
writeln!(f, " {}", rule)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for rule in &self.rewrite_rules {
|
for rule in self.rewrite_rules {
|
||||||
writeln!(f, " {}", rule)?;
|
writeln!(f, " {}", rule)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for rule in &self.limit_rules {
|
for rule in self.limit_rules {
|
||||||
writeln!(f, " {}", rule)?;
|
writeln!(f, " {}", rule)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::db::entities::log_setting::Model as LogSetting;
|
use crate::service::proxy::types::LogSettingConfig;
|
||||||
|
|
||||||
impl std::fmt::Display for LogSetting {
|
impl std::fmt::Display for LogSettingConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
if let Some(ref path) = self.access_log_path {
|
if let Some(ref path) = self.access_log_path {
|
||||||
if let Some(ref level) = self.log_level {
|
if let Some(ref level) = self.log_level {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
mod access_rule;
|
pub(crate) mod access_rule;
|
||||||
mod cache_zone;
|
pub(crate) mod cache_zone;
|
||||||
mod limit_rule;
|
pub(crate) mod limit_rule;
|
||||||
mod limit_zone;
|
pub(crate) mod limit_zone;
|
||||||
mod location_block;
|
pub(crate) mod location_block;
|
||||||
mod log_setting;
|
pub(crate) mod log_setting;
|
||||||
mod proxy_setting;
|
pub(crate) mod proxy_setting;
|
||||||
mod rewrite_rule;
|
pub(crate) mod rewrite_rule;
|
||||||
mod server_block;
|
pub(crate) mod server_block;
|
||||||
mod ssl_certificate;
|
pub(crate) mod ssl_certificate;
|
||||||
mod upstream;
|
pub(crate) mod upstream;
|
||||||
|
|||||||
@@ -1,32 +1,23 @@
|
|||||||
use crate::db::entities::proxy_setting::Model as ProxySetting;
|
use crate::service::proxy::types::ProxySettingConfig;
|
||||||
|
|
||||||
pub struct ProxySettingRender {
|
pub struct ProxySettingRender<'a> {
|
||||||
pub setting: ProxySetting,
|
pub setting: &'a ProxySettingConfig,
|
||||||
pub cache_zone_name: Option<String>,
|
pub cache_zone_name: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProxySettingRender {
|
impl std::fmt::Display for ProxySettingRender<'_> {
|
||||||
fn render_timeout(value: Option<i32>, directive: &str) -> Option<String> {
|
|
||||||
value.map(|v| format!(" {} {}s;", directive, v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for ProxySettingRender {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
if let Some(line) = Self::render_timeout(self.setting.read_timeout, "proxy_read_timeout")
|
if let Some(timeout) = self.setting.read_timeout {
|
||||||
{
|
writeln!(f, " proxy_read_timeout {}s;", timeout)?;
|
||||||
writeln!(f, "{}", line)?;
|
|
||||||
}
|
}
|
||||||
if let Some(line) =
|
if let Some(timeout) = self.setting.connect_timeout {
|
||||||
Self::render_timeout(self.setting.connect_timeout, "proxy_connect_timeout")
|
writeln!(f, " proxy_connect_timeout {}s;", timeout)?;
|
||||||
{
|
|
||||||
writeln!(f, "{}", line)?;
|
|
||||||
}
|
}
|
||||||
if let Some(buffer) = self.setting.buffer_size {
|
if let Some(buffer) = self.setting.buffer_size {
|
||||||
writeln!(f, " proxy_buffer_size {};", buffer)?;
|
writeln!(f, " proxy_buffer_size {};", buffer)?;
|
||||||
}
|
}
|
||||||
if self.setting.cache_enabled.unwrap_or(false) {
|
if self.setting.cache_enabled.unwrap_or(false) {
|
||||||
if let Some(ref zone_name) = self.cache_zone_name {
|
if let Some(zone_name) = self.cache_zone_name {
|
||||||
writeln!(f, " proxy_cache {};", zone_name)?;
|
writeln!(f, " proxy_cache {};", zone_name)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::db::entities::rewrite_rule::Model as RewriteRule;
|
use crate::service::proxy::types::RewriteRuleConfig;
|
||||||
|
|
||||||
impl std::fmt::Display for RewriteRule {
|
impl std::fmt::Display for RewriteRuleConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "rewrite {} {}", self.pattern, self.replacement)?;
|
write!(f, "rewrite {} {}", self.pattern, self.replacement)?;
|
||||||
if let Some(ref flag) = self.flag {
|
if let Some(ref flag) = self.flag {
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use crate::db::entities::server_block::Model as ServerBlock;
|
use crate::service::proxy::types::ServerBlockConfig;
|
||||||
|
|
||||||
pub struct ServerBlockRender {
|
pub struct ServerBlockRender<'a> {
|
||||||
pub block: ServerBlock,
|
pub block: &'a ServerBlockConfig,
|
||||||
pub ssl_cert: Option<String>,
|
pub ssl_cert: Option<&'a str>,
|
||||||
pub locations: Vec<String>,
|
pub locations: &'a [String],
|
||||||
pub access_rules: Vec<String>,
|
pub access_rules: &'a [String],
|
||||||
pub log_setting: Option<String>,
|
pub log_setting: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for ServerBlockRender {
|
impl std::fmt::Display for ServerBlockRender<'_> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
writeln!(f, "server {{")?;
|
writeln!(f, "server {{")?;
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ impl std::fmt::Display for ServerBlockRender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref cert) = self.ssl_cert {
|
if let Some(cert) = self.ssl_cert {
|
||||||
writeln!(f, "{}", cert)?;
|
writeln!(f, "{}", cert)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref log) = self.log_setting {
|
if let Some(log) = self.log_setting {
|
||||||
for line in log.lines() {
|
for line in log.lines() {
|
||||||
if !line.is_empty() {
|
if !line.is_empty() {
|
||||||
writeln!(f, "{}", line)?;
|
writeln!(f, "{}", line)?;
|
||||||
@@ -36,11 +36,11 @@ impl std::fmt::Display for ServerBlockRender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for rule in &self.access_rules {
|
for rule in self.access_rules {
|
||||||
writeln!(f, " {}", rule)?;
|
writeln!(f, " {}", rule)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for loc in &self.locations {
|
for loc in self.locations {
|
||||||
writeln!(f, "{}", loc)?;
|
writeln!(f, "{}", loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::db::entities::ssl_certificate::Model as SslCertificate;
|
use crate::service::proxy::types::SslCertificateConfig;
|
||||||
|
|
||||||
impl std::fmt::Display for SslCertificate {
|
impl std::fmt::Display for SslCertificateConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
writeln!(f, " ssl_certificate {};", self.cert_path)?;
|
writeln!(f, " ssl_certificate {};", self.cert_path)?;
|
||||||
writeln!(f, " ssl_certificate_key {};", self.key_path)
|
writeln!(f, " ssl_certificate_key {};", self.key_path)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::db::entities::upstream::Model as Upstream;
|
use crate::service::proxy::types::UpstreamConfig;
|
||||||
|
|
||||||
impl std::fmt::Display for Upstream {
|
impl std::fmt::Display for UpstreamConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, " server {}:{};", self.target_host, self.target_port)
|
write!(f, " server {}:{};", self.target_host, self.target_port)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,187 @@
|
|||||||
pub mod config;
|
pub(crate) mod config;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::service::proxy::ProxyConfigRenderer;
|
||||||
|
use crate::service::proxy::types::{
|
||||||
|
AccessRuleConfig, CacheZoneConfig, LimitRuleConfig, LimitZoneConfig, LogSettingConfig,
|
||||||
|
OverrideRef, ProxyConfig, ProxySettingConfig, RewriteRuleConfig, SslCertificateConfig,
|
||||||
|
UpstreamConfig,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn resolve_ids<'a, T>(ids: &[OverrideRef], map: &'a HashMap<Uuid, T>) -> Vec<&'a T> {
|
||||||
|
ids.iter().filter_map(|r| map.get(&r.id)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_upstream_name(
|
||||||
|
upstream_id: Option<Uuid>,
|
||||||
|
upstreams: &HashMap<Uuid, UpstreamConfig>,
|
||||||
|
) -> Option<&str> {
|
||||||
|
upstream_id
|
||||||
|
.and_then(|id| upstreams.get(&id))
|
||||||
|
.map(|u| u.name.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_cache_zone_name(
|
||||||
|
zone_id: Option<Uuid>,
|
||||||
|
cache_zones: &HashMap<Uuid, CacheZoneConfig>,
|
||||||
|
) -> Option<&str> {
|
||||||
|
zone_id
|
||||||
|
.and_then(|id| cache_zones.get(&id))
|
||||||
|
.map(|z| z.name.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_limit_zone_name(
|
||||||
|
zone_id: Uuid,
|
||||||
|
limit_zones: &HashMap<Uuid, LimitZoneConfig>,
|
||||||
|
) -> Option<&str> {
|
||||||
|
limit_zones.get(&zone_id).map(|z| z.name.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_access_rules(
|
||||||
|
ids: &[OverrideRef],
|
||||||
|
access_rules: &HashMap<Uuid, AccessRuleConfig>,
|
||||||
|
) -> Vec<String> {
|
||||||
|
resolve_ids(ids, access_rules)
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| r.to_string())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_rewrite_rules(
|
||||||
|
ids: &[OverrideRef],
|
||||||
|
rewrite_rules: &HashMap<Uuid, RewriteRuleConfig>,
|
||||||
|
) -> Vec<String> {
|
||||||
|
resolve_ids(ids, rewrite_rules)
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| r.to_string())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_limit_rules(
|
||||||
|
ids: &[OverrideRef],
|
||||||
|
limit_rules: &HashMap<Uuid, LimitRuleConfig>,
|
||||||
|
limit_zones: &HashMap<Uuid, LimitZoneConfig>,
|
||||||
|
) -> Vec<String> {
|
||||||
|
resolve_ids(ids, limit_rules)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|rule| {
|
||||||
|
let zone_name = resolve_limit_zone_name(rule.zone_id, limit_zones)?;
|
||||||
|
Some(config::limit_rule::LimitRuleRender { rule, zone_name }.to_string())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_proxy_setting(
|
||||||
|
ids: &[OverrideRef],
|
||||||
|
proxy_settings: &HashMap<Uuid, ProxySettingConfig>,
|
||||||
|
cache_zones: &HashMap<Uuid, CacheZoneConfig>,
|
||||||
|
) -> Option<String> {
|
||||||
|
let setting = resolve_ids(ids, proxy_settings).into_iter().next()?;
|
||||||
|
let cache_zone_name = resolve_cache_zone_name(setting.cache_zone, cache_zones);
|
||||||
|
Some(
|
||||||
|
config::proxy_setting::ProxySettingRender {
|
||||||
|
setting,
|
||||||
|
cache_zone_name,
|
||||||
|
}
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_log_setting(
|
||||||
|
ids: &[OverrideRef],
|
||||||
|
log_settings: &HashMap<Uuid, LogSettingConfig>,
|
||||||
|
) -> Option<String> {
|
||||||
|
let setting = resolve_ids(ids, log_settings).into_iter().next()?;
|
||||||
|
Some(setting.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssl_cert(
|
||||||
|
ids: &[OverrideRef],
|
||||||
|
ssl_certificates: &HashMap<Uuid, SslCertificateConfig>,
|
||||||
|
) -> Option<String> {
|
||||||
|
let cert = resolve_ids(ids, ssl_certificates).into_iter().next()?;
|
||||||
|
Some(cert.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NginxConfigRenderer;
|
||||||
|
|
||||||
|
impl ProxyConfigRenderer for NginxConfigRenderer {
|
||||||
|
fn render(&self, config: &ProxyConfig) -> String {
|
||||||
|
let mut output = String::new();
|
||||||
|
|
||||||
|
// Global cache zones
|
||||||
|
for zone in config.cache_zones.values() {
|
||||||
|
writeln!(output, "{}", zone).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit request zones
|
||||||
|
for zone in config.limit_zones.values() {
|
||||||
|
writeln!(output, "{}", zone).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upstream blocks
|
||||||
|
for upstream in config.upstreams.values() {
|
||||||
|
writeln!(output, "upstream {} {{", upstream.name).ok();
|
||||||
|
writeln!(output, "{}", upstream).ok();
|
||||||
|
writeln!(output, "}}").ok();
|
||||||
|
writeln!(output).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server blocks
|
||||||
|
for sb in config.server_blocks.values() {
|
||||||
|
let access_rules = render_access_rules(&sb.access_rules, &config.access_rules);
|
||||||
|
let ssl_cert = render_ssl_cert(&sb.ssl_certificates, &config.ssl_certificates);
|
||||||
|
let log_setting = render_log_setting(&sb.log_settings, &config.log_settings);
|
||||||
|
|
||||||
|
// Render location blocks for this server
|
||||||
|
let locations: Vec<String> = resolve_ids(&sb.location_blocks, &config.location_blocks)
|
||||||
|
.into_iter()
|
||||||
|
.map(|lb| {
|
||||||
|
let upstream_name =
|
||||||
|
resolve_upstream_name(lb.proxy_pass_upstream_id, &config.upstreams);
|
||||||
|
let lb_access_rules =
|
||||||
|
render_access_rules(&lb.access_rules, &config.access_rules);
|
||||||
|
let lb_rewrite_rules =
|
||||||
|
render_rewrite_rules(&lb.rewrite_rules, &config.rewrite_rules);
|
||||||
|
let lb_proxy_setting = render_proxy_setting(
|
||||||
|
&lb.proxy_settings,
|
||||||
|
&config.proxy_settings,
|
||||||
|
&config.cache_zones,
|
||||||
|
);
|
||||||
|
let lb_limit_rules = render_limit_rules(
|
||||||
|
&lb.limit_rules,
|
||||||
|
&config.limit_rules,
|
||||||
|
&config.limit_zones,
|
||||||
|
);
|
||||||
|
|
||||||
|
config::location_block::LocationBlockRender {
|
||||||
|
block: lb,
|
||||||
|
upstream_name,
|
||||||
|
access_rules: &lb_access_rules,
|
||||||
|
rewrite_rules: &lb_rewrite_rules,
|
||||||
|
proxy_setting: lb_proxy_setting.as_deref(),
|
||||||
|
limit_rules: &lb_limit_rules,
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let server = config::server_block::ServerBlockRender {
|
||||||
|
block: sb,
|
||||||
|
ssl_cert: ssl_cert.as_deref(),
|
||||||
|
locations: &locations,
|
||||||
|
access_rules: &access_rules,
|
||||||
|
log_setting: log_setting.as_deref(),
|
||||||
|
};
|
||||||
|
|
||||||
|
writeln!(output, "{}", server).ok();
|
||||||
|
writeln!(output).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use sea_orm::DatabaseConnection;
|
||||||
|
|
||||||
|
use super::nginx::NginxConfigRenderer;
|
||||||
|
use super::repo::{ProxyRepo, ProxyRepoImpl};
|
||||||
|
use super::types::{ProxyConfig, ProxyServiceError, ProxyServiceResult, ProxyType};
|
||||||
|
use super::{ProxyConfigRenderer, ProxyServiceTrait};
|
||||||
|
|
||||||
|
pub struct ProxyServiceImpl {
|
||||||
|
repo: Box<dyn ProxyRepo>,
|
||||||
|
renderers: HashMap<ProxyType, Box<dyn ProxyConfigRenderer>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProxyServiceImpl {
|
||||||
|
pub fn new(db: DatabaseConnection) -> Self {
|
||||||
|
let mut renderers: HashMap<ProxyType, Box<dyn ProxyConfigRenderer>> = HashMap::new();
|
||||||
|
renderers.insert(ProxyType::Nginx, Box::new(NginxConfigRenderer));
|
||||||
|
Self {
|
||||||
|
repo: Box::new(ProxyRepoImpl::new(db)),
|
||||||
|
renderers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl ProxyServiceTrait for ProxyServiceImpl {
|
||||||
|
async fn get_proxy_config(&self, proxy_id: uuid::Uuid) -> ProxyServiceResult<ProxyConfig> {
|
||||||
|
self.repo.get_merged_proxy_config(proxy_id).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProxyServiceImpl {
|
||||||
|
pub async fn render_config(&self, proxy_id: uuid::Uuid) -> ProxyServiceResult<String> {
|
||||||
|
let config = self.repo.get_merged_proxy_config(proxy_id).await?;
|
||||||
|
let renderer = self
|
||||||
|
.renderers
|
||||||
|
.get(&config.r#type)
|
||||||
|
.ok_or(ProxyServiceError::RendererNotFound)?;
|
||||||
|
Ok(renderer.render(&config))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use std::collections::HashMap;
|
|||||||
pub enum ProxyServiceError {
|
pub enum ProxyServiceError {
|
||||||
ConfigNotFound,
|
ConfigNotFound,
|
||||||
InvalidConfig,
|
InvalidConfig,
|
||||||
|
RendererNotFound,
|
||||||
DatabaseError(sea_orm::DbErr),
|
DatabaseError(sea_orm::DbErr),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ impl From<sea_orm::DbErr> for ProxyServiceError {
|
|||||||
|
|
||||||
pub type ProxyServiceResult<T> = Result<T, ProxyServiceError>;
|
pub type ProxyServiceResult<T> = Result<T, ProxyServiceError>;
|
||||||
|
|
||||||
|
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
|
||||||
pub enum ProxyType {
|
pub enum ProxyType {
|
||||||
Nginx,
|
Nginx,
|
||||||
}
|
}
|
||||||
@@ -247,6 +249,7 @@ impl From<crate::db::entities::access_rule::Model> for AccessRuleConfig {
|
|||||||
pub struct CacheZoneConfig {
|
pub struct CacheZoneConfig {
|
||||||
pub id: uuid::Uuid,
|
pub id: uuid::Uuid,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub path: String,
|
||||||
pub size: String,
|
pub size: String,
|
||||||
pub override_of_id: Option<uuid::Uuid>,
|
pub override_of_id: Option<uuid::Uuid>,
|
||||||
}
|
}
|
||||||
@@ -256,6 +259,7 @@ impl From<crate::db::entities::cache_zone::Model> for CacheZoneConfig {
|
|||||||
CacheZoneConfig {
|
CacheZoneConfig {
|
||||||
id: model.id,
|
id: model.id,
|
||||||
name: model.name,
|
name: model.name,
|
||||||
|
path: model.path,
|
||||||
size: model.size_limit,
|
size: model.size_limit,
|
||||||
override_of_id: model.override_of_id,
|
override_of_id: model.override_of_id,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user