detached 5c72601

refactor: extract startProxyServers helper from runServers

commit
5c7260102f36221567b6feb07d15d24232618ae3
author
brice · · 2026-03-22 18:53 UTC
parent
e4d9ea0
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +49 -43
M internal/app/run.go +49 -43
@@ -1796,49 +1796,9 @@ func runServers(ctx context.Context, v *viper.Viper, cfg Config, registryHandler
17961796
17971797 registrySrv, registryReady := startServer(fmt.Sprintf(":%d", cfg.Server.RegistryPort), registryHandler, "registry", nil, errChan, log)
17981798
1799- var proxySrv *http.Server
1800- var proxyReady <-chan struct{}
1801- var tlsSrv *http.Server
1802- var tlsReady <-chan struct{}
1803- if cfg.Server.TLSEnabled {
1804- if cfg.Server.TLSCertFile == "" || cfg.Server.TLSKeyFile == "" {
1805- return fmt.Errorf("server.tls_enabled=true requires both server.tls_cert_file and server.tls_key_file")
1806- }
1807- // When TLS is enabled, HTTP port becomes redirect-only.
1808- tlsPort := cfg.Server.TLSPort
1809- redirectHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1810- host := r.Host
1811- if h, _, err := net.SplitHostPort(host); err == nil {
1812- host = h
1813- } else if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
1814- host = strings.TrimSuffix(strings.TrimPrefix(host, "["), "]")
1815- }
1816- if tlsPort != 443 {
1817- host = net.JoinHostPort(host, strconv.Itoa(tlsPort))
1818- } else if strings.Contains(host, ":") {
1819- // Re-bracket bare IPv6 literal for the URL.
1820- host = "[" + host + "]"
1821- }
1822- target := "https://" + host + r.RequestURI
1823- http.Redirect(w, r, target, http.StatusPermanentRedirect)
1824- })
1825- proxySrv, proxyReady = startServer(fmt.Sprintf(":%d", cfg.Server.Port), redirectHandler, "proxy-redirect", nil, errChan, log)
1826- tlsSrv, tlsReady = startTLSServer(
1827- fmt.Sprintf(":%d", cfg.Server.TLSPort),
1828- proxyHandler,
1829- "proxy-tls",
1830- cfg.Server.TLSCertFile,
1831- cfg.Server.TLSKeyFile,
1832- errChan,
1833- log,
1834- )
1835- } else {
1836- // Enable both HTTP/1.1 and cleartext HTTP/2 on the proxy server so Gordon can
1837- // accept h2c traffic from clients and load balancers (e.g. Cloudflare).
1838- var proxyProtos http.Protocols
1839- proxyProtos.SetHTTP1(true)
1840- proxyProtos.SetUnencryptedHTTP2(true)
1841- proxySrv, proxyReady = startServer(fmt.Sprintf(":%d", cfg.Server.Port), proxyHandler, "proxy", &proxyProtos, errChan, log)
1799+ proxySrv, proxyReady, tlsSrv, tlsReady, err := startProxyServers(cfg, proxyHandler, errChan, log)
1800+ if err != nil {
1801+ return err
18421802 }
18431803
18441804 // Wait for all enabled servers to bind their ports before auto-starting containers.
@@ -2119,6 +2079,52 @@ func gracefulShutdown(registrySrv, proxySrv, tlsSrv *http.Server, containerSvc *
21192079 log.Info().Msg("Gordon stopped")
21202080 }
21212081
2082+// startProxyServers sets up proxy server(s) depending on TLS configuration.
2083+// With TLS enabled, the HTTP port becomes a redirect-only server and a separate TLS server handles traffic.
2084+// Without TLS, a single server handles both HTTP/1.1 and cleartext HTTP/2.
2085+func startProxyServers(cfg Config, proxyHandler http.Handler, errChan chan<- error, log zerowrap.Logger) (*http.Server, <-chan struct{}, *http.Server, <-chan struct{}, error) {
2086+ if !cfg.Server.TLSEnabled {
2087+ var proxyProtos http.Protocols
2088+ proxyProtos.SetHTTP1(true)
2089+ proxyProtos.SetUnencryptedHTTP2(true)
2090+ srv, ready := startServer(fmt.Sprintf(":%d", cfg.Server.Port), proxyHandler, "proxy", &proxyProtos, errChan, log)
2091+ return srv, ready, nil, nil, nil
2092+ }
2093+
2094+ if cfg.Server.TLSCertFile == "" || cfg.Server.TLSKeyFile == "" {
2095+ return nil, nil, nil, nil, fmt.Errorf("server.tls_enabled=true requires both server.tls_cert_file and server.tls_key_file")
2096+ }
2097+
2098+ tlsPort := cfg.Server.TLSPort
2099+ redirectHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2100+ host := r.Host
2101+ if h, _, err := net.SplitHostPort(host); err == nil {
2102+ host = h
2103+ } else if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
2104+ host = strings.TrimSuffix(strings.TrimPrefix(host, "["), "]")
2105+ }
2106+ if tlsPort != 443 {
2107+ host = net.JoinHostPort(host, strconv.Itoa(tlsPort))
2108+ } else if strings.Contains(host, ":") {
2109+ host = "[" + host + "]"
2110+ }
2111+ target := "https://" + host + r.RequestURI
2112+ http.Redirect(w, r, target, http.StatusPermanentRedirect)
2113+ })
2114+
2115+ proxySrv, proxyReady := startServer(fmt.Sprintf(":%d", cfg.Server.Port), redirectHandler, "proxy-redirect", nil, errChan, log)
2116+ tlsSrv, tlsReady := startTLSServer(
2117+ fmt.Sprintf(":%d", cfg.Server.TLSPort),
2118+ proxyHandler,
2119+ "proxy-tls",
2120+ cfg.Server.TLSCertFile,
2121+ cfg.Server.TLSKeyFile,
2122+ errChan,
2123+ log,
2124+ )
2125+ return proxySrv, proxyReady, tlsSrv, tlsReady, nil
2126+}
2127+
21222128 // startServer starts an HTTP server, returning the server instance and a channel
21232129 // that closes once the listening socket is bound. This lets callers wait for the
21242130 // port to be ready before taking actions that depend on it (e.g. auto-start
@@ -1796,49 +1796,9 @@ func runServers(ctx context.Context, v *viper.Viper, cfg Config, registryHandler
1796 1796
1797 registrySrv, registryReady := startServer(fmt.Sprintf(":%d", cfg.Server.RegistryPort), registryHandler, "registry", nil, errChan, log)1797 registrySrv, registryReady := startServer(fmt.Sprintf(":%d", cfg.Server.RegistryPort), registryHandler, "registry", nil, errChan, log)
1798 1798
1799- var proxySrv *http.Server1799+ proxySrv, proxyReady, tlsSrv, tlsReady, err := startProxyServers(cfg, proxyHandler, errChan, log)
1800- var proxyReady <-chan struct{}1800+ if err != nil {
1801- var tlsSrv *http.Server1801+ return err
1802- var tlsReady <-chan struct{}
1803- if cfg.Server.TLSEnabled {
1804- if cfg.Server.TLSCertFile == "" || cfg.Server.TLSKeyFile == "" {
1805- return fmt.Errorf("server.tls_enabled=true requires both server.tls_cert_file and server.tls_key_file")
1806- }
1807- // When TLS is enabled, HTTP port becomes redirect-only.
1808- tlsPort := cfg.Server.TLSPort
1809- redirectHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1810- host := r.Host
1811- if h, _, err := net.SplitHostPort(host); err == nil {
1812- host = h
1813- } else if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
1814- host = strings.TrimSuffix(strings.TrimPrefix(host, "["), "]")
1815- }
1816- if tlsPort != 443 {
1817- host = net.JoinHostPort(host, strconv.Itoa(tlsPort))
1818- } else if strings.Contains(host, ":") {
1819- // Re-bracket bare IPv6 literal for the URL.
1820- host = "[" + host + "]"
1821- }
1822- target := "https://" + host + r.RequestURI
1823- http.Redirect(w, r, target, http.StatusPermanentRedirect)
1824- })
1825- proxySrv, proxyReady = startServer(fmt.Sprintf(":%d", cfg.Server.Port), redirectHandler, "proxy-redirect", nil, errChan, log)
1826- tlsSrv, tlsReady = startTLSServer(
1827- fmt.Sprintf(":%d", cfg.Server.TLSPort),
1828- proxyHandler,
1829- "proxy-tls",
1830- cfg.Server.TLSCertFile,
1831- cfg.Server.TLSKeyFile,
1832- errChan,
1833- log,
1834- )
1835- } else {
1836- // Enable both HTTP/1.1 and cleartext HTTP/2 on the proxy server so Gordon can
1837- // accept h2c traffic from clients and load balancers (e.g. Cloudflare).
1838- var proxyProtos http.Protocols
1839- proxyProtos.SetHTTP1(true)
1840- proxyProtos.SetUnencryptedHTTP2(true)
1841- proxySrv, proxyReady = startServer(fmt.Sprintf(":%d", cfg.Server.Port), proxyHandler, "proxy", &proxyProtos, errChan, log)
1842 }1802 }
1843 1803
1844 // Wait for all enabled servers to bind their ports before auto-starting containers.1804 // Wait for all enabled servers to bind their ports before auto-starting containers.
@@ -2119,6 +2079,52 @@ func gracefulShutdown(registrySrv, proxySrv, tlsSrv *http.Server, containerSvc *
2119 log.Info().Msg("Gordon stopped")2079 log.Info().Msg("Gordon stopped")
2120 }2080 }
2121 2081
2082+// startProxyServers sets up proxy server(s) depending on TLS configuration.
2083+// With TLS enabled, the HTTP port becomes a redirect-only server and a separate TLS server handles traffic.
2084+// Without TLS, a single server handles both HTTP/1.1 and cleartext HTTP/2.
2085+func startProxyServers(cfg Config, proxyHandler http.Handler, errChan chan<- error, log zerowrap.Logger) (*http.Server, <-chan struct{}, *http.Server, <-chan struct{}, error) {
2086+ if !cfg.Server.TLSEnabled {
2087+ var proxyProtos http.Protocols
2088+ proxyProtos.SetHTTP1(true)
2089+ proxyProtos.SetUnencryptedHTTP2(true)
2090+ srv, ready := startServer(fmt.Sprintf(":%d", cfg.Server.Port), proxyHandler, "proxy", &proxyProtos, errChan, log)
2091+ return srv, ready, nil, nil, nil
2092+ }
2093+
2094+ if cfg.Server.TLSCertFile == "" || cfg.Server.TLSKeyFile == "" {
2095+ return nil, nil, nil, nil, fmt.Errorf("server.tls_enabled=true requires both server.tls_cert_file and server.tls_key_file")
2096+ }
2097+
2098+ tlsPort := cfg.Server.TLSPort
2099+ redirectHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2100+ host := r.Host
2101+ if h, _, err := net.SplitHostPort(host); err == nil {
2102+ host = h
2103+ } else if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
2104+ host = strings.TrimSuffix(strings.TrimPrefix(host, "["), "]")
2105+ }
2106+ if tlsPort != 443 {
2107+ host = net.JoinHostPort(host, strconv.Itoa(tlsPort))
2108+ } else if strings.Contains(host, ":") {
2109+ host = "[" + host + "]"
2110+ }
2111+ target := "https://" + host + r.RequestURI
2112+ http.Redirect(w, r, target, http.StatusPermanentRedirect)
2113+ })
2114+
2115+ proxySrv, proxyReady := startServer(fmt.Sprintf(":%d", cfg.Server.Port), redirectHandler, "proxy-redirect", nil, errChan, log)
2116+ tlsSrv, tlsReady := startTLSServer(
2117+ fmt.Sprintf(":%d", cfg.Server.TLSPort),
2118+ proxyHandler,
2119+ "proxy-tls",
2120+ cfg.Server.TLSCertFile,
2121+ cfg.Server.TLSKeyFile,
2122+ errChan,
2123+ log,
2124+ )
2125+ return proxySrv, proxyReady, tlsSrv, tlsReady, nil
2126+}
2127+
2122 // startServer starts an HTTP server, returning the server instance and a channel2128 // startServer starts an HTTP server, returning the server instance and a channel
2123 // that closes once the listening socket is bound. This lets callers wait for the2129 // that closes once the listening socket is bound. This lets callers wait for the
2124 // port to be ready before taking actions that depend on it (e.g. auto-start2130 // port to be ready before taking actions that depend on it (e.g. auto-start

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close