v2.30.0-pre4 15d9fe3

handler.go RawHistoryFolder

1// Package proxy implements the HTTP adapter for the reverse proxy.
2package proxy
3
4import (
5	"net/http"
6	"sync/atomic"
7
8	"github.com/bnema/zerowrap"
9
10	"github.com/bnema/gordon/internal/boundaries/in"
11)
12
13// Handler implements http.Handler for the reverse proxy.
14// It owns all HTTP-level concerns: concurrency limiting, body size enforcement,
15// transport selection, and reverse proxy execution.
16// Routing decisions are delegated to the ProxyService usecase.
17type Handler struct {
18	proxySvc          in.ProxyService
19	log               zerowrap.Logger
20	appTransport      http.RoundTripper
21	h2cTransport      http.RoundTripper
22	registryTransport http.RoundTripper
23	activeConns       atomic.Int64
24}
25
26// NewHandler creates a new proxy HTTP handler.
27func NewHandler(proxySvc in.ProxyService, log zerowrap.Logger) *Handler {
28	return &Handler{
29		proxySvc:          proxySvc,
30		log:               log,
31		appTransport:      newAppTransport(),
32		h2cTransport:      newH2CTransport(),
33		registryTransport: newRegistryTransport(),
34	}
35}
36
37// ServeHTTP handles incoming HTTP requests and proxies them to the appropriate backend.
38func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
39	cfg := h.proxySvc.ProxyConfig()
40
41	// SECURITY: Limit concurrent connections to prevent resource exhaustion.
42	if cfg.MaxConcurrentConns > 0 {
43		current := h.activeConns.Add(1)
44		if current > int64(cfg.MaxConcurrentConns) {
45			h.activeConns.Add(-1)
46			proxyError(w, "Service Unavailable", http.StatusServiceUnavailable)
47			return
48		}
49		defer h.activeConns.Add(-1)
50	}
51
52	// SECURITY: Limit request body size to prevent resource exhaustion.
53	if cfg.MaxBodySize > 0 {
54		r.Body = http.MaxBytesReader(w, r.Body, cfg.MaxBodySize)
55	}
56
57	// Enrich request context with fields for downstream logging
58	ctx := zerowrap.CtxWithFields(r.Context(), map[string]any{
59		zerowrap.FieldLayer:    "adapter",
60		zerowrap.FieldAdapter:  "http",
61		zerowrap.FieldMethod:   r.Method,
62		zerowrap.FieldPath:     r.URL.Path,
63		zerowrap.FieldHost:     r.Host,
64		zerowrap.FieldClientIP: r.RemoteAddr,
65	})
66	r = r.WithContext(ctx)
67	log := zerowrap.FromCtx(ctx)
68
69	// Check if this is the registry domain
70	if h.proxySvc.IsRegistryDomain(r.Host) {
71		log.Debug().Msg("routing request to registry")
72		h.forwardToRegistry(w, r, cfg.RegistryPort)
73		return
74	}
75
76	// Get target for this domain
77	log.Debug().Str("resolving_target_for", r.Host).Msg("looking up proxy target")
78	target, err := h.proxySvc.GetTarget(ctx, r.Host)
79	if err != nil {
80		log.Warn().Err(err).Msg("no route found for domain")
81		proxyError(w, "404 page not found", http.StatusNotFound)
82		return
83	}
84
85	log.Debug().
86		Str("host", target.Host).
87		Int("port", target.Port).
88		Str("container_id", target.ContainerID).
89		Msg("resolved proxy target")
90
91	h.forwardToTarget(w, r, target, cfg.MaxResponseSize)
92}

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 8

Tags 106

↑↓ moveenter openesc close