mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-12 02:06:37 +08:00
[优化] 移除 OpenRestyResolvers 配置,统一上游渲染为带 keepalive 的 named upstream
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"openflare/common"
|
||||
"openflare/model"
|
||||
@@ -83,15 +82,11 @@ type routeCacheConfig struct {
|
||||
type routeUpstreamConfig struct {
|
||||
Name string
|
||||
Scheme string
|
||||
Servers []routeUpstreamServer
|
||||
ProxyPassURI string
|
||||
Servers []string
|
||||
UsesNamedUpstream bool
|
||||
}
|
||||
|
||||
type routeUpstreamServer struct {
|
||||
Address string
|
||||
Resolve bool
|
||||
}
|
||||
|
||||
type openRestyConfigSnapshot struct {
|
||||
WorkerProcesses string `json:"worker_processes"`
|
||||
WorkerConnections int `json:"worker_connections"`
|
||||
@@ -117,7 +112,6 @@ type openRestyConfigSnapshot struct {
|
||||
GzipEnabled bool `json:"gzip_enabled"`
|
||||
GzipMinLength int `json:"gzip_min_length"`
|
||||
GzipCompLevel int `json:"gzip_comp_level"`
|
||||
Resolvers string `json:"resolvers,omitempty"`
|
||||
CacheEnabled bool `json:"cache_enabled"`
|
||||
CachePath string `json:"cache_path,omitempty"`
|
||||
CacheLevels string `json:"cache_levels"`
|
||||
@@ -182,7 +176,6 @@ var requiredMainConfigTemplatePlaceholders = []string{
|
||||
"{{OpenRestyGzip}}",
|
||||
"{{OpenRestyGzipMinLength}}",
|
||||
"{{OpenRestyGzipCompLevel}}",
|
||||
"{{OpenRestyResolverDirective}}",
|
||||
"{{OpenRestyCacheBlock}}",
|
||||
"{{OpenRestyRouteConfigInclude}}",
|
||||
}
|
||||
@@ -541,7 +534,6 @@ func buildOpenRestyConfigSnapshot() openRestyConfigSnapshot {
|
||||
GzipEnabled: common.OpenRestyGzipEnabled,
|
||||
GzipMinLength: common.OpenRestyGzipMinLength,
|
||||
GzipCompLevel: common.OpenRestyGzipCompLevel,
|
||||
Resolvers: common.OpenRestyResolvers,
|
||||
CacheEnabled: common.OpenRestyCacheEnabled,
|
||||
CachePath: common.OpenRestyCachePath,
|
||||
CacheLevels: common.OpenRestyCacheLevels,
|
||||
@@ -603,7 +595,6 @@ func diffOpenRestyOptionDetails(left openRestyConfigSnapshot, right openRestyCon
|
||||
appendIfChanged("OpenRestyGzipEnabled", fmt.Sprintf("%t", left.GzipEnabled), fmt.Sprintf("%t", right.GzipEnabled))
|
||||
appendIfChanged("OpenRestyGzipMinLength", fmt.Sprintf("%d", left.GzipMinLength), fmt.Sprintf("%d", right.GzipMinLength))
|
||||
appendIfChanged("OpenRestyGzipCompLevel", fmt.Sprintf("%d", left.GzipCompLevel), fmt.Sprintf("%d", right.GzipCompLevel))
|
||||
appendIfChanged("OpenRestyResolvers", left.Resolvers, right.Resolvers)
|
||||
appendIfChanged("OpenRestyCacheEnabled", fmt.Sprintf("%t", left.CacheEnabled), fmt.Sprintf("%t", right.CacheEnabled))
|
||||
appendIfChanged("OpenRestyCachePath", left.CachePath, right.CachePath)
|
||||
appendIfChanged("OpenRestyCacheLevels", left.CacheLevels, right.CacheLevels)
|
||||
@@ -650,7 +641,6 @@ func openRestyOptionKeys() []string {
|
||||
"OpenRestyGzipEnabled",
|
||||
"OpenRestyGzipMinLength",
|
||||
"OpenRestyGzipCompLevel",
|
||||
"OpenRestyResolvers",
|
||||
"OpenRestyCacheEnabled",
|
||||
"OpenRestyCachePath",
|
||||
"OpenRestyCacheLevels",
|
||||
@@ -676,9 +666,6 @@ func renderRouteConfig(routes []*model.ProxyRoute, cfg openRestyConfigSnapshot)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("路由 %s 上游配置无效", route.Domain)
|
||||
}
|
||||
if err := validateRenderableUpstreams(route.Domain, upstreams, cfg); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
cacheRules, err := decodeStoredCacheRules(route.CacheRules)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("路由 %s 缓存规则无效", route.Domain)
|
||||
@@ -688,7 +675,7 @@ func renderRouteConfig(routes []*model.ProxyRoute, cfg openRestyConfigSnapshot)
|
||||
Policy: route.CachePolicy,
|
||||
Rules: cacheRules,
|
||||
}
|
||||
upstreamConfig := buildRouteUpstreamConfig(route, upstreams, cfg)
|
||||
upstreamConfig := buildRouteUpstreamConfig(route, upstreams)
|
||||
if upstreamConfig.UsesNamedUpstream {
|
||||
builder.WriteString(renderNamedUpstreamBlock(upstreamConfig))
|
||||
}
|
||||
@@ -770,7 +757,7 @@ func renderMainConfigTemplate(templateText string, cfg openRestyConfigSnapshot)
|
||||
"{{OpenRestyGzip}}", onOff(cfg.GzipEnabled),
|
||||
"{{OpenRestyGzipMinLength}}", fmt.Sprintf("%d", cfg.GzipMinLength),
|
||||
"{{OpenRestyGzipCompLevel}}", fmt.Sprintf("%d", cfg.GzipCompLevel),
|
||||
"{{OpenRestyResolverDirective}}", renderResolverDirective(cfg.Resolvers),
|
||||
"{{OpenRestyResolverDirective}}", "",
|
||||
"{{OpenRestyCacheBlock}}", renderOpenRestyCacheTemplateBlock(cfg),
|
||||
"{{OpenRestyRouteConfigInclude}}", nginxRouteConfigPlaceholder,
|
||||
)
|
||||
@@ -850,7 +837,7 @@ func nextVersionNumber(now time.Time) (string, error) {
|
||||
}
|
||||
|
||||
func renderHTTPProxyServer(domain string, originURL string, originHost string, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, upstreamConfig routeUpstreamConfig, cfg openRestyConfigSnapshot) string {
|
||||
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n\n location / {\n%s%s%s }\n}\n\n", domain, renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig, cfg))
|
||||
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n\n location / {\n%s%s%s }\n}\n\n", domain, renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig))
|
||||
}
|
||||
|
||||
func renderHTTPRedirectServer(domain string) string {
|
||||
@@ -860,7 +847,7 @@ func renderHTTPRedirectServer(domain string) string {
|
||||
func renderHTTPSServer(domain string, originURL string, originHost string, certificateID uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, upstreamConfig routeUpstreamConfig, cfg openRestyConfigSnapshot) string {
|
||||
certPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateCertFileName(certificateID))
|
||||
keyPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateKeyFileName(certificateID))
|
||||
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n\n location / {\n%s%s%s }\n}\n\n", domain, certPath, keyPath, renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig, cfg))
|
||||
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n\n location / {\n%s%s%s }\n}\n\n", domain, certPath, keyPath, renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig))
|
||||
}
|
||||
|
||||
func renderConnectionUpgradeMap() string {
|
||||
@@ -885,12 +872,13 @@ func renderProxyHeaderBlock(originURL string, originHost string, customHeaders [
|
||||
builder.WriteString(" proxy_set_header X-Real-IP $remote_addr;\n")
|
||||
builder.WriteString(" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n")
|
||||
builder.WriteString(" proxy_set_header X-Forwarded-Proto $scheme;\n")
|
||||
if common.OpenRestyWebsocketEnabled || upstreamConfig.UsesNamedUpstream {
|
||||
if common.OpenRestyWebsocketEnabled {
|
||||
builder.WriteString(" proxy_http_version 1.1;\n")
|
||||
builder.WriteString(" proxy_set_header Connection $connection_upgrade;\n")
|
||||
}
|
||||
if common.OpenRestyWebsocketEnabled {
|
||||
builder.WriteString(" proxy_set_header Upgrade $http_upgrade;\n")
|
||||
} else if upstreamConfig.UsesNamedUpstream {
|
||||
builder.WriteString(" proxy_http_version 1.1;\n")
|
||||
builder.WriteString(" proxy_set_header Connection \"\";\n")
|
||||
}
|
||||
for _, header := range customHeaders {
|
||||
builder.WriteString(fmt.Sprintf(" proxy_set_header %s %s;\n", header.Key, quoteNginxHeaderValue(header.Value)))
|
||||
@@ -963,40 +951,18 @@ func buildPathExactMatchPattern(rules []string) string {
|
||||
return fmt.Sprintf("^(?:%s)$", strings.Join(parts, "|"))
|
||||
}
|
||||
|
||||
func renderProxyPassBlock(originURL string, upstreamConfig routeUpstreamConfig, cfg openRestyConfigSnapshot) string {
|
||||
func renderProxyPassBlock(originURL string, upstreamConfig routeUpstreamConfig) string {
|
||||
parsed, err := url.Parse(originURL)
|
||||
if err != nil || parsed.Host == "" || parsed.Scheme == "" {
|
||||
return fmt.Sprintf(" proxy_pass %s;\n", originURL)
|
||||
}
|
||||
if upstreamConfig.UsesNamedUpstream {
|
||||
return fmt.Sprintf(" proxy_pass %s://%s;\n", upstreamConfig.Scheme, upstreamConfig.Name)
|
||||
return fmt.Sprintf(" proxy_pass %s://%s%s;\n", upstreamConfig.Scheme, upstreamConfig.Name, upstreamConfig.ProxyPassURI)
|
||||
}
|
||||
if !shouldUseRuntimeResolver(originURL, cfg.Resolvers) {
|
||||
return fmt.Sprintf(" proxy_pass %s;\n", originURL)
|
||||
}
|
||||
upstreamURL := fmt.Sprintf("%s://%s", parsed.Scheme, parsed.Host)
|
||||
basePath := strings.TrimRight(parsed.EscapedPath(), "/")
|
||||
if basePath == "" || basePath == "." {
|
||||
basePath = ""
|
||||
}
|
||||
if parsed.RawQuery != "" {
|
||||
if basePath == "" {
|
||||
basePath = "/"
|
||||
}
|
||||
basePath += "?" + parsed.RawQuery
|
||||
}
|
||||
var builder strings.Builder
|
||||
builder.WriteString(fmt.Sprintf(" set $openflare_upstream %s;\n", quoteNginxStringLiteral(upstreamURL)))
|
||||
if basePath != "" {
|
||||
builder.WriteString(fmt.Sprintf(" set $openflare_upstream_base_path %s;\n", quoteNginxStringLiteral(basePath)))
|
||||
builder.WriteString(" proxy_pass $openflare_upstream$openflare_upstream_base_path$request_uri;\n")
|
||||
return builder.String()
|
||||
}
|
||||
builder.WriteString(" proxy_pass $openflare_upstream$request_uri;\n")
|
||||
return builder.String()
|
||||
return fmt.Sprintf(" proxy_pass %s;\n", originURL)
|
||||
}
|
||||
|
||||
func buildRouteUpstreamConfig(route *model.ProxyRoute, upstreams []string, cfg openRestyConfigSnapshot) routeUpstreamConfig {
|
||||
func buildRouteUpstreamConfig(route *model.ProxyRoute, upstreams []string) routeUpstreamConfig {
|
||||
if len(upstreams) == 0 {
|
||||
return routeUpstreamConfig{}
|
||||
}
|
||||
@@ -1005,27 +971,15 @@ func buildRouteUpstreamConfig(route *model.ProxyRoute, upstreams []string, cfg o
|
||||
if err != nil || parsed.Host == "" || parsed.Scheme == "" {
|
||||
return routeUpstreamConfig{}
|
||||
}
|
||||
if strings.TrimSpace(parsed.EscapedPath()) != "" && strings.TrimSpace(parsed.EscapedPath()) != "/" {
|
||||
return routeUpstreamConfig{}
|
||||
}
|
||||
if parsed.RawQuery != "" {
|
||||
return routeUpstreamConfig{}
|
||||
}
|
||||
server := routeUpstreamServer{Address: parsed.Host}
|
||||
if !isIPAddressHostname(parsed.Hostname()) {
|
||||
if strings.TrimSpace(cfg.Resolvers) == "" {
|
||||
return routeUpstreamConfig{}
|
||||
}
|
||||
server.Resolve = true
|
||||
}
|
||||
return routeUpstreamConfig{
|
||||
Name: buildRouteUpstreamName(route),
|
||||
Scheme: parsed.Scheme,
|
||||
Servers: []routeUpstreamServer{server},
|
||||
ProxyPassURI: buildUpstreamProxyPassURI(parsed),
|
||||
Servers: []string{parsed.Host},
|
||||
UsesNamedUpstream: true,
|
||||
}
|
||||
}
|
||||
servers := make([]routeUpstreamServer, 0, len(upstreams))
|
||||
servers := make([]string, 0, len(upstreams))
|
||||
var scheme string
|
||||
for _, upstream := range upstreams {
|
||||
parsed, err := url.Parse(strings.TrimSpace(upstream))
|
||||
@@ -1043,11 +997,7 @@ func buildRouteUpstreamConfig(route *model.ProxyRoute, upstreams []string, cfg o
|
||||
} else if scheme != parsed.Scheme {
|
||||
return routeUpstreamConfig{}
|
||||
}
|
||||
server := routeUpstreamServer{Address: parsed.Host}
|
||||
if !isIPAddressHostname(parsed.Hostname()) {
|
||||
server.Resolve = true
|
||||
}
|
||||
servers = append(servers, server)
|
||||
servers = append(servers, parsed.Host)
|
||||
}
|
||||
return routeUpstreamConfig{
|
||||
Name: buildRouteUpstreamName(route),
|
||||
@@ -1057,6 +1007,20 @@ func buildRouteUpstreamConfig(route *model.ProxyRoute, upstreams []string, cfg o
|
||||
}
|
||||
}
|
||||
|
||||
func buildUpstreamProxyPassURI(parsed *url.URL) string {
|
||||
if parsed == nil {
|
||||
return ""
|
||||
}
|
||||
path := parsed.EscapedPath()
|
||||
if path == "/" {
|
||||
path = ""
|
||||
}
|
||||
if parsed.RawQuery == "" {
|
||||
return path
|
||||
}
|
||||
return fmt.Sprintf("%s?%s", path, parsed.RawQuery)
|
||||
}
|
||||
|
||||
func buildRouteUpstreamName(route *model.ProxyRoute) string {
|
||||
sanitized := strings.Map(func(r rune) rune {
|
||||
switch {
|
||||
@@ -1081,68 +1045,12 @@ func renderNamedUpstreamBlock(upstreamConfig routeUpstreamConfig) string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString(fmt.Sprintf("upstream %s {\n", upstreamConfig.Name))
|
||||
for _, server := range upstreamConfig.Servers {
|
||||
if server.Resolve {
|
||||
builder.WriteString(fmt.Sprintf(" server %s resolve max_fails=3 fail_timeout=10s;\n", server.Address))
|
||||
continue
|
||||
}
|
||||
builder.WriteString(fmt.Sprintf(" server %s max_fails=3 fail_timeout=10s;\n", server.Address))
|
||||
builder.WriteString(fmt.Sprintf(" server %s max_fails=3 fail_timeout=10s;\n", server))
|
||||
}
|
||||
builder.WriteString(" keepalive 128;\n}\n\n")
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
func validateRenderableUpstreams(domain string, upstreams []string, cfg openRestyConfigSnapshot) error {
|
||||
if len(upstreams) <= 1 {
|
||||
return nil
|
||||
}
|
||||
if strings.TrimSpace(cfg.Resolvers) != "" {
|
||||
return nil
|
||||
}
|
||||
for _, upstream := range upstreams {
|
||||
parsed, err := url.Parse(strings.TrimSpace(upstream))
|
||||
if err != nil || parsed.Hostname() == "" {
|
||||
return fmt.Errorf("路由 %s 上游配置无效", domain)
|
||||
}
|
||||
if !isIPAddressHostname(parsed.Hostname()) {
|
||||
return fmt.Errorf("路由 %s 的多上游主机名需要先配置 OpenRestyResolvers", domain)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isIPAddressHostname(host string) bool {
|
||||
return net.ParseIP(strings.TrimSpace(host)) != nil
|
||||
}
|
||||
|
||||
func shouldUseRuntimeResolver(originURL string, resolvers string) bool {
|
||||
if strings.TrimSpace(resolvers) == "" {
|
||||
return false
|
||||
}
|
||||
return requiresRuntimeResolver(originURL)
|
||||
}
|
||||
|
||||
func requiresRuntimeResolver(originURL string) bool {
|
||||
parsed, err := url.Parse(strings.TrimSpace(originURL))
|
||||
if err != nil || parsed.Hostname() == "" {
|
||||
return false
|
||||
}
|
||||
return net.ParseIP(parsed.Hostname()) == nil
|
||||
}
|
||||
|
||||
func renderResolverDirective(value string) string {
|
||||
resolvers := splitResolverList(value)
|
||||
if len(resolvers) == 0 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(" resolver %s valid=30s ipv6=off;\n resolver_timeout 5s;\n", strings.Join(resolvers, " "))
|
||||
}
|
||||
|
||||
func splitResolverList(value string) []string {
|
||||
return strings.FieldsFunc(strings.TrimSpace(value), func(r rune) bool {
|
||||
return r == ',' || r == '\n' || r == '\r' || r == '\t' || r == ' '
|
||||
})
|
||||
}
|
||||
|
||||
func resolveUpstreamServerName(originURL string, originHost string) string {
|
||||
parsed, err := url.Parse(originURL)
|
||||
if err != nil || !strings.EqualFold(parsed.Scheme, "https") {
|
||||
|
||||
@@ -156,11 +156,17 @@ func TestPublishConfigVersionRendersCustomHeaders(t *testing.T) {
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_set_header Connection $connection_upgrade;") {
|
||||
t.Fatal("expected rendered config to use normalized websocket connection header")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass https://origin.internal;") {
|
||||
t.Fatal("expected hostname origin without resolver to keep direct proxy_pass")
|
||||
if !strings.Contains(result.Version.RenderedConfig, "upstream backend_custom_example_com_1 {") {
|
||||
t.Fatal("expected hostname origin to render named upstream")
|
||||
}
|
||||
if strings.Contains(result.Version.RenderedConfig, "proxy_pass $openflare_upstream$request_uri;") {
|
||||
t.Fatal("expected rendered config to avoid runtime-resolved proxy_pass when no resolvers are configured")
|
||||
if !strings.Contains(result.Version.RenderedConfig, "server origin.internal max_fails=3 fail_timeout=10s;") {
|
||||
t.Fatal("expected hostname origin to render upstream server entry")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "keepalive 128;") {
|
||||
t.Fatal("expected named upstream to enable keepalive")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass https://backend_custom_example_com_1;") {
|
||||
t.Fatal("expected hostname origin to proxy through named upstream")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,8 +245,8 @@ func TestPublishConfigVersionRendersRouteLevelCachePolicy(t *testing.T) {
|
||||
if strings.Count(result.Version.RenderedConfig, "proxy_cache openflare_cache;") != 1 {
|
||||
t.Fatal("expected only cache-enabled route to include proxy_cache directive")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass https://origin.internal;") {
|
||||
t.Fatal("expected cache-enabled hostname route without resolver to keep direct proxy_pass")
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass https://backend_static_example_com_1;") {
|
||||
t.Fatal("expected cache-enabled hostname route to proxy through named upstream")
|
||||
}
|
||||
if !strings.Contains(result.Version.SnapshotJSON, `"cache_enabled":true`) {
|
||||
t.Fatal("expected snapshot to include route cache toggle")
|
||||
@@ -294,7 +300,7 @@ func TestPublishConfigVersionRendersMultipleUpstreams(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublishConfigVersionRejectsHostnameLoadBalancingWithoutResolvers(t *testing.T) {
|
||||
func TestPublishConfigVersionRendersHostnameLoadBalancingUpstream(t *testing.T) {
|
||||
setupServiceTestDB(t)
|
||||
|
||||
_, err := CreateProxyRoute(ProxyRouteInput{
|
||||
@@ -307,9 +313,24 @@ func TestPublishConfigVersionRejectsHostnameLoadBalancingWithoutResolvers(t *tes
|
||||
t.Fatalf("CreateProxyRoute failed: %v", err)
|
||||
}
|
||||
|
||||
_, err = PublishConfigVersion("root")
|
||||
if err == nil || !strings.Contains(err.Error(), "多上游主机名需要先配置 OpenRestyResolvers") {
|
||||
t.Fatalf("expected hostname load balancing publish validation error, got %v", err)
|
||||
result, err := PublishConfigVersion("root")
|
||||
if err != nil {
|
||||
t.Fatalf("PublishConfigVersion failed: %v", err)
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "upstream backend_hostname_lb_example_com_1 {") {
|
||||
t.Fatal("expected hostname load balancing route to define named upstream")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "server c1:39010 max_fails=3 fail_timeout=10s;") {
|
||||
t.Fatal("expected rendered config to include primary hostname upstream")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "server c2:39010 max_fails=3 fail_timeout=10s;") {
|
||||
t.Fatal("expected rendered config to include secondary hostname upstream")
|
||||
}
|
||||
if strings.Contains(result.Version.RenderedConfig, " resolve ") {
|
||||
t.Fatal("expected hostname upstreams to avoid resolver-based server parameters")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass http://backend_hostname_lb_example_com_1;") {
|
||||
t.Fatal("expected hostname load balancing route to proxy through named upstream")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,23 +360,23 @@ func TestPublishConfigVersionOverridesOriginHostHeader(t *testing.T) {
|
||||
if !strings.Contains(result.Version.RenderedConfig, `proxy_ssl_name "git.arctel.net";`) {
|
||||
t.Fatal("expected rendered config to set proxy ssl name from origin host override")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass https://git.arctel.net;") {
|
||||
t.Fatal("expected rendered config to keep direct proxy_pass for hostname origin when resolvers are blank")
|
||||
if !strings.Contains(result.Version.RenderedConfig, "upstream backend_git_arctel_de_1 {") {
|
||||
t.Fatal("expected hostname origin to render named upstream")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass https://backend_git_arctel_de_1;") {
|
||||
t.Fatal("expected rendered config to proxy through named upstream for hostname origin")
|
||||
}
|
||||
if !strings.Contains(result.Version.SnapshotJSON, `"origin_host":"git.arctel.net"`) {
|
||||
t.Fatal("expected snapshot to include origin_host override")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublishConfigVersionUsesRuntimeResolverWhenConfigured(t *testing.T) {
|
||||
func TestPublishConfigVersionUsesNamedUpstreamForOriginBasePath(t *testing.T) {
|
||||
setupServiceTestDB(t)
|
||||
if err := model.UpdateOption("OpenRestyResolvers", "1.1.1.1, 8.8.8.8"); err != nil {
|
||||
t.Fatalf("UpdateOption OpenRestyResolvers failed: %v", err)
|
||||
}
|
||||
|
||||
_, err := CreateProxyRoute(ProxyRouteInput{
|
||||
Domain: "resolver.example.com",
|
||||
OriginURL: "https://origin.internal/api",
|
||||
OriginURL: "https://origin.internal/api/",
|
||||
Enabled: true,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -366,28 +387,16 @@ func TestPublishConfigVersionUsesRuntimeResolverWhenConfigured(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("PublishConfigVersion failed: %v", err)
|
||||
}
|
||||
if !strings.Contains(result.Version.MainConfig, "resolver 1.1.1.1 8.8.8.8 valid=30s ipv6=off;") {
|
||||
t.Fatal("expected main config to render configured resolver directive")
|
||||
if !strings.Contains(result.Version.RenderedConfig, "upstream backend_resolver_example_com_1 {") {
|
||||
t.Fatal("expected hostname origin with base path to still render named upstream")
|
||||
}
|
||||
if strings.Contains(result.Version.RenderedConfig, "upstream backend_resolver_example_com_1 {") {
|
||||
t.Fatal("expected hostname origin with base path to avoid named upstream block")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, `set $openflare_upstream "https://origin.internal";`) {
|
||||
t.Fatal("expected rendered config to use runtime upstream variable when resolvers are configured")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, `set $openflare_upstream_base_path "/api";`) {
|
||||
t.Fatal("expected rendered config to preserve origin base path for runtime-resolved origin")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass $openflare_upstream$openflare_upstream_base_path$request_uri;") {
|
||||
t.Fatal("expected rendered config to proxy via runtime-resolved upstream variable and base path when resolvers are configured")
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass https://backend_resolver_example_com_1/api/;") {
|
||||
t.Fatal("expected rendered config to preserve base path while proxying through named upstream")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublishConfigVersionUsesNamedUpstreamForHostnameOriginsWhenResolversConfigured(t *testing.T) {
|
||||
func TestPublishConfigVersionUsesNamedUpstreamForHostnameOrigins(t *testing.T) {
|
||||
setupServiceTestDB(t)
|
||||
if err := model.UpdateOption("OpenRestyResolvers", "1.1.1.1"); err != nil {
|
||||
t.Fatalf("UpdateOption OpenRestyResolvers failed: %v", err)
|
||||
}
|
||||
|
||||
_, err := CreateProxyRoute(ProxyRouteInput{
|
||||
Domain: "resolver-upstream.example.com",
|
||||
@@ -403,17 +412,17 @@ func TestPublishConfigVersionUsesNamedUpstreamForHostnameOriginsWhenResolversCon
|
||||
t.Fatalf("PublishConfigVersion failed: %v", err)
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "upstream backend_resolver_upstream_example_com_1 {") {
|
||||
t.Fatal("expected rendered config to define named upstream for hostname origin when resolvers are configured")
|
||||
t.Fatal("expected rendered config to define named upstream for hostname origin")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "server origin.internal resolve max_fails=3 fail_timeout=10s;") {
|
||||
t.Fatal("expected rendered config to mark hostname upstream server as resolve")
|
||||
if !strings.Contains(result.Version.RenderedConfig, "server origin.internal max_fails=3 fail_timeout=10s;") {
|
||||
t.Fatal("expected rendered config to include hostname upstream server entry")
|
||||
}
|
||||
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass https://backend_resolver_upstream_example_com_1;") {
|
||||
t.Fatal("expected rendered config to proxy through named upstream when resolver-backed hostname upstream is safe")
|
||||
t.Fatal("expected rendered config to proxy through named upstream for hostname origin")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublishConfigVersionKeepsDirectProxyPassForIPOrigins(t *testing.T) {
|
||||
func TestPublishConfigVersionUsesNamedUpstreamForIPOrigins(t *testing.T) {
|
||||
setupServiceTestDB(t)
|
||||
|
||||
_, err := CreateProxyRoute(ProxyRouteInput{
|
||||
@@ -442,10 +451,6 @@ func TestPublishConfigVersionKeepsDirectProxyPassForIPOrigins(t *testing.T) {
|
||||
|
||||
func TestPreviewConfigVersionCanDisableWebsocketHeaders(t *testing.T) {
|
||||
setupServiceTestDB(t)
|
||||
if err := model.UpdateOption("OpenRestyResolvers", ""); err != nil {
|
||||
t.Fatalf("UpdateOption OpenRestyResolvers failed: %v", err)
|
||||
}
|
||||
|
||||
_, err := CreateProxyRoute(ProxyRouteInput{
|
||||
Domain: "ws-off.example.com",
|
||||
OriginURL: "https://origin.internal",
|
||||
@@ -462,8 +467,11 @@ func TestPreviewConfigVersionCanDisableWebsocketHeaders(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("PreviewConfigVersion failed: %v", err)
|
||||
}
|
||||
if strings.Contains(preview.RenderedConfig, "proxy_http_version 1.1;") {
|
||||
t.Fatal("expected preview config to omit websocket proxy_http_version when disabled")
|
||||
if !strings.Contains(preview.RenderedConfig, "proxy_http_version 1.1;") {
|
||||
t.Fatal("expected preview config to keep HTTP/1.1 proxying for named upstream keepalive")
|
||||
}
|
||||
if !strings.Contains(preview.RenderedConfig, `proxy_set_header Connection "";`) {
|
||||
t.Fatal("expected preview config to clear connection header when websocket upgrades are disabled")
|
||||
}
|
||||
if strings.Contains(preview.RenderedConfig, "proxy_set_header Upgrade $http_upgrade;") {
|
||||
t.Fatal("expected preview config to omit websocket upgrade header when disabled")
|
||||
|
||||
Reference in New Issue
Block a user