Added custom error

This commit is contained in:
Magnus Root 2026-04-01 12:52:09 +03:00
parent d609591010
commit 4a82783b84
5 changed files with 64 additions and 46 deletions

19
api.go
View file

@ -347,6 +347,25 @@ type stringWriter interface {
WriteString(s string) (int, error) WriteString(s string) (int, error)
} }
// getProxyNextUpstream формирует строку proxy_next_upstream из кодов в settings.
// Дефолт: error timeout invalid_header http_500 http_502 http_503 http_504
func getProxyNextUpstream(settings AppsSettings) string {
codes := "500,502,503,504"
if settings.ProxyNextUpstreamCodes.Valid && strings.TrimSpace(settings.ProxyNextUpstreamCodes.String) != "" {
codes = strings.TrimSpace(settings.ProxyNextUpstreamCodes.String)
}
base := "error timeout invalid_header"
parts := strings.Split(codes, ",")
for _, part := range parts {
code := strings.TrimSpace(part)
if code != "" {
base += " http_" + code
}
}
return base
}
// getMaxFails возвращает max_fails из AppsSettings или дефолтное значение 5 // getMaxFails возвращает max_fails из AppsSettings или дефолтное значение 5
func getMaxFails(settings AppsSettings) int { func getMaxFails(settings AppsSettings) int {
if settings.MaxFails.Valid && settings.MaxFails.Int64 >= 0 { if settings.MaxFails.Valid && settings.MaxFails.Int64 >= 0 {

2
db.go
View file

@ -160,6 +160,7 @@ func getAppsSettingsByClientTitle(db *sql.DB, clientTitle string) ([]AppsSetting
max_fails, max_fails,
fail_timeout, fail_timeout,
balancing_method, balancing_method,
proxy_next_upstream_codes,
custom_sw_nginx_ssl custom_sw_nginx_ssl
FROM apps_settings FROM apps_settings
WHERE client_title = $1 WHERE client_title = $1
@ -194,6 +195,7 @@ func getAppsSettingsByClientTitle(db *sql.DB, clientTitle string) ([]AppsSetting
&a.MaxFails, &a.MaxFails,
&a.FailTimeout, &a.FailTimeout,
&a.BalancingMethod, &a.BalancingMethod,
&a.ProxyNextUpstreamCodes,
&a.CustomSWNginxSSL, &a.CustomSWNginxSSL,
) )
if err != nil { if err != nil {

View file

@ -272,7 +272,7 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta
f.WriteString(fmt.Sprintf(" error_log /var/log/angie/%d_%s_error.log error;\n\n", res.L7ResourceID, res.ServerName)) f.WriteString(fmt.Sprintf(" error_log /var/log/angie/%d_%s_error.log error;\n\n", res.L7ResourceID, res.ServerName))
writeNetworkSettings(f, config) writeNetworkSettings(f, config)
writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug) writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug, getProxyNextUpstream(res.AppsSettings))
if hasCustomLocation { if hasCustomLocation {
log.Printf(" └─ Добавление location_angie_custom (отдельный блок) для l7ResourceID %d (HTTP, порт %d)", res.L7ResourceID, httpPort) log.Printf(" └─ Добавление location_angie_custom (отдельный блок) для l7ResourceID %d (HTTP, порт %d)", res.L7ResourceID, httpPort)
@ -325,7 +325,7 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta
} }
writeNetworkSettings(f, config) writeNetworkSettings(f, config)
writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug) writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug, getProxyNextUpstream(res.AppsSettings))
if hasCustomLocation { if hasCustomLocation {
log.Printf(" └─ Добавление location_angie_custom (отдельный блок) для l7ResourceID %d (HTTPS, порт %d)", res.L7ResourceID, httpsPort) log.Printf(" └─ Добавление location_angie_custom (отдельный блок) для l7ResourceID %d (HTTPS, порт %d)", res.L7ResourceID, httpsPort)
@ -399,26 +399,24 @@ func writeAngieSSLSettings(f *os.File, customSSL sql.NullString) {
} }
// writeStandardServerSettings записывает стандартные настройки сервера (Angie) // writeStandardServerSettings записывает стандартные настройки сервера (Angie)
func writeStandardServerSettings(f *os.File, customDirectives string, debug bool) { func writeStandardServerSettings(f *os.File, customDirectives string, debug bool, proxyNextUpstream string) {
settings := ` server_tokens off; f.WriteString(" server_tokens off;\n")
sendfile on; f.WriteString(" sendfile on;\n")
gzip on; f.WriteString(" gzip on;\n")
client_max_body_size 0; f.WriteString(" client_max_body_size 0;\n")
f.WriteString("\n")
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; f.WriteString(fmt.Sprintf(" proxy_next_upstream %s;\n", proxyNextUpstream))
proxy_http_version 1.1; f.WriteString(" proxy_http_version 1.1;\n")
f.WriteString("\n")
js_set $safe_host main.sanitizeHost; f.WriteString(" js_set $safe_host main.sanitizeHost;\n")
proxy_set_header X-Real-IP $remote_addr; f.WriteString(" proxy_set_header X-Real-IP $remote_addr;\n")
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; f.WriteString(" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n")
proxy_set_header Connection $proxy_connection; f.WriteString(" proxy_set_header Connection $proxy_connection;\n")
proxy_set_header Upgrade $http_upgrade; f.WriteString(" proxy_set_header Upgrade $http_upgrade;\n")
proxy_set_header Host $safe_host; f.WriteString(" proxy_set_header Host $safe_host;\n")
proxy_set_header X-Original-Host $host; f.WriteString(" proxy_set_header X-Original-Host $host;\n")
proxy_pass_header Date; f.WriteString(" proxy_pass_header Date;\n")
proxy_pass_header Server; f.WriteString(" proxy_pass_header Server;\n")
`
f.WriteString(settings)
if debug { if debug {
f.WriteString(" client_body_buffer_size 1m;\n") f.WriteString(" client_body_buffer_size 1m;\n")
} }
@ -426,24 +424,22 @@ func writeStandardServerSettings(f *os.File, customDirectives string, debug bool
} }
// writeNginxStandardSettings записывает стандартные настройки сервера (Nginx) // writeNginxStandardSettings записывает стандартные настройки сервера (Nginx)
func writeNginxStandardSettings(f *os.File, customDirectives string) { func writeNginxStandardSettings(f *os.File, customDirectives string, proxyNextUpstream string) {
settings := ` server_tokens off; f.WriteString(" server_tokens off;\n")
sendfile on; f.WriteString(" sendfile on;\n")
gzip on; f.WriteString(" gzip on;\n")
client_max_body_size 0; f.WriteString(" client_max_body_size 0;\n")
f.WriteString("\n")
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; f.WriteString(fmt.Sprintf(" proxy_next_upstream %s;\n", proxyNextUpstream))
proxy_http_version 1.1; f.WriteString(" proxy_http_version 1.1;\n")
f.WriteString("\n")
#proxy_set_header X-Real-IP $remote_addr; f.WriteString(" #proxy_set_header X-Real-IP $remote_addr;\n")
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; f.WriteString(" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n")
proxy_set_header Connection $proxy_connection; f.WriteString(" proxy_set_header Connection $proxy_connection;\n")
proxy_set_header Upgrade $http_upgrade; f.WriteString(" proxy_set_header Upgrade $http_upgrade;\n")
proxy_set_header Host $backend_host; f.WriteString(" proxy_set_header Host $backend_host;\n")
proxy_pass_header Date; f.WriteString(" proxy_pass_header Date;\n")
proxy_pass_header Server; f.WriteString(" proxy_pass_header Server;\n")
`
f.WriteString(settings)
writeCustomOrDefaultDirectives(f, customDirectives) writeCustomOrDefaultDirectives(f, customDirectives)
} }
@ -514,7 +510,7 @@ func generateAngieCustomServerBlock(f *os.File, config Config, res ResourceData,
res.L7ResourceID, sanitizeServerName(block.ServerName), block.Port)) res.L7ResourceID, sanitizeServerName(block.ServerName), block.Port))
writeNetworkSettings(f, config) writeNetworkSettings(f, config)
writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug) writeStandardServerSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesAngieCustom), debug, getProxyNextUpstream(res.AppsSettings))
// Кастомные location блоки из location_angie_custom (перед location /) // Кастомные location блоки из location_angie_custom (перед location /)
if customLocationStr != "" { if customLocationStr != "" {
@ -703,7 +699,7 @@ func generateNginxResourceConfig(filepath string, config Config, res ResourceDat
f.WriteString(" set_real_ip_from 172.16.0.0/12;\n") f.WriteString(" set_real_ip_from 172.16.0.0/12;\n")
f.WriteString(" real_ip_header X-Forwarded-For;\n") f.WriteString(" real_ip_header X-Forwarded-For;\n")
f.WriteString(" real_ip_recursive on;\n\n") f.WriteString(" real_ip_recursive on;\n\n")
writeNginxStandardSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesNginxCustom)) writeNginxStandardSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesNginxCustom), getProxyNextUpstream(res.AppsSettings))
if hasCustomNginxLocation && isFullNginxLocationBlock { if hasCustomNginxLocation && isFullNginxLocationBlock {
log.Printf(" └─ Добавление location_nginx_custom (отдельный блок) для l7ResourceID %d (HTTP, порт %d)", res.L7ResourceID, httpPort) log.Printf(" └─ Добавление location_nginx_custom (отдельный блок) для l7ResourceID %d (HTTP, порт %d)", res.L7ResourceID, httpPort)
@ -742,7 +738,7 @@ func generateNginxResourceConfig(filepath string, config Config, res ResourceDat
f.WriteString(" set_real_ip_from 172.16.0.0/12;\n") f.WriteString(" set_real_ip_from 172.16.0.0/12;\n")
f.WriteString(" real_ip_header X-Forwarded-For;\n") f.WriteString(" real_ip_header X-Forwarded-For;\n")
f.WriteString(" real_ip_recursive on;\n\n") f.WriteString(" real_ip_recursive on;\n\n")
writeNginxStandardSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesNginxCustom)) writeNginxStandardSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesNginxCustom), getProxyNextUpstream(res.AppsSettings))
if hasCustomNginxLocation && isFullNginxLocationBlock { if hasCustomNginxLocation && isFullNginxLocationBlock {
log.Printf(" └─ Добавление location_nginx_custom (отдельный блок) для l7ResourceID %d (HTTPS, порт %d)", res.L7ResourceID, httpsPort) log.Printf(" └─ Добавление location_nginx_custom (отдельный блок) для l7ResourceID %d (HTTPS, порт %d)", res.L7ResourceID, httpsPort)
@ -836,7 +832,7 @@ func generateCustomServerBlock(f *os.File, res ResourceData, block CustomServerB
f.WriteString(" real_ip_header X-Forwarded-For;\n") f.WriteString(" real_ip_header X-Forwarded-For;\n")
f.WriteString(" real_ip_recursive on;\n\n") f.WriteString(" real_ip_recursive on;\n\n")
writeNginxStandardSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesNginxCustom)) writeNginxStandardSettings(f, getCustomServerDirectives(res.AppsSettings.ServerDirectivesNginxCustom), getProxyNextUpstream(res.AppsSettings))
// Кастомные location блоки из location_nginx_custom (перед location /) // Кастомные location блоки из location_nginx_custom (перед location /)
if locationDirectives != "" && strings.Contains(locationDirectives, "location ") { if locationDirectives != "" && strings.Contains(locationDirectives, "location ") {

View file

@ -754,7 +754,7 @@ func writeSWStandardSettings(f *os.File, settings AppsSettings) {
f.WriteString(" sendfile on;\n") f.WriteString(" sendfile on;\n")
f.WriteString(" gzip on;\n\n") f.WriteString(" gzip on;\n\n")
f.WriteString(" proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;\n") f.WriteString(" proxy_next_upstream " + getProxyNextUpstream(settings) + ";\n")
f.WriteString(" proxy_http_version 1.1;\n\n") f.WriteString(" proxy_http_version 1.1;\n\n")
f.WriteString(" #proxy_set_header X-Real-IP $remote_addr;\n") f.WriteString(" #proxy_set_header X-Real-IP $remote_addr;\n")
@ -783,7 +783,7 @@ func writeSWStandardSettings(f *os.File, settings AppsSettings) {
f.WriteString(" client_max_body_size 1g;\n") f.WriteString(" client_max_body_size 1g;\n")
f.WriteString(" large_client_header_buffers 4 128k;\n\n") f.WriteString(" large_client_header_buffers 4 128k;\n\n")
f.WriteString(" proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;\n") f.WriteString(" proxy_next_upstream " + getProxyNextUpstream(settings) + ";\n")
f.WriteString(" proxy_http_version 1.1;\n") f.WriteString(" proxy_http_version 1.1;\n")
f.WriteString(" proxy_connect_timeout 3s;\n") f.WriteString(" proxy_connect_timeout 3s;\n")
f.WriteString(" proxy_busy_buffers_size 32k;\n") f.WriteString(" proxy_busy_buffers_size 32k;\n")

View file

@ -37,6 +37,7 @@ type AppsSettings struct {
MaxFails sql.NullInt64 // Количество неудачных попыток к origin (дефолт 5) MaxFails sql.NullInt64 // Количество неудачных попыток к origin (дефолт 5)
FailTimeout sql.NullInt64 // Время в секундах после которого origin снова доступен (дефолт 15) FailTimeout sql.NullInt64 // Время в секундах после которого origin снова доступен (дефолт 15)
BalancingMethod sql.NullString // Метод балансировки: least_conn, ip_hash, random и т.д. BalancingMethod sql.NullString // Метод балансировки: least_conn, ip_hash, random и т.д.
ProxyNextUpstreamCodes sql.NullString // HTTP-коды для proxy_next_upstream (дефолт: 500,502,503,504)
CustomSWNginxSSL sql.NullString // Кастомные SSL директивы для SW nginx - полностью заменяют дефолтные если заполнено CustomSWNginxSSL sql.NullString // Кастомные SSL директивы для SW nginx - полностью заменяют дефолтные если заполнено
} }