retry only on real network errors

Now retries only happen when actual network errors occur and not only
anymore based on the HTTP status code. This is because the backend could
also send this status codes as their normal interface and in that case
we don't want to retry.
This commit is contained in:
Marco Jantke 2017-05-03 10:20:33 +02:00 committed by Ludovic Fernandez
parent 131d8dd765
commit f79317a435
6 changed files with 202 additions and 9 deletions

40
server/errorhandler.go Normal file
View file

@ -0,0 +1,40 @@
package server
import (
"io"
"net"
"net/http"
"github.com/containous/traefik/middlewares"
)
// RecordingErrorHandler is an error handler, implementing the vulcand/oxy
// error handler interface, which is recording network errors by using the netErrorRecorder.
// In addition it sets a proper HTTP status code and body, depending on the type of error occurred.
type RecordingErrorHandler struct {
netErrorRecorder middlewares.NetErrorRecorder
}
// NewRecordingErrorHandler creates and returns a new instance of RecordingErrorHandler.
func NewRecordingErrorHandler(recorder middlewares.NetErrorRecorder) *RecordingErrorHandler {
return &RecordingErrorHandler{recorder}
}
func (eh *RecordingErrorHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, err error) {
statusCode := http.StatusInternalServerError
if e, ok := err.(net.Error); ok {
eh.netErrorRecorder.Record(req.Context())
if e.Timeout() {
statusCode = http.StatusGatewayTimeout
} else {
statusCode = http.StatusBadGateway
}
} else if err == io.EOF {
eh.netErrorRecorder.Record(req.Context())
statusCode = http.StatusBadGateway
}
w.WriteHeader(statusCode)
w.Write([]byte(http.StatusText(statusCode)))
}