refactor(10.2-01): nest framework packages under modules

- Move remaining beach packages and embedded admin assets\n- Rewrite framework, example, build, and gate paths
This commit is contained in:
Jakub Zych
2026-09-28 02:21:02 +02:00
parent ac1f6d14f4
commit 5e50b166ef
277 changed files with 303 additions and 303 deletions

105
modules/surf/clientip.go Normal file
View File

@@ -0,0 +1,105 @@
package surf
import (
"net"
"net/http"
"net/netip"
"strings"
"git.golem15.com/golem15/summercms/modules/compass"
)
// ClientIP is the single source of client IP for limiter keys (D-04).
// RemoteAddr is used unless it parses as being inside one of trusted;
// in that case the rightmost X-Forwarded-For hop NOT inside any trusted
// prefix is used. An empty trusted list means RemoteAddr only.
func ClientIP(r *http.Request, trusted []netip.Prefix) string {
if r == nil {
return ""
}
remote := parseIP(r.RemoteAddr)
if len(trusted) == 0 || remote == (netip.Addr{}) || !addrTrusted(remote, trusted) {
if remote == (netip.Addr{}) {
return ""
}
return remote.String()
}
xff := r.Header.Get("X-Forwarded-For")
if xff == "" {
return remote.String()
}
hops := strings.Split(xff, ",")
for i := len(hops) - 1; i >= 0; i-- {
hop := strings.TrimSpace(hops[i])
if hop == "" {
continue
}
addr, err := netip.ParseAddr(hop)
if err != nil {
continue
}
addr = addr.Unmap()
if !addrTrusted(addr, trusted) {
return addr.String()
}
}
return remote.String()
}
// TrustedProxies reads http.trusted_proxies (a []string of CIDRs) from cfg
// and parses it once into []netip.Prefix. A malformed entry is skipped, not
// fatal (logged by the caller if desired).
func TrustedProxies(cfg *compass.Config) []netip.Prefix {
if cfg == nil {
return nil
}
raw, ok := cfg.Lookup("http.trusted_proxies")
if !ok {
return nil
}
var entries []string
switch v := raw.(type) {
case []string:
entries = v
case []any:
for _, item := range v {
s, _ := item.(string)
if s != "" {
entries = append(entries, s)
}
}
default:
return nil
}
var out []netip.Prefix
for _, e := range entries {
p, err := netip.ParsePrefix(strings.TrimSpace(e))
if err != nil {
continue
}
out = append(out, p)
}
return out
}
func parseIP(remoteAddr string) netip.Addr {
host, _, err := net.SplitHostPort(remoteAddr)
if err != nil {
host = remoteAddr
}
host = strings.Trim(host, "[]")
addr, err := netip.ParseAddr(host)
if err != nil {
return netip.Addr{}
}
return addr.Unmap()
}
func addrTrusted(addr netip.Addr, trusted []netip.Prefix) bool {
for _, p := range trusted {
if p.Contains(addr) {
return true
}
}
return false
}