summaryrefslogtreecommitdiff
path: root/pkg/worker_handler
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/worker_handler')
-rw-r--r--pkg/worker_handler/handler.go56
-rw-r--r--pkg/worker_handler/request.go6
-rw-r--r--pkg/worker_handler/response.go6
3 files changed, 46 insertions, 22 deletions
diff --git a/pkg/worker_handler/handler.go b/pkg/worker_handler/handler.go
index e0d1aae0..0ff23d9d 100644
--- a/pkg/worker_handler/handler.go
+++ b/pkg/worker_handler/handler.go
@@ -57,25 +57,27 @@ func (e *ResponseEvent) Elapsed() time.Duration {
// Handler serves http connections to underlying PHP application using PSR-7 protocol. Context will include request headers,
// parsed files and query, payload will include parsed form dataTree (if any).
type Handler struct {
- maxRequestSize uint64
- uploads config.Uploads
- trusted config.Cidrs
- log logger.Logger
- pool pool.Pool
- mul sync.Mutex
- lsn events.Listener
+ maxRequestSize uint64
+ uploads config.Uploads
+ trusted config.Cidrs
+ log logger.Logger
+ pool pool.Pool
+ mul sync.Mutex
+ lsn events.Listener
+ internalHTTPCode uint64
}
// NewHandler return handle interface implementation
-func NewHandler(maxReqSize uint64, uploads config.Uploads, trusted config.Cidrs, pool pool.Pool) (*Handler, error) {
+func NewHandler(maxReqSize uint64, internalHTTPCode uint64, uploads config.Uploads, trusted config.Cidrs, pool pool.Pool) (*Handler, error) {
if pool == nil {
return nil, errors.E(errors.Str("pool should be initialized"))
}
return &Handler{
- maxRequestSize: maxReqSize * MB,
- uploads: uploads,
- pool: pool,
- trusted: trusted,
+ maxRequestSize: maxReqSize * MB,
+ uploads: uploads,
+ pool: pool,
+ trusted: trusted,
+ internalHTTPCode: internalHTTPCode,
}, nil
}
@@ -100,14 +102,14 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
size, err := strconv.ParseInt(length, 10, 64)
if err != nil {
// if got an error while parsing -> assign 500 code to the writer and return
- http.Error(w, errors.E(op, err).Error(), 500)
+ http.Error(w, "", 500)
h.sendEvent(ErrorEvent{Request: r, Error: errors.E(op, errors.Str("error while parsing value from the `content-length` header")), start: start, elapsed: time.Since(start)})
return
}
if size > int64(h.maxRequestSize) {
h.sendEvent(ErrorEvent{Request: r, Error: errors.E(op, errors.Str("request body max size is exceeded")), start: start, elapsed: time.Since(start)})
- http.Error(w, errors.E(op, errors.Str("request body max size is exceeded")).Error(), 500)
+ http.Error(w, errors.E(op, errors.Str("request body max size is exceeded")).Error(), http.StatusBadRequest)
return
}
}
@@ -135,21 +137,21 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
p, err := req.Payload()
if err != nil {
- http.Error(w, errors.E(op, err).Error(), 500)
+ h.handleError(w, r, start, err)
h.sendEvent(ErrorEvent{Request: r, Error: errors.E(op, err), start: start, elapsed: time.Since(start)})
return
}
rsp, err := h.pool.Exec(p)
if err != nil {
- http.Error(w, errors.E(op, err).Error(), 500)
+ h.handleError(w, r, start, err)
h.sendEvent(ErrorEvent{Request: r, Error: errors.E(op, err), start: start, elapsed: time.Since(start)})
return
}
resp, err := NewResponse(rsp)
if err != nil {
- http.Error(w, errors.E(op, err).Error(), resp.Status)
+ h.handleError(w, r, start, err)
h.sendEvent(ErrorEvent{Request: r, Error: errors.E(op, err), start: start, elapsed: time.Since(start)})
return
}
@@ -162,6 +164,26 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}
+// handleError will handle internal RR errors and return 500
+func (h *Handler) handleError(w http.ResponseWriter, r *http.Request, start time.Time, err error) {
+ const op = errors.Op("handle_error")
+ // internal error types, user should not see them
+ if errors.Is(errors.SoftJob, err) ||
+ errors.Is(errors.WatcherStopped, err) ||
+ errors.Is(errors.WorkerAllocate, err) ||
+ errors.Is(errors.NoFreeWorkers, err) ||
+ errors.Is(errors.ExecTTL, err) ||
+ errors.Is(errors.IdleTTL, err) ||
+ errors.Is(errors.TTL, err) ||
+ errors.Is(errors.Encode, err) ||
+ errors.Is(errors.Decode, err) ||
+ errors.Is(errors.Network, err) {
+ // write an internal server error
+ w.WriteHeader(int(h.internalHTTPCode))
+ h.sendEvent(ErrorEvent{Request: r, Error: errors.E(op, err), start: start, elapsed: time.Since(start)})
+ }
+}
+
// handleResponse triggers response event.
func (h *Handler) handleResponse(req *Request, resp *Response, start time.Time) {
h.sendEvent(ResponseEvent{Request: req, Response: resp, start: start, elapsed: time.Since(start)})
diff --git a/pkg/worker_handler/request.go b/pkg/worker_handler/request.go
index 75ee8381..44c466bb 100644
--- a/pkg/worker_handler/request.go
+++ b/pkg/worker_handler/request.go
@@ -9,6 +9,7 @@ import (
"strings"
j "github.com/json-iterator/go"
+ "github.com/spiral/errors"
"github.com/spiral/roadrunner/v2/pkg/payload"
"github.com/spiral/roadrunner/v2/plugins/http/attributes"
"github.com/spiral/roadrunner/v2/plugins/http/config"
@@ -138,16 +139,17 @@ func (r *Request) Close(log logger.Logger) {
// Payload request marshaled RoadRunner payload based on PSR7 data. values encode method is JSON. Make sure to open
// files prior to calling this method.
func (r *Request) Payload() (payload.Payload, error) {
+ const op = errors.Op("marshal_payload")
p := payload.Payload{}
var err error
if p.Context, err = json.Marshal(r); err != nil {
- return payload.Payload{}, err
+ return payload.Payload{}, errors.E(op, errors.Encode, err)
}
if r.Parsed {
if p.Body, err = json.Marshal(r.body); err != nil {
- return payload.Payload{}, err
+ return payload.Payload{}, errors.E(op, errors.Encode, err)
}
} else if r.body != nil {
p.Body = r.body.([]byte)
diff --git a/pkg/worker_handler/response.go b/pkg/worker_handler/response.go
index 1763d304..cbf22794 100644
--- a/pkg/worker_handler/response.go
+++ b/pkg/worker_handler/response.go
@@ -4,8 +4,8 @@ import (
"io"
"net/http"
"strings"
- "sync"
+ "github.com/spiral/errors"
"github.com/spiral/roadrunner/v2/pkg/payload"
)
@@ -19,14 +19,14 @@ type Response struct {
// associated Body payload.
Body interface{}
- sync.Mutex
}
// NewResponse creates new response based on given pool payload.
func NewResponse(p payload.Payload) (*Response, error) {
+ const op = errors.Op("http_response")
r := &Response{Body: p.Body}
if err := json.Unmarshal(p.Context, r); err != nil {
- return nil, err
+ return nil, errors.E(op, errors.Decode, err)
}
return r, nil