Files
dokku/plugins/nginx-vhosts/report.go
Jose Diaz-Gonzalez 7ee882c4e7 feat: port nginx :report subcommand to golang
The bash :report implementation for the nginx-vhosts plugin is replaced with a compiled golang binary that reuses the plugin's existing golang property getters, so every raw, global and computed key is unchanged while collection runs in parallel and json is marshalled directly. The global report keeps its existing behaviour of surfacing only the global keys.
2026-07-07 07:12:59 -04:00

115 lines
5.2 KiB
Go

package nginxvhosts
import (
"os"
"strconv"
"strings"
"github.com/dokku/dokku/plugins/common"
)
type nginxReportProp struct {
name string
appFn common.ReportFunc
computedFn common.ReportFunc
globalFn common.ReportFunc
}
func wrapGlobal(fn func() string) common.ReportFunc {
return func(string) string { return fn() }
}
func nginxReportProps() []nginxReportProp {
return []nginxReportProp{
{"access-log-format", AppAccessLogFormat, ComputedAccessLogFormat, wrapGlobal(GlobalAccessLogFormat)},
{"access-log-path", AppAccessLogPath, ComputedAccessLogPath, wrapGlobal(GlobalAccessLogPath)},
{"bind-address-ipv4", AppBindAddressIPv4, ComputedBindAddressIPv4, wrapGlobal(GlobalBindAddressIPv4)},
{"bind-address-ipv6", AppBindAddressIPv6, ComputedBindAddressIPv6, wrapGlobal(GlobalBindAddressIPv6)},
{"client-body-timeout", AppClientBodyTimeout, ComputedClientBodyTimeout, wrapGlobal(GlobalClientBodyTimeout)},
{"client-header-timeout", AppClientHeaderTimeout, ComputedClientHeaderTimeout, wrapGlobal(GlobalClientHeaderTimeout)},
{"client-max-body-size", AppClientMaxBodySize, ComputedClientMaxBodySize, wrapGlobal(GlobalClientMaxBodySize)},
{"disable-custom-config", AppDisableCustomConfig, ComputedDisableCustomConfig, wrapGlobal(GlobalDisableCustomConfig)},
{"error-log-path", AppErrorLogPath, ComputedErrorLogPath, wrapGlobal(GlobalErrorLogPath)},
{"hsts-include-subdomains", AppHSTSIncludeSubdomains, ComputedHSTSIncludeSubdomains, wrapGlobal(GlobalHSTSIncludeSubdomains)},
{"hsts-max-age", AppHSTSMaxAge, ComputedHSTSMaxAge, wrapGlobal(GlobalHSTSMaxAge)},
{"hsts-preload", AppHSTSPreload, ComputedHSTSPreload, wrapGlobal(GlobalHSTSPreload)},
{"hsts", AppHSTS, ComputedHSTS, wrapGlobal(GlobalHSTS)},
{"keepalive-timeout", AppKeepaliveTimeout, ComputedKeepaliveTimeout, wrapGlobal(GlobalKeepaliveTimeout)},
{"lingering-timeout", AppLingeringTimeout, ComputedLingeringTimeout, wrapGlobal(GlobalLingeringTimeout)},
{"nginx-conf-sigil-path", AppNginxConfSigilPath, ComputedNginxConfSigilPath, wrapGlobal(GlobalNginxConfSigilPath)},
{"nginx-service-command", AppNginxServiceCommand, ComputedNginxServiceCommand, wrapGlobal(GlobalNginxServiceCommand)},
{"proxy-buffer-size", AppProxyBufferSize, ComputedProxyBufferSize, wrapGlobal(GlobalProxyBufferSize)},
{"proxy-buffering", AppProxyBuffering, ComputedProxyBuffering, wrapGlobal(GlobalProxyBuffering)},
{"proxy-buffers", AppProxyBuffers, ComputedProxyBuffers, wrapGlobal(GlobalProxyBuffers)},
{"proxy-busy-buffers-size", AppProxyBusyBuffersSize, ComputedProxyBusyBuffersSize, wrapGlobal(GlobalProxyBusyBuffersSize)},
{"proxy-connect-timeout", AppProxyConnectTimeout, ComputedProxyConnectTimeout, wrapGlobal(GlobalProxyConnectTimeout)},
{"proxy-keepalive", AppProxyKeepalive, ComputedProxyKeepalive, wrapGlobal(GlobalProxyKeepalive)},
{"proxy-read-timeout", AppProxyReadTimeout, ComputedProxyReadTimeout, wrapGlobal(GlobalProxyReadTimeout)},
{"proxy-send-timeout", AppProxySendTimeout, ComputedProxySendTimeout, wrapGlobal(GlobalProxySendTimeout)},
{"send-timeout", AppSendTimeout, ComputedSendTimeout, wrapGlobal(GlobalSendTimeout)},
{"underscore-in-headers", AppUnderscoreInHeaders, ComputedUnderscoreInHeaders, wrapGlobal(GlobalUnderscoreInHeaders)},
{"x-forwarded-for-value", AppXForwardedForValue, ComputedXForwardedForValue, wrapGlobal(GlobalXForwardedForValue)},
{"x-forwarded-port-value", AppXForwardedPortValue, ComputedXForwardedPortValue, wrapGlobal(GlobalXForwardedPortValue)},
{"x-forwarded-proto-value", AppXForwardedProtoValue, ComputedXForwardedProtoValue, wrapGlobal(GlobalXForwardedProtoValue)},
{"x-forwarded-ssl", AppXForwardedSSL, ComputedXForwardedSSL, wrapGlobal(GlobalXForwardedSSL)},
}
}
// ReportSingleApp is an internal function that displays the nginx report for one or more apps
func ReportSingleApp(appName string, format string, infoFlag string) error {
if appName != "--global" {
if err := common.VerifyAppName(appName); err != nil {
return err
}
}
isGlobal := appName == "--global"
flags := map[string]common.ReportFunc{}
for _, p := range nginxReportProps() {
flags["--nginx-"+p.name] = p.appFn
flags["--nginx-computed-"+p.name] = p.computedFn
flags["--nginx-global-"+p.name] = p.globalFn
}
flags["--nginx-last-visited-at"] = reportLastVisitedAt
if isGlobal {
for key := range flags {
if !strings.Contains(key, "-global-") {
delete(flags, key)
}
}
}
flagKeys := []string{}
for flagKey := range flags {
flagKeys = append(flagKeys, flagKey)
}
infoFlags := common.CollectReport(appName, infoFlag, flags)
return common.ReportSingleApp(common.ReportSingleAppInput{
ReportType: "nginx",
AppName: appName,
InfoFlag: infoFlag,
InfoFlags: infoFlags,
InfoFlagKeys: flagKeys,
Format: format,
TrimPrefix: true,
UppercaseFirstCharacter: true,
EmitLegacyPrefix: false,
})
}
func reportLastVisitedAt(appName string) string {
logPath := AppAccessLogPath(appName)
if logPath == "off" || logPath == "/dev/null" {
return ""
}
info, err := os.Stat(logPath)
if err != nil || !info.Mode().IsRegular() {
return ""
}
return strconv.FormatInt(info.ModTime().Unix(), 10)
}