fix(reverseproxy): improve error handling for HTTP proxy errors and add suppress some HTTP2 and HTTP/3 error codes

This commit is contained in:
yusing
2025-09-10 23:20:23 +08:00
parent c9c5677b35
commit 7770ce7025

View File

@@ -24,6 +24,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/quic-go/quic-go/http3"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/yusing/go-proxy/internal/logging/accesslog" "github.com/yusing/go-proxy/internal/logging/accesslog"
@@ -31,6 +32,7 @@ import (
nettypes "github.com/yusing/go-proxy/internal/net/types" nettypes "github.com/yusing/go-proxy/internal/net/types"
U "github.com/yusing/go-proxy/internal/utils" U "github.com/yusing/go-proxy/internal/utils"
"golang.org/x/net/http/httpguts" "golang.org/x/net/http/httpguts"
"golang.org/x/net/http2"
) )
// A ProxyRequest contains a request to be rewritten by a [ReverseProxy]. // A ProxyRequest contains a request to be rewritten by a [ReverseProxy].
@@ -170,9 +172,9 @@ func copyHeader(dst, src http.Header) {
func (p *ReverseProxy) errorHandler(rw http.ResponseWriter, r *http.Request, err error, writeHeader bool) { func (p *ReverseProxy) errorHandler(rw http.ResponseWriter, r *http.Request, err error, writeHeader bool) {
reqURL := r.Host + r.URL.Path reqURL := r.Host + r.URL.Path
switch { switch {
case errors.Is(err, context.Canceled), case errors.Is(err, context.Canceled), errors.Is(err, io.EOF):
errors.Is(err, io.EOF), log.Trace().Err(err).Str("url", reqURL).Msg("http proxy error")
errors.Is(err, context.DeadlineExceeded): case errors.Is(err, context.DeadlineExceeded):
log.Debug().Err(err).Str("url", reqURL).Msg("http proxy error") log.Debug().Err(err).Str("url", reqURL).Msg("http proxy error")
default: default:
var recordErr tls.RecordHeaderError var recordErr tls.RecordHeaderError
@@ -182,11 +184,30 @@ func (p *ReverseProxy) errorHandler(rw http.ResponseWriter, r *http.Request, err
Msgf(`scheme was likely misconfigured as https, Msgf(`scheme was likely misconfigured as https,
try setting "proxy.%s.scheme" back to "http"`, p.TargetName) try setting "proxy.%s.scheme" back to "http"`, p.TargetName)
log.Err(err).Msg("underlying error") log.Err(err).Msg("underlying error")
} else { goto logged
log.Err(err).Str("url", reqURL).Msg("http proxy error")
} }
var h2Err http2.StreamError
if errors.As(err, &h2Err) {
// ignore these errors
switch h2Err.Code {
case http2.ErrCodeStreamClosed:
goto logged
}
}
var h3Err *http3.Error
if errors.As(err, &h3Err) {
// ignore these errors
switch h3Err.ErrorCode {
case
http3.ErrCodeNoError,
http3.ErrCodeRequestCanceled:
goto logged
}
}
log.Err(err).Str("url", reqURL).Msg("http proxy error")
} }
logged:
if writeHeader { if writeHeader {
rw.WriteHeader(http.StatusInternalServerError) rw.WriteHeader(http.StatusInternalServerError)
} }