Merge branch 'master' into net-wal

pull/7046/head
Mohammed Al Sahaf 2025-06-02 20:13:47 +03:00 committed by GitHub
commit e2104d3235
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 51 additions and 60 deletions

View File

@ -19,6 +19,7 @@ import (
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
"fmt" "fmt"
"maps"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"reflect" "reflect"
@ -335,9 +336,7 @@ func TestAdminHandlerBuiltinRouteErrors(t *testing.T) {
func testGetMetricValue(labels map[string]string) float64 { func testGetMetricValue(labels map[string]string) float64 {
promLabels := prometheus.Labels{} promLabels := prometheus.Labels{}
for k, v := range labels { maps.Copy(promLabels, labels)
promLabels[k] = v
}
metric, err := adminMetrics.requestErrors.GetMetricWith(promLabels) metric, err := adminMetrics.requestErrors.GetMetricWith(promLabels)
if err != nil { if err != nil {
@ -377,9 +376,7 @@ func (m *mockModule) CaddyModule() ModuleInfo {
func TestNewAdminHandlerRouterRegistration(t *testing.T) { func TestNewAdminHandlerRouterRegistration(t *testing.T) {
originalModules := make(map[string]ModuleInfo) originalModules := make(map[string]ModuleInfo)
for k, v := range modules { maps.Copy(originalModules, modules)
originalModules[k] = v
}
defer func() { defer func() {
modules = originalModules modules = originalModules
}() }()
@ -479,9 +476,7 @@ func TestAdminRouterProvisioning(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
originalModules := make(map[string]ModuleInfo) originalModules := make(map[string]ModuleInfo)
for k, v := range modules { maps.Copy(originalModules, modules)
originalModules[k] = v
}
defer func() { defer func() {
modules = originalModules modules = originalModules
}() }()
@ -774,9 +769,7 @@ func (m *mockIssuerModule) CaddyModule() ModuleInfo {
func TestManageIdentity(t *testing.T) { func TestManageIdentity(t *testing.T) {
originalModules := make(map[string]ModuleInfo) originalModules := make(map[string]ModuleInfo)
for k, v := range modules { maps.Copy(originalModules, modules)
originalModules[k] = v
}
defer func() { defer func() {
modules = originalModules modules = originalModules
}() }()

View File

@ -16,6 +16,7 @@ package httpcaddyfile
import ( import (
"encoding/json" "encoding/json"
"maps"
"net" "net"
"slices" "slices"
"sort" "sort"
@ -365,9 +366,7 @@ func parseSegmentAsConfig(h Helper) ([]ConfigValue, error) {
// copy existing matcher definitions so we can augment // copy existing matcher definitions so we can augment
// new ones that are defined only in this scope // new ones that are defined only in this scope
matcherDefs := make(map[string]caddy.ModuleMap, len(h.matcherDefs)) matcherDefs := make(map[string]caddy.ModuleMap, len(h.matcherDefs))
for key, val := range h.matcherDefs { maps.Copy(matcherDefs, h.matcherDefs)
matcherDefs[key] = val
}
// find and extract any embedded matcher definitions in this scope // find and extract any embedded matcher definitions in this scope
for i := 0; i < len(segments); i++ { for i := 0; i < len(segments); i++ {
@ -483,12 +482,29 @@ func sortRoutes(routes []ConfigValue) {
// we can only confidently compare path lengths if both // we can only confidently compare path lengths if both
// directives have a single path to match (issue #5037) // directives have a single path to match (issue #5037)
if iPathLen > 0 && jPathLen > 0 { if iPathLen > 0 && jPathLen > 0 {
// trim the trailing wildcard if there is one
iPathTrimmed := strings.TrimSuffix(iPM[0], "*")
jPathTrimmed := strings.TrimSuffix(jPM[0], "*")
// if both paths are the same except for a trailing wildcard, // if both paths are the same except for a trailing wildcard,
// sort by the shorter path first (which is more specific) // sort by the shorter path first (which is more specific)
if strings.TrimSuffix(iPM[0], "*") == strings.TrimSuffix(jPM[0], "*") { if iPathTrimmed == jPathTrimmed {
return iPathLen < jPathLen return iPathLen < jPathLen
} }
// we use the trimmed length to compare the paths
// https://github.com/caddyserver/caddy/issues/7012#issuecomment-2870142195
// credit to https://github.com/Hellio404
// for sorts with many items, mixing matchers w/ and w/o wildcards will confuse the sort and result in incorrect orders
iPathLen = len(iPathTrimmed)
jPathLen = len(jPathTrimmed)
// if both paths have the same length, sort lexically
// https://github.com/caddyserver/caddy/pull/7015#issuecomment-2871993588
if iPathLen == jPathLen {
return iPathTrimmed < jPathTrimmed
}
// sort most-specific (longest) path first // sort most-specific (longest) path first
return iPathLen > jPathLen return iPathLen > jPathLen
} }

View File

@ -24,6 +24,7 @@ import (
"io" "io"
"io/fs" "io/fs"
"log" "log"
"maps"
"net" "net"
"net/http" "net/http"
"os" "os"
@ -703,9 +704,7 @@ func AdminAPIRequest(adminAddr, method, uri string, headers http.Header, body io
if body != nil { if body != nil {
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
} }
for k, v := range headers { maps.Copy(req.Header, headers)
req.Header[k] = v
}
// make an HTTP client that dials our network type, since admin // make an HTTP client that dials our network type, since admin
// endpoints aren't always TCP, which is what the default transport // endpoints aren't always TCP, which is what the default transport

View File

@ -300,8 +300,10 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c
info, err := fs.Stat(fileSystem, filename) info, err := fs.Stat(fileSystem, filename)
if err != nil { if err != nil {
err = fsrv.mapDirOpenError(fileSystem, err, filename) err = fsrv.mapDirOpenError(fileSystem, err, filename)
if errors.Is(err, fs.ErrNotExist) || errors.Is(err, fs.ErrInvalid) { if errors.Is(err, fs.ErrNotExist) {
return fsrv.notFound(w, r, next) return fsrv.notFound(w, r, next)
} else if errors.Is(err, fs.ErrInvalid) {
return caddyhttp.Error(http.StatusBadRequest, err)
} else if errors.Is(err, fs.ErrPermission) { } else if errors.Is(err, fs.ErrPermission) {
return caddyhttp.Error(http.StatusForbidden, err) return caddyhttp.Error(http.StatusForbidden, err)
} }
@ -611,6 +613,11 @@ func (fsrv *FileServer) mapDirOpenError(fileSystem fs.FS, originalErr error, nam
return originalErr return originalErr
} }
var pathErr *fs.PathError
if errors.As(originalErr, &pathErr) {
return fs.ErrInvalid
}
parts := strings.Split(name, separator) parts := strings.Split(name, separator)
for i := range parts { for i := range parts {
if parts[i] == "" { if parts[i] == "" {

View File

@ -118,6 +118,11 @@ func (irh interceptedResponseHandler) WriteHeader(statusCode int) {
irh.ResponseRecorder.WriteHeader(statusCode) irh.ResponseRecorder.WriteHeader(statusCode)
} }
// EXPERIMENTAL: Subject to change or removal.
func (irh interceptedResponseHandler) Unwrap() http.ResponseWriter {
return irh.ResponseRecorder
}
// EXPERIMENTAL: Subject to change or removal. // EXPERIMENTAL: Subject to change or removal.
func (ir Intercept) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { func (ir Intercept) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
buf := bufPool.Get().(*bytes.Buffer) buf := bufPool.Get().(*bytes.Buffer)

View File

@ -17,6 +17,7 @@ package fastcgi
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"slices"
"strconv" "strconv"
"strings" "strings"
@ -314,7 +315,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
// if the index is turned off, we skip the redirect and try_files // if the index is turned off, we skip the redirect and try_files
if indexFile != "off" { if indexFile != "off" {
dirRedir := false var dirRedir bool
dirIndex := "{http.request.uri.path}/" + indexFile dirIndex := "{http.request.uri.path}/" + indexFile
tryPolicy := "first_exist_fallback" tryPolicy := "first_exist_fallback"
@ -328,13 +329,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
tryPolicy = "" tryPolicy = ""
} }
for _, tf := range tryFiles { dirRedir = slices.Contains(tryFiles, dirIndex)
if tf == dirIndex {
dirRedir = true
break
}
}
} }
if dirRedir { if dirRedir {

View File

@ -528,13 +528,7 @@ func (h *HTTPTransport) shouldUseTLS(req *http.Request) bool {
} }
port := req.URL.Port() port := req.URL.Port()
for i := range h.TLS.ExceptPorts { return !slices.Contains(h.TLS.ExceptPorts, port)
if h.TLS.ExceptPorts[i] == port {
return false
}
}
return true
} }
// TLSEnabled returns true if TLS is enabled. // TLSEnabled returns true if TLS is enabled.

View File

@ -22,6 +22,7 @@ import (
"net/http" "net/http"
"net/textproto" "net/textproto"
"os" "os"
"slices"
"strconv" "strconv"
"strings" "strings"
"text/template" "text/template"
@ -323,13 +324,7 @@ func cmdRespond(fl caddycmd.Flags) (int, error) {
// figure out if status code was explicitly specified; this lets // figure out if status code was explicitly specified; this lets
// us set a non-zero value as the default but is a little hacky // us set a non-zero value as the default but is a little hacky
var statusCodeFlagSpecified bool statusCodeFlagSpecified := slices.Contains(os.Args, "--status")
for _, fl := range os.Args {
if fl == "--status" {
statusCodeFlagSpecified = true
break
}
}
// try to determine what kind of parameter the unnamed argument is // try to determine what kind of parameter the unnamed argument is
if arg != "" { if arg != "" {

View File

@ -87,13 +87,7 @@ nextChoice:
} }
if len(p.AnyTag) > 0 { if len(p.AnyTag) > 0 {
var found bool found := slices.ContainsFunc(p.AnyTag, cert.HasTag)
for _, tag := range p.AnyTag {
if cert.HasTag(tag) {
found = true
break
}
}
if !found { if !found {
continue continue
} }

View File

@ -25,6 +25,7 @@ import (
"io" "io"
"os" "os"
"reflect" "reflect"
"slices"
"strings" "strings"
"github.com/mholt/acmez/v3" "github.com/mholt/acmez/v3"
@ -369,13 +370,7 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
} }
// ensure ALPN includes the ACME TLS-ALPN protocol // ensure ALPN includes the ACME TLS-ALPN protocol
var alpnFound bool alpnFound := slices.Contains(p.ALPN, acmez.ACMETLS1Protocol)
for _, a := range p.ALPN {
if a == acmez.ACMETLS1Protocol {
alpnFound = true
break
}
}
if !alpnFound && (cfg.NextProtos == nil || len(cfg.NextProtos) > 0) { if !alpnFound && (cfg.NextProtos == nil || len(cfg.NextProtos) > 0) {
cfg.NextProtos = append(cfg.NextProtos, acmez.ACMETLS1Protocol) cfg.NextProtos = append(cfg.NextProtos, acmez.ACMETLS1Protocol)
} }
@ -1004,11 +999,9 @@ func (l LeafCertClientAuth) VerifyClientCertificate(rawCerts [][]byte, _ [][]*x5
return fmt.Errorf("can't parse the given certificate: %s", err.Error()) return fmt.Errorf("can't parse the given certificate: %s", err.Error())
} }
for _, trustedLeafCert := range l.trustedLeafCerts { if slices.ContainsFunc(l.trustedLeafCerts, remoteLeafCert.Equal) {
if remoteLeafCert.Equal(trustedLeafCert) {
return nil return nil
} }
}
return fmt.Errorf("client leaf certificate failed validation") return fmt.Errorf("client leaf certificate failed validation")
} }