[功能] 添加OpenResty解析器指令支持,增强配置模板和运行时解析能力

This commit is contained in:
ryan
2026-03-18 11:16:56 +08:00
parent bb284c2f37
commit 4c4f7f9ced
6 changed files with 165 additions and 5 deletions
+1 -1
View File
@@ -125,7 +125,7 @@ http {
gzip {{OpenRestyGzip}};
gzip_min_length {{OpenRestyGzipMinLength}};
gzip_comp_level {{OpenRestyGzipCompLevel}};
{{OpenRestyCacheBlock}} include {{OpenRestyRouteConfigInclude}};
{{OpenRestyResolverDirective}}{{OpenRestyCacheBlock}} include {{OpenRestyRouteConfigInclude}};
}
`
+36 -2
View File
@@ -124,6 +124,7 @@ const (
nginxLuaDirPlaceholder = "__OPENFLARE_LUA_DIR__"
nginxObservabilityListenPlaceholder = "__OPENFLARE_OBSERVABILITY_LISTEN__"
nginxObservabilityPortPlaceholder = "__OPENFLARE_OBSERVABILITY_PORT__"
nginxResolverDirectivePlaceholder = "__OPENFLARE_RESOLVER_DIRECTIVE__"
)
var requiredMainConfigTemplatePlaceholders = []string{
@@ -151,6 +152,7 @@ var requiredMainConfigTemplatePlaceholders = []string{
"{{OpenRestyGzip}}",
"{{OpenRestyGzipMinLength}}",
"{{OpenRestyGzipCompLevel}}",
"{{OpenRestyResolverDirective}}",
"{{OpenRestyCacheBlock}}",
"{{OpenRestyRouteConfigInclude}}",
}
@@ -671,6 +673,7 @@ func renderMainConfigTemplate(templateText string, cfg openRestyConfigSnapshot)
"{{OpenRestyGzip}}", onOff(cfg.GzipEnabled),
"{{OpenRestyGzipMinLength}}", fmt.Sprintf("%d", cfg.GzipMinLength),
"{{OpenRestyGzipCompLevel}}", fmt.Sprintf("%d", cfg.GzipCompLevel),
"{{OpenRestyResolverDirective}}", nginxResolverDirectivePlaceholder,
"{{OpenRestyCacheBlock}}", renderOpenRestyCacheTemplateBlock(cfg),
"{{OpenRestyRouteConfigInclude}}", nginxRouteConfigPlaceholder,
)
@@ -750,7 +753,7 @@ func nextVersionNumber(now time.Time) (string, error) {
}
func renderHTTPProxyServer(domain string, originURL string, originHost string, customHeaders []ProxyRouteCustomHeaderInput) string {
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s\n location / {\n%s proxy_pass %s;\n }\n}\n\n", domain, renderExactHostGuard(domain), renderProxyHeaderBlock(originURL, originHost, customHeaders), originURL)
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s\n location / {\n%s%s }\n}\n\n", domain, renderExactHostGuard(domain), renderProxyHeaderBlock(originURL, originHost, customHeaders), renderProxyPassBlock(originURL))
}
func renderHTTPRedirectServer(domain string) string {
@@ -760,7 +763,7 @@ func renderHTTPRedirectServer(domain string) string {
func renderHTTPSServer(domain string, originURL string, originHost string, certificateID uint, customHeaders []ProxyRouteCustomHeaderInput) 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 server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s\n location / {\n%s proxy_pass %s;\n }\n}\n\n", domain, certPath, keyPath, renderExactHostGuard(domain), renderProxyHeaderBlock(originURL, originHost, customHeaders), originURL)
return fmt.Sprintf("server {\n listen 443 ssl;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s\n location / {\n%s%s }\n}\n\n", domain, certPath, keyPath, renderExactHostGuard(domain), renderProxyHeaderBlock(originURL, originHost, customHeaders), renderProxyPassBlock(originURL))
}
func renderExactHostGuard(domain string) string {
@@ -795,6 +798,33 @@ func renderProxyHeaderBlock(originURL string, originHost string, customHeaders [
return builder.String()
}
func renderProxyPassBlock(originURL string) string {
parsed, err := url.Parse(originURL)
if err != nil || parsed.Host == "" || parsed.Scheme == "" {
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()
}
func resolveUpstreamServerName(originURL string, originHost string) string {
parsed, err := url.Parse(originURL)
if err != nil || !strings.EqualFold(parsed.Scheme, "https") {
@@ -811,6 +841,10 @@ func resolveUpstreamServerName(originURL string, originHost string) string {
}
func quoteNginxHeaderValue(value string) string {
return quoteNginxStringLiteral(value)
}
func quoteNginxStringLiteral(value string) string {
escaped := strings.ReplaceAll(value, `\`, `\\`)
escaped = strings.ReplaceAll(escaped, `"`, `\"`)
return fmt.Sprintf(`"%s"`, escaped)
@@ -63,6 +63,9 @@ func TestCreateTLSCertificateAndRenderHTTPSConfig(t *testing.T) {
if !strings.Contains(result.Version.MainConfig, "listen __OPENFLARE_OBSERVABILITY_LISTEN__;") {
t.Fatal("expected main config to include managed openresty observability listen placeholder")
}
if !strings.Contains(result.Version.MainConfig, "__OPENFLARE_RESOLVER_DIRECTIVE__") {
t.Fatal("expected main config to include managed resolver directive placeholder")
}
if strings.Contains(result.Version.MainConfig, "allow 127.0.0.1;") {
t.Fatal("expected main config to avoid hard-coded allow rules on observability server")
}
@@ -138,6 +141,12 @@ func TestPublishConfigVersionRendersCustomHeaders(t *testing.T) {
if !strings.Contains(result.Version.RenderedConfig, "proxy_set_header Connection $http_connection;") {
t.Fatal("expected rendered config to forward websocket connection header")
}
if !strings.Contains(result.Version.RenderedConfig, `set $openflare_upstream "https://origin.internal";`) {
t.Fatal("expected rendered config to defer upstream resolution via variable proxy_pass")
}
if !strings.Contains(result.Version.RenderedConfig, "proxy_pass $openflare_upstream$request_uri;") {
t.Fatal("expected rendered config to proxy via runtime-resolved upstream variable")
}
}
func TestPublishConfigVersionOverridesOriginHostHeader(t *testing.T) {
@@ -166,6 +175,9 @@ 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, `set $openflare_upstream "https://git.arctel.net";`) {
t.Fatal("expected rendered config to avoid resolving https upstream during config load")
}
if !strings.Contains(result.Version.SnapshotJSON, `"origin_host":"git.arctel.net"`) {
t.Fatal("expected snapshot to include origin_host override")
}