summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-08-28 14:56:01 +0000
committerGitHub <[email protected]>2020-08-28 14:56:01 +0000
commitfea88ad23d8686ec6ddbeb48f5cfc7b2640c036e (patch)
treee8b33245bf9b2862d43a003c8713ea07445868e6
parent9103939fa98de53170d2bf0e8cd74529786d7ab2 (diff)
parent1911de96bea8c30293bc192e22940646f9f5a9d2 (diff)
Merge #355
355: Broken pipe issue r=48d90782 a=48d90782 - The issue with the broken pipe properly handled - superfluous response.WriteHeader issue fixed Co-authored-by: Valery Piashchynski <[email protected]>
-rw-r--r--service/http/errors.go25
-rw-r--r--service/http/errors_windows.go27
-rw-r--r--service/http/handler.go27
-rw-r--r--service/http/response.go6
4 files changed, 75 insertions, 10 deletions
diff --git a/service/http/errors.go b/service/http/errors.go
new file mode 100644
index 00000000..fb8762ef
--- /dev/null
+++ b/service/http/errors.go
@@ -0,0 +1,25 @@
+// +build !windows
+
+package http
+
+import (
+ "errors"
+ "net"
+ "os"
+ "syscall"
+)
+
+// Broken pipe
+var errEPIPE = errors.New("EPIPE(32) -> connection reset by peer")
+
+// handleWriteError just check if error was caused by aborted connection on linux
+func handleWriteError(err error) error {
+ if netErr, ok2 := err.(*net.OpError); ok2 {
+ if syscallErr, ok3 := netErr.Err.(*os.SyscallError); ok3 {
+ if syscallErr.Err == syscall.EPIPE {
+ return errEPIPE
+ }
+ }
+ }
+ return err
+}
diff --git a/service/http/errors_windows.go b/service/http/errors_windows.go
new file mode 100644
index 00000000..3d0ba04c
--- /dev/null
+++ b/service/http/errors_windows.go
@@ -0,0 +1,27 @@
+// +build windows
+
+package http
+
+import (
+ "errors"
+ "net"
+ "os"
+ "syscall"
+)
+
+//Software caused connection abort.
+//An established connection was aborted by the software in your host computer,
+//possibly due to a data transmission time-out or protocol error.
+var errEPIPE = errors.New("WSAECONNABORTED (10053) -> an established connection was aborted by peer")
+
+// handleWriteError just check if error was caused by aborted connection on windows
+func handleWriteError(err error) error {
+ if netErr, ok2 := err.(*net.OpError); ok2 {
+ if syscallErr, ok3 := netErr.Err.(*os.SyscallError); ok3 {
+ if syscallErr.Err == syscall.WSAECONNABORTED {
+ return errEPIPE
+ }
+ }
+ }
+ return err
+}
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..f34754be 100644
--- a/service/http/response.go
+++ b/service/http/response.go
@@ -1,14 +1,16 @@
package http
import (
- json "github.com/json-iterator/go"
"io"
"net/http"
"strings"
+ json "github.com/json-iterator/go"
+
"github.com/spiral/roadrunner"
)
+
// Response handles PSR7 response logic.
type Response struct {
// Status contains response status.
@@ -57,7 +59,7 @@ func (r *Response) Write(w http.ResponseWriter) error {
if data, ok := r.body.([]byte); ok {
_, err := w.Write(data)
if err != nil {
- return err
+ return handleWriteError(err)
}
}