From a7f8371096fce063d64d0ea3e780685a366c537b Mon Sep 17 00:00:00 2001 From: Valery Piashchynski Date: Thu, 27 Aug 2020 17:24:52 +0300 Subject: Issue with broken pipe properly handled --- service/http/handler.go | 27 +++++++++++++++++++-------- service/http/response.go | 16 +++++++++++++++- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/service/http/handler.go b/service/http/handler.go index ab7c382b..eca05483 100644 --- a/service/http/handler.go +++ b/service/http/handler.go @@ -1,15 +1,17 @@ package http import ( - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spiral/roadrunner" + "fmt" "net" "net/http" "strconv" "strings" "sync" "time" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/spiral/roadrunner" ) const ( @@ -130,13 +132,22 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // handleError sends error. func (h *Handler) handleError(w http.ResponseWriter, r *http.Request, err error, start time.Time) { - h.throw(EventError, &ErrorEvent{Request: r, Error: err, start: start, elapsed: time.Since(start)}) - - w.WriteHeader(500) - _, err = w.Write([]byte(err.Error())) - if err != nil { + // if pipe is broken, there is no sense to write the header + // in this case we just report about error + if err == errEPIPE { h.throw(EventError, &ErrorEvent{Request: r, Error: err, start: start, elapsed: time.Since(start)}) + return } + // ResponseWriter is ok, write the error code + w.WriteHeader(500) + _, err2 := w.Write([]byte(err.Error())) + // error during the writing to the ResponseWriter + if err2 != nil { + // concat original error with ResponseWriter error + h.throw(EventError, &ErrorEvent{Request: r, Error: errors.New(fmt.Sprintf("error: %v, during handle this error, ResponseWriter error occurred: %v", err, err2)), start: start, elapsed: time.Since(start)}) + return + } + h.throw(EventError, &ErrorEvent{Request: r, Error: err, start: start, elapsed: time.Since(start)}) } // handleResponse triggers response event. diff --git a/service/http/response.go b/service/http/response.go index 0942b3d2..045f56da 100644 --- a/service/http/response.go +++ b/service/http/response.go @@ -1,14 +1,21 @@ package http import ( - json "github.com/json-iterator/go" + "errors" "io" + "net" "net/http" + "os" "strings" + "syscall" + + json "github.com/json-iterator/go" "github.com/spiral/roadrunner" ) +var errEPIPE = errors.New("EPIPE(32) -> possibly connection reset by peer") + // Response handles PSR7 response logic. type Response struct { // Status contains response status. @@ -57,6 +64,13 @@ func (r *Response) Write(w http.ResponseWriter) error { if data, ok := r.body.([]byte); ok { _, err := w.Write(data) if err != nil { + if netErr, ok2 := err.(*net.OpError); ok2 { + if syscallErr, ok3 := netErr.Err.(*os.SyscallError); ok3 { + if syscallErr.Err == syscall.EPIPE { + return errEPIPE + } + } + } return err } } -- cgit v1.2.3