Merge branch v2.11 into v3.3

This commit is contained in:
kevinpollet 2025-03-27 09:29:32 +01:00
commit c910ceeb00
No known key found for this signature in database
GPG key ID: 0C9A5DDD1B292453
18 changed files with 144 additions and 86 deletions

View file

@ -2,6 +2,7 @@ package httputil
import (
"context"
"crypto/tls"
"errors"
"io"
stdlog "log"
@ -112,7 +113,13 @@ func ErrorHandlerWithContext(ctx context.Context, w http.ResponseWriter, err err
statusCode := ComputeStatusCode(err)
logger := log.Ctx(ctx)
logger.Debug().Err(err).Msgf("%d %s", statusCode, statusText(statusCode))
// Log the error with error level if it is a TLS error related to configuration.
if isTLSConfigError(err) {
logger.Error().Err(err).Msgf("%d %s", statusCode, statusText(statusCode))
} else {
logger.Debug().Err(err).Msgf("%d %s", statusCode, statusText(statusCode))
}
w.WriteHeader(statusCode)
if _, werr := w.Write([]byte(statusText(statusCode))); werr != nil {
@ -127,6 +134,22 @@ func statusText(statusCode int) string {
return http.StatusText(statusCode)
}
// isTLSConfigError returns true if the error is a TLS error which is related to configuration.
// We assume that if the error is a tls.RecordHeaderError or a tls.CertificateVerificationError,
// it is related to configuration, because the client should not send a TLS request to a non-TLS server,
// and the client configuration should allow to verify the server certificate.
func isTLSConfigError(err error) bool {
// tls.RecordHeaderError is returned when the client sends a TLS request to a non-TLS server.
var recordHeaderErr tls.RecordHeaderError
if errors.As(err, &recordHeaderErr) {
return true
}
// tls.CertificateVerificationError is returned when the server certificate cannot be verified.
var certVerificationErr *tls.CertificateVerificationError
return errors.As(err, &certVerificationErr)
}
// ComputeStatusCode computes the HTTP status code according to the given error.
func ComputeStatusCode(err error) int {
switch {

View file

@ -1,12 +1,15 @@
package httputil
import (
"crypto/tls"
"errors"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/traefik/traefik/v3/pkg/testhelpers"
)
@ -100,3 +103,46 @@ func Test_directorBuilder(t *testing.T) {
})
}
}
func Test_isTLSConfigError(t *testing.T) {
testCases := []struct {
desc string
err error
expected bool
}{
{
desc: "nil",
},
{
desc: "TLS ECHRejectionError",
err: &tls.ECHRejectionError{},
},
{
desc: "TLS AlertError",
err: tls.AlertError(0),
},
{
desc: "Random error",
err: errors.New("random error"),
},
{
desc: "TLS RecordHeaderError",
err: tls.RecordHeaderError{},
expected: true,
},
{
desc: "TLS CertificateVerificationError",
err: &tls.CertificateVerificationError{},
expected: true,
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
actual := isTLSConfigError(test.err)
require.Equal(t, test.expected, actual)
})
}
}