mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-11 17:56:37 +08:00
feat: split openresty settings into performance page
This commit is contained in:
@@ -116,6 +116,31 @@ const (
|
||||
nginxRouteConfigPlaceholder = "__ATSF_ROUTE_CONFIG__"
|
||||
)
|
||||
|
||||
var requiredMainConfigTemplatePlaceholders = []string{
|
||||
"{{OpenRestyWorkerProcesses}}",
|
||||
"{{OpenRestyWorkerConnections}}",
|
||||
"{{OpenRestyWorkerRlimitNofile}}",
|
||||
"{{OpenRestyEventsUseDirective}}",
|
||||
"{{OpenRestyEventsMultiAcceptDirective}}",
|
||||
"{{OpenRestyKeepaliveTimeout}}",
|
||||
"{{OpenRestyKeepaliveRequests}}",
|
||||
"{{OpenRestyClientHeaderTimeout}}",
|
||||
"{{OpenRestyClientBodyTimeout}}",
|
||||
"{{OpenRestySendTimeout}}",
|
||||
"{{OpenRestyProxyConnectTimeout}}",
|
||||
"{{OpenRestyProxySendTimeout}}",
|
||||
"{{OpenRestyProxyReadTimeout}}",
|
||||
"{{OpenRestyProxyBuffering}}",
|
||||
"{{OpenRestyProxyBuffers}}",
|
||||
"{{OpenRestyProxyBufferSize}}",
|
||||
"{{OpenRestyProxyBusyBuffersSize}}",
|
||||
"{{OpenRestyGzip}}",
|
||||
"{{OpenRestyGzipMinLength}}",
|
||||
"{{OpenRestyGzipCompLevel}}",
|
||||
"{{OpenRestyCacheBlock}}",
|
||||
"{{OpenRestyRouteConfigInclude}}",
|
||||
}
|
||||
|
||||
func ListConfigVersions() ([]*model.ConfigVersion, error) {
|
||||
return model.ListConfigVersions()
|
||||
}
|
||||
@@ -569,51 +594,77 @@ func renderRouteConfig(routes []*model.ProxyRoute) (string, []SupportFile, error
|
||||
}
|
||||
|
||||
func renderMainConfig(cfg openRestyConfigSnapshot) string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("# This file is generated by ATSFlare. Do not edit manually.\n")
|
||||
builder.WriteString(fmt.Sprintf("worker_processes %s;\n", cfg.WorkerProcesses))
|
||||
builder.WriteString(fmt.Sprintf("worker_rlimit_nofile %d;\n", cfg.WorkerRlimitNofile))
|
||||
builder.WriteString("pid logs/nginx.pid;\n\n")
|
||||
builder.WriteString("events {\n")
|
||||
builder.WriteString(fmt.Sprintf(" worker_connections %d;\n", cfg.WorkerConnections))
|
||||
if strings.TrimSpace(cfg.EventsUse) != "" {
|
||||
builder.WriteString(fmt.Sprintf(" use %s;\n", cfg.EventsUse))
|
||||
templateText := common.OpenRestyMainConfigTemplate
|
||||
if strings.TrimSpace(templateText) == "" {
|
||||
templateText = defaultOpenRestyMainConfigTemplate()
|
||||
}
|
||||
if cfg.EventsMultiAcceptEnabled {
|
||||
builder.WriteString(" multi_accept on;\n")
|
||||
return renderMainConfigTemplate(templateText, cfg)
|
||||
}
|
||||
|
||||
func ValidateOpenRestyMainConfigTemplate(templateText string) error {
|
||||
trimmed := strings.TrimSpace(templateText)
|
||||
if trimmed == "" {
|
||||
return errors.New("OpenRestyMainConfigTemplate 不能为空")
|
||||
}
|
||||
builder.WriteString("}\n\n")
|
||||
builder.WriteString("http {\n")
|
||||
builder.WriteString(" include mime.types;\n")
|
||||
builder.WriteString(" default_type application/octet-stream;\n")
|
||||
builder.WriteString(" sendfile on;\n")
|
||||
builder.WriteString(" tcp_nopush on;\n")
|
||||
builder.WriteString(" tcp_nodelay on;\n")
|
||||
builder.WriteString(fmt.Sprintf(" keepalive_timeout %d;\n", cfg.KeepaliveTimeout))
|
||||
builder.WriteString(fmt.Sprintf(" keepalive_requests %d;\n", cfg.KeepaliveRequests))
|
||||
builder.WriteString(fmt.Sprintf(" client_header_timeout %d;\n", cfg.ClientHeaderTimeout))
|
||||
builder.WriteString(fmt.Sprintf(" client_body_timeout %d;\n", cfg.ClientBodyTimeout))
|
||||
builder.WriteString(fmt.Sprintf(" send_timeout %d;\n", cfg.SendTimeout))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_connect_timeout %d;\n", cfg.ProxyConnectTimeout))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_send_timeout %d;\n", cfg.ProxySendTimeout))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_read_timeout %d;\n", cfg.ProxyReadTimeout))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_buffering %s;\n", onOff(cfg.ProxyBufferingEnabled)))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_buffers %s;\n", cfg.ProxyBuffers))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_buffer_size %s;\n", cfg.ProxyBufferSize))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_busy_buffers_size %s;\n", cfg.ProxyBusyBuffersSize))
|
||||
builder.WriteString(fmt.Sprintf(" gzip %s;\n", onOff(cfg.GzipEnabled)))
|
||||
builder.WriteString(fmt.Sprintf(" gzip_min_length %d;\n", cfg.GzipMinLength))
|
||||
builder.WriteString(fmt.Sprintf(" gzip_comp_level %d;\n", cfg.GzipCompLevel))
|
||||
if cfg.CacheEnabled {
|
||||
builder.WriteString(fmt.Sprintf(" proxy_cache_path %s levels=%s keys_zone=atsflare_cache:10m inactive=%s max_size=%s;\n", cfg.CachePath, cfg.CacheLevels, cfg.CacheInactive, cfg.CacheMaxSize))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_cache_key \"%s\";\n", cfg.CacheKeyTemplate))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_cache_lock %s;\n", onOff(cfg.CacheLockEnabled)))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_cache_lock_timeout %s;\n", cfg.CacheLockTimeout))
|
||||
builder.WriteString(fmt.Sprintf(" proxy_cache_use_stale %s;\n", cfg.CacheUseStale))
|
||||
for _, placeholder := range requiredMainConfigTemplatePlaceholders {
|
||||
if !strings.Contains(trimmed, placeholder) {
|
||||
return fmt.Errorf("OpenRestyMainConfigTemplate 必须保留占位符 %s", placeholder)
|
||||
}
|
||||
}
|
||||
builder.WriteString(fmt.Sprintf(" include %s;\n", nginxRouteConfigPlaceholder))
|
||||
builder.WriteString("}\n")
|
||||
return builder.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaultOpenRestyMainConfigTemplate() string {
|
||||
return common.OpenRestyMainConfigTemplate
|
||||
}
|
||||
|
||||
func renderMainConfigTemplate(templateText string, cfg openRestyConfigSnapshot) string {
|
||||
replacer := strings.NewReplacer(
|
||||
"{{OpenRestyWorkerProcesses}}", cfg.WorkerProcesses,
|
||||
"{{OpenRestyWorkerConnections}}", fmt.Sprintf("%d", cfg.WorkerConnections),
|
||||
"{{OpenRestyWorkerRlimitNofile}}", fmt.Sprintf("%d", cfg.WorkerRlimitNofile),
|
||||
"{{OpenRestyEventsUseDirective}}", renderTemplateDirective(cfg.EventsUse != "", fmt.Sprintf("use %s;", cfg.EventsUse)),
|
||||
"{{OpenRestyEventsMultiAcceptDirective}}", renderTemplateDirective(cfg.EventsMultiAcceptEnabled, "multi_accept on;"),
|
||||
"{{OpenRestyKeepaliveTimeout}}", fmt.Sprintf("%d", cfg.KeepaliveTimeout),
|
||||
"{{OpenRestyKeepaliveRequests}}", fmt.Sprintf("%d", cfg.KeepaliveRequests),
|
||||
"{{OpenRestyClientHeaderTimeout}}", fmt.Sprintf("%d", cfg.ClientHeaderTimeout),
|
||||
"{{OpenRestyClientBodyTimeout}}", fmt.Sprintf("%d", cfg.ClientBodyTimeout),
|
||||
"{{OpenRestySendTimeout}}", fmt.Sprintf("%d", cfg.SendTimeout),
|
||||
"{{OpenRestyProxyConnectTimeout}}", fmt.Sprintf("%d", cfg.ProxyConnectTimeout),
|
||||
"{{OpenRestyProxySendTimeout}}", fmt.Sprintf("%d", cfg.ProxySendTimeout),
|
||||
"{{OpenRestyProxyReadTimeout}}", fmt.Sprintf("%d", cfg.ProxyReadTimeout),
|
||||
"{{OpenRestyProxyBuffering}}", onOff(cfg.ProxyBufferingEnabled),
|
||||
"{{OpenRestyProxyBuffers}}", cfg.ProxyBuffers,
|
||||
"{{OpenRestyProxyBufferSize}}", cfg.ProxyBufferSize,
|
||||
"{{OpenRestyProxyBusyBuffersSize}}", cfg.ProxyBusyBuffersSize,
|
||||
"{{OpenRestyGzip}}", onOff(cfg.GzipEnabled),
|
||||
"{{OpenRestyGzipMinLength}}", fmt.Sprintf("%d", cfg.GzipMinLength),
|
||||
"{{OpenRestyGzipCompLevel}}", fmt.Sprintf("%d", cfg.GzipCompLevel),
|
||||
"{{OpenRestyCacheBlock}}", renderOpenRestyCacheTemplateBlock(cfg),
|
||||
"{{OpenRestyRouteConfigInclude}}", nginxRouteConfigPlaceholder,
|
||||
)
|
||||
return replacer.Replace(templateText)
|
||||
}
|
||||
|
||||
func renderTemplateDirective(enabled bool, statement string) string {
|
||||
if !enabled {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(" %s\n", statement)
|
||||
}
|
||||
|
||||
func renderOpenRestyCacheTemplateBlock(cfg openRestyConfigSnapshot) string {
|
||||
if !cfg.CacheEnabled {
|
||||
return ""
|
||||
}
|
||||
return strings.Join([]string{
|
||||
fmt.Sprintf(" proxy_cache_path %s levels=%s keys_zone=atsflare_cache:10m inactive=%s max_size=%s;", cfg.CachePath, cfg.CacheLevels, cfg.CacheInactive, cfg.CacheMaxSize),
|
||||
fmt.Sprintf(" proxy_cache_key \"%s\";", cfg.CacheKeyTemplate),
|
||||
fmt.Sprintf(" proxy_cache_lock %s;", onOff(cfg.CacheLockEnabled)),
|
||||
fmt.Sprintf(" proxy_cache_lock_timeout %s;", cfg.CacheLockTimeout),
|
||||
fmt.Sprintf(" proxy_cache_use_stale %s;", cfg.CacheUseStale),
|
||||
"",
|
||||
}, "\n")
|
||||
}
|
||||
|
||||
func onOff(value bool) string {
|
||||
|
||||
@@ -251,6 +251,45 @@ func TestCreateTLSCertificateRejectsInvalidPEM(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenRestyMainConfigTemplateRenderAndValidate(t *testing.T) {
|
||||
setupServiceTestDB(t)
|
||||
|
||||
customTemplate := strings.ReplaceAll(
|
||||
common.OpenRestyMainConfigTemplate,
|
||||
"pid logs/nginx.pid;",
|
||||
"pid logs/nginx.pid;\nworker_shutdown_timeout 10s;",
|
||||
)
|
||||
if err := ValidateOpenRestyMainConfigTemplate(customTemplate); err != nil {
|
||||
t.Fatalf("ValidateOpenRestyMainConfigTemplate failed: %v", err)
|
||||
}
|
||||
if err := model.UpdateOption("OpenRestyMainConfigTemplate", customTemplate); err != nil {
|
||||
t.Fatalf("UpdateOption OpenRestyMainConfigTemplate failed: %v", err)
|
||||
}
|
||||
|
||||
preview, err := PreviewConfigVersion()
|
||||
if err != nil {
|
||||
t.Fatalf("PreviewConfigVersion failed: %v", err)
|
||||
}
|
||||
if !strings.Contains(preview.MainConfig, "worker_shutdown_timeout 10s;") {
|
||||
t.Fatal("expected preview main config to include custom template content")
|
||||
}
|
||||
if strings.Contains(preview.MainConfig, "{{OpenRestyWorkerProcesses}}") {
|
||||
t.Fatal("expected preview main config placeholders to be rendered")
|
||||
}
|
||||
if !strings.Contains(preview.MainConfig, "include __ATSF_ROUTE_CONFIG__;") {
|
||||
t.Fatal("expected preview main config to preserve managed route include")
|
||||
}
|
||||
|
||||
invalidTemplate := strings.ReplaceAll(
|
||||
common.OpenRestyMainConfigTemplate,
|
||||
"{{OpenRestyRouteConfigInclude}}",
|
||||
"",
|
||||
)
|
||||
if err := ValidateOpenRestyMainConfigTemplate(invalidTemplate); err == nil {
|
||||
t.Fatal("expected template without managed route placeholder to fail validation")
|
||||
}
|
||||
}
|
||||
|
||||
func setupServiceTestDB(t *testing.T) {
|
||||
t.Helper()
|
||||
common.SQLitePath = filepath.Join(t.TempDir(), "service.db")
|
||||
|
||||
Reference in New Issue
Block a user