diff options
Diffstat (limited to 'pkg/worker_handler')
-rw-r--r-- | pkg/worker_handler/handler.go | 56 | ||||
-rw-r--r-- | pkg/worker_handler/request.go | 6 | ||||
-rw-r--r-- | pkg/worker_handler/response.go | 6 |
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 |