Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
coprocess: abort request on response hook errors
  • Loading branch information
matiasinsaurralde committed Aug 15, 2019
1 parent c9d9621 commit 6164ae6
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 8 deletions.
7 changes: 6 additions & 1 deletion gateway/coprocess.go
Expand Up @@ -416,7 +416,12 @@ func (h *CustomMiddlewareResponseHook) Init(mwDef interface{}, spec *APISpec) er
}

func (h *CustomMiddlewareResponseHook) Name() string {
return ""
return "CustomMiddlewareResponseHook"
}

func (h *CustomMiddlewareResponseHook) HandleError(rw http.ResponseWriter, req *http.Request) {
handler := ErrorHandler{h.mw.BaseMiddleware}
handler.HandleError(rw, req, "Middleware error", http.StatusInternalServerError, true)
}

func (h *CustomMiddlewareResponseHook) HandleResponse(rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) error {
Expand Down
3 changes: 3 additions & 0 deletions gateway/coprocess_dummy.go
Expand Up @@ -75,6 +75,9 @@ func (h *CustomMiddlewareResponseHook) Init(mw interface{}, spec *APISpec) error
return nil
}

func (h *CustomMiddlewareResponseHook) HandleError(rw http.ResponseWriter, req *http.Request) {
}

func (h *CustomMiddlewareResponseHook) HandleResponse(rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) error {
return nil
}
Expand Down
14 changes: 10 additions & 4 deletions gateway/middleware.go
Expand Up @@ -9,12 +9,12 @@ import (
"strconv"
"time"

"github.com/sirupsen/logrus"
"github.com/gocraft/health"
"github.com/justinas/alice"
newrelic "github.com/newrelic/go-agent"
"github.com/paulbellamy/ratecounter"
cache "github.com/pmylund/go-cache"
"github.com/sirupsen/logrus"

"github.com/TykTechnologies/tyk/apidef"
"github.com/TykTechnologies/tyk/config"
Expand Down Expand Up @@ -545,6 +545,7 @@ type TykResponseHandler interface {
Init(interface{}, *APISpec) error
Name() string
HandleResponse(http.ResponseWriter, *http.Response, *http.Request, *user.SessionState) error
HandleError(http.ResponseWriter, *http.Request)
}

func responseProcessorByName(name string) TykResponseHandler {
Expand All @@ -563,14 +564,19 @@ func responseProcessorByName(name string) TykResponseHandler {
return nil
}

func handleResponseChain(chain []TykResponseHandler, rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) error {
func handleResponseChain(chain []TykResponseHandler, rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) (abortRequest bool, err error) {
traceIsEnabled := trace.IsEnabled()
for _, rh := range chain {
if err := handleResponse(rh, rw, res, req, ses, traceIsEnabled); err != nil {
return err
// Abort the request if this handler is a response middleware hook:
if rh.Name() == "CustomMiddlewareResponseHook" {
rh.HandleError(rw, req)
return true, err
}
return false, err
}
}
return nil
return false, nil
}

func handleResponse(rh TykResponseHandler, rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState, shouldTrace bool) error {
Expand Down
2 changes: 1 addition & 1 deletion gateway/mw_virtual_endpoint.go
Expand Up @@ -287,7 +287,7 @@ func forceResponse(w http.ResponseWriter,

if !isPre {
// Handle response middleware
if err := handleResponseChain(spec.ResponseChain, w, newResponse, r, session); err != nil {
if _, err := handleResponseChain(spec.ResponseChain, w, newResponse, r, session); err != nil {
logger.WithError(err).Error("Response chain failed! ")
}
}
Expand Down
3 changes: 3 additions & 0 deletions gateway/res_handler_header_injector.go
Expand Up @@ -27,6 +27,9 @@ func (h *HeaderInjector) Init(c interface{}, spec *APISpec) error {
return mapstructure.Decode(c, &h.config)
}

func (h *HeaderInjector) HandleError(rw http.ResponseWriter, req *http.Request) {
}

func (h *HeaderInjector) HandleResponse(rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) error {
// TODO: This should only target specific paths

Expand Down
3 changes: 3 additions & 0 deletions gateway/res_handler_header_transform.go
Expand Up @@ -36,6 +36,9 @@ func (h *HeaderTransform) Init(c interface{}, spec *APISpec) error {
return nil
}

func (h *HeaderTransform) HandleError(rw http.ResponseWriter, req *http.Request) {
}

func (h *HeaderTransform) HandleResponse(rw http.ResponseWriter,
res *http.Response, req *http.Request, ses *user.SessionState) error {

Expand Down
3 changes: 3 additions & 0 deletions gateway/res_handler_jq_transform.go
Expand Up @@ -22,6 +22,9 @@ func (h *ResponseTransformJQMiddleware) Init(c interface{}, spec *APISpec) error
return nil
}

func (h *ResponseTransformJQMiddleware) HandleError(rw http.ResponseWriter, req *http.Request) {
}

func (h *ResponseTransformJQMiddleware) HandleResponse(rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) error {
_, versionPaths, _, _ := h.Spec.Version(req)
found, meta := h.Spec.CheckSpecMatchesStatus(req, versionPaths, TransformedJQResponse)
Expand Down
3 changes: 3 additions & 0 deletions gateway/res_handler_jq_transform_dummy.go
Expand Up @@ -22,6 +22,9 @@ func (h *ResponseTransformJQMiddleware) Init(c interface{}, spec *APISpec) error
return nil
}

func (h *ResponseTransformJQMiddleware) HandleError(rw http.ResponseWriter, req *http.Request) {
}

func (h *ResponseTransformJQMiddleware) HandleResponse(rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) error {
log.Warning("JQ transforms not supported")
return nil
Expand Down
5 changes: 4 additions & 1 deletion gateway/res_handler_transform.go
Expand Up @@ -10,8 +10,8 @@ import (
"net/http"
"strconv"

"github.com/sirupsen/logrus"
"github.com/clbanning/mxj"
"github.com/sirupsen/logrus"

"github.com/TykTechnologies/tyk/apidef"
"github.com/TykTechnologies/tyk/headers"
Expand Down Expand Up @@ -76,6 +76,9 @@ func compressBuffer(in bytes.Buffer, encoding string) (out bytes.Buffer) {
return out
}

func (h *ResponseTransformMiddleware) HandleError(rw http.ResponseWriter, req *http.Request) {
}

func (h *ResponseTransformMiddleware) HandleResponse(rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) error {

logger := log.WithFields(logrus.Fields{
Expand Down
9 changes: 8 additions & 1 deletion gateway/reverse_proxy.go
Expand Up @@ -751,7 +751,14 @@ func (p *ReverseProxy) WrappedServeHTTP(rw http.ResponseWriter, req *http.Reques

// Middleware chain handling here - very simple, but should do
// the trick. Chain can be empty, in which case this is a no-op.
if err := handleResponseChain(p.TykAPISpec.ResponseChain, rw, res, req, ses); err != nil {
// abortRequest is set to true when a response hook fails
// For reference see "HandleError" in coprocess.go
abortRequest, err := handleResponseChain(p.TykAPISpec.ResponseChain, rw, res, req, ses)
if abortRequest {
return nil
}

if err != nil {
log.Error("Response chain failed! ", err)
}

Expand Down

0 comments on commit 6164ae6

Please sign in to comment.