Files
OpenFlare/pkg/render/openresty/render_route.go
T
2026-06-19 17:20:39 +08:00

152 lines
6.7 KiB
Go

package openresty
import (
"fmt"
"strings"
)
type routeCertPartition struct {
httpOnlyDomains []string
domainsByCertID map[uint][]string
}
func partitionRouteDomainsByCert(domains []string, certIDs, domainCertIDs []uint) routeCertPartition {
httpOnlyDomains := make([]string, 0, len(domains))
domainsByCertID := make(map[uint][]string, len(certIDs))
for index, domain := range domains {
if index >= len(domainCertIDs) || domainCertIDs[index] == 0 {
httpOnlyDomains = append(httpOnlyDomains, domain)
continue
}
domainsByCertID[domainCertIDs[index]] = append(domainsByCertID[domainCertIDs[index]], domain)
}
return routeCertPartition{
httpOnlyDomains: httpOnlyDomains,
domainsByCertID: domainsByCertID,
}
}
func validateRouteCertificates(route Route, displayName string, certIDs []uint, partition routeCertPartition, certificates map[uint]string) error {
for _, certID := range certIDs {
assignedDomains := partition.domainsByCertID[certID]
if len(assignedDomains) == 0 {
continue
}
certPEM, ok := certificates[certID]
if !ok {
return fmt.Errorf("route %s certificate %d does not exist", route.Domain, certID)
}
if err := validateCertificateCoverage(certPEM, assignedDomains); err != nil {
return fmt.Errorf("site %s certificate validation failed: %w", displayName, err)
}
}
return nil
}
func renderPagesRouteHTTPS(
builder *strings.Builder,
serverNames, displayName string,
route Route,
partition routeCertPartition,
certIDs []uint,
limitConfig routeLimitConfig,
powEnabled bool,
cfg ConfigSnapshot,
) {
if route.RedirectHTTP {
if len(partition.httpOnlyDomains) > 0 {
builder.WriteString(renderHTTPPagesServer(renderServerNames(partition.httpOnlyDomains), displayName, route.PagesDeployment, limitConfig, powEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword))
}
for _, certID := range certIDs {
if assignedDomains := partition.domainsByCertID[certID]; len(assignedDomains) > 0 {
builder.WriteString(renderHTTPRedirectServer(renderServerNames(assignedDomains)))
}
}
} else {
builder.WriteString(renderHTTPPagesServer(serverNames, displayName, route.PagesDeployment, limitConfig, powEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword))
}
for _, certID := range certIDs {
if assignedDomains := partition.domainsByCertID[certID]; len(assignedDomains) > 0 {
builder.WriteString(renderHTTPSPagesServer(renderServerNames(assignedDomains), displayName, certID, route.PagesDeployment, limitConfig, powEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
}
}
}
func renderProxyRouteHTTPS(
builder *strings.Builder,
serverNames, displayName string,
route Route,
partition routeCertPartition,
certIDs []uint,
cacheConfig routeCacheConfig,
limitConfig routeLimitConfig,
upstreamConfig routeUpstreamConfig,
powEnabled bool,
cfg ConfigSnapshot,
) {
if route.RedirectHTTP {
if len(partition.httpOnlyDomains) > 0 {
builder.WriteString(renderHTTPProxyServer(renderServerNames(partition.httpOnlyDomains), displayName, route.OriginURL, route.OriginHost, route.CustomHeaders, cacheConfig, limitConfig, upstreamConfig, powEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
}
for _, certID := range certIDs {
if assignedDomains := partition.domainsByCertID[certID]; len(assignedDomains) > 0 {
builder.WriteString(renderHTTPRedirectServer(renderServerNames(assignedDomains)))
}
}
} else {
builder.WriteString(renderHTTPProxyServer(serverNames, displayName, route.OriginURL, route.OriginHost, route.CustomHeaders, cacheConfig, limitConfig, upstreamConfig, powEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
}
for _, certID := range certIDs {
if assignedDomains := partition.domainsByCertID[certID]; len(assignedDomains) > 0 {
builder.WriteString(renderHTTPSServer(renderServerNames(assignedDomains), displayName, route.OriginURL, route.OriginHost, certID, route.CustomHeaders, cacheConfig, limitConfig, upstreamConfig, powEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
}
}
}
func renderPagesRoute(builder *strings.Builder, route Route, displayName, serverNames string, certificates map[uint]string, limitConfig routeLimitConfig, powEnabled bool, cfg ConfigSnapshot) error {
if route.PagesDeployment == nil {
return fmt.Errorf("route %s pages deployment is missing", route.Domain)
}
if !route.EnableHTTPS {
builder.WriteString(renderHTTPPagesServer(serverNames, displayName, route.PagesDeployment, limitConfig, powEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword))
return nil
}
certIDs := normalizeCertIDs(route.CertID, route.CertIDs)
domainCertIDs := normalizeDomainCertIDs(normalizedRouteDomains(route), certIDs, route.DomainCertIDs)
if len(certIDs) == 0 {
return fmt.Errorf("路由 %s 未配置证书", route.Domain)
}
partition := partitionRouteDomainsByCert(normalizedRouteDomains(route), certIDs, domainCertIDs)
if err := validateRouteCertificates(route, displayName, certIDs, partition, certificates); err != nil {
return err
}
renderPagesRouteHTTPS(builder, serverNames, displayName, route, partition, certIDs, limitConfig, powEnabled, cfg)
return nil
}
func renderProxyRoute(builder *strings.Builder, route Route, displayName, serverNames string, certificates map[uint]string, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, powEnabled bool, cfg ConfigSnapshot) error {
upstreams := route.Upstreams
if len(upstreams) == 0 && strings.TrimSpace(route.OriginURL) != "" {
upstreams = []string{route.OriginURL}
}
upstreamConfig := buildRouteUpstreamConfig(route, upstreams)
if upstreamConfig.UsesNamedUpstream {
builder.WriteString(renderNamedUpstreamBlock(upstreamConfig))
}
if !route.EnableHTTPS {
builder.WriteString(renderHTTPProxyServer(serverNames, displayName, route.OriginURL, route.OriginHost, route.CustomHeaders, cacheConfig, limitConfig, upstreamConfig, powEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
return nil
}
certIDs := normalizeCertIDs(route.CertID, route.CertIDs)
domainCertIDs := normalizeDomainCertIDs(normalizedRouteDomains(route), certIDs, route.DomainCertIDs)
if len(certIDs) == 0 {
return fmt.Errorf("路由 %s 未配置证书", route.Domain)
}
partition := partitionRouteDomainsByCert(normalizedRouteDomains(route), certIDs, domainCertIDs)
if err := validateRouteCertificates(route, displayName, certIDs, partition, certificates); err != nil {
return err
}
renderProxyRouteHTTPS(builder, serverNames, displayName, route, partition, certIDs, cacheConfig, limitConfig, upstreamConfig, powEnabled, cfg)
return nil
}