Repository: gomods/athens
Pull request #1627 (2020-06-14 15:07:44)

pkg/middleware: add tracing to ValidationHook
I noticed that our ValidationHook does not trace outgoing client calls. This PR does two things: 

1. It adds client tracing to outgoing Validation calls
2. It propagates the request context so that if a request is cancelled, the ValidationHook also gets cancelled 


Patch:
diff --git a/cmd/proxy/actions/app.go b/cmd/proxy/actions/app.go
index dda7b495..22ffdbf8 100644
--- a/cmd/proxy/actions/app.go
+++ b/cmd/proxy/actions/app.go
@@ -118,7 +118,7 @@ func App(conf *config.Config) (http.Handler, error) {
 
 	// Having the hook set means we want to use it
 	if vHook := conf.ValidatorHook; vHook != "" {
-		r.Use(mw.NewValidationMiddleware(vHook))
+		r.Use(mw.NewValidationMiddleware(client, vHook))
 	}
 
 	store, err := GetStorage(conf.StorageType, conf.Storage, conf.TimeoutDuration(), client)
diff --git a/pkg/middleware/validation.go b/pkg/middleware/validation.go
index feb6fc60..7f3cdc4e 100644
--- a/pkg/middleware/validation.go
+++ b/pkg/middleware/validation.go
@@ -15,7 +15,7 @@ import (
 
 // NewValidationMiddleware builds a middleware function that performs validation checks by calling
 // an external webhook
-func NewValidationMiddleware(validatorHook string) mux.MiddlewareFunc {
+func NewValidationMiddleware(client *http.Client, validatorHook string) mux.MiddlewareFunc {
 	const op errors.Op = "actions.NewValidationMiddleware"
 	return func(h http.Handler) http.Handler {
 		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -25,13 +25,14 @@ func NewValidationMiddleware(validatorHook string) mux.MiddlewareFunc {
 				h.ServeHTTP(w, r)
 				return
 			}
+			ctx := r.Context()
 			// not checking the error. Not all requests include a version
 			// i.e. list requests path is like /{module:.+}/@v/list with no version parameter
 			version, _ := paths.GetVersion(r)
 			if version != "" {
-				response, err := validate(validatorHook, mod, version)
+				response, err := validate(ctx, client, validatorHook, mod, version)
 				if err != nil {
-					entry := log.EntryFromContext(r.Context())
+					entry := log.EntryFromContext(ctx)
 					entry.SystemErr(err)
 					w.WriteHeader(http.StatusInternalServerError)
 					return
@@ -66,7 +67,7 @@ type validationResponse struct {
 	Message []byte
 }
 
-func validate(hook, mod, ver string) (validationResponse, error) {
+func validate(ctx context.Context, client *http.Client, hook, mod, ver string) (validationResponse, error) {
 	const op errors.Op = "actions.validate"
 
 	toVal := &validationParams{mod, ver}
@@ -75,7 +76,12 @@ func validate(hook, mod, ver string) (validationResponse, error) {
 		return validationResponse{Valid: false}, errors.E(op, err)
 	}
 
-	resp, err := http.Post(hook, "application/json", bytes.NewBuffer(jsonVal))
+	req, err := http.NewRequestWithContext(ctx, http.MethodPost, hook, bytes.NewReader(jsonVal))
+	if err != nil {
+		return validationResponse{}, errors.E(op, err)
+	}
+	req.Header.Set("Content-Type", "application/json")
+	resp, err := client.Do(req)
 	if err != nil {
 		return validationResponse{Valid: false}, errors.E(op, err)
 	}


Test patch:
diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go
index 7d631d3f..0c789d4b 100644
--- a/pkg/middleware/middleware_test.go
+++ b/pkg/middleware/middleware_test.go
@@ -95,7 +95,7 @@ func Test_FilterMiddleware(t *testing.T) {
 func hookFilterApp(hook string) *mux.Router {
 	h := func(w http.ResponseWriter, r *http.Request) {}
 	r := mux.NewRouter()
-	r.Use(NewValidationMiddleware(hook))
+	r.Use(NewValidationMiddleware(http.DefaultClient, hook))
 
 	r.HandleFunc(pathList, h)
 	r.HandleFunc(pathVersionInfo, h)