changeset 4243:d776110b4db0 json-handler-middleware

Made the de-serialized input of the JSON handler accessible via the context of the request.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 22 Aug 2019 10:54:08 +0200
parents 1458c9b0fdaa
children 4394daeea96a
files pkg/controllers/cross.go pkg/controllers/diff.go pkg/controllers/gauges.go pkg/controllers/importconfig.go pkg/controllers/importqueue.go pkg/controllers/json.go pkg/controllers/manualimports.go pkg/controllers/printtemplates.go pkg/controllers/publish.go pkg/controllers/pwreset.go pkg/controllers/search.go pkg/controllers/srimports.go pkg/controllers/surveys.go pkg/controllers/system.go pkg/controllers/user.go
diffstat 15 files changed, 70 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/cross.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/cross.go	Thu Aug 22 10:54:08 2019 +0200
@@ -64,12 +64,9 @@
 	return mls, err
 }
 
-func crossSection(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func crossSection(req *http.Request) (jr JSONResult, err error) {
 
-	csi := input.(*models.CrossSectionInput)
+	csi := JSONInput(req).(*models.CrossSectionInput)
 
 	start := time.Now()
 	ctx := req.Context()
--- a/pkg/controllers/diff.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/diff.go	Thu Aug 22 10:54:08 2019 +0200
@@ -84,15 +84,12 @@
 // TODO: Make this configurable?
 var diffCalculationSemaphore = semaphore.NewWeighted(int64(3))
 
-func diffCalculation(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func diffCalculation(req *http.Request) (jr JSONResult, err error) {
 
 	begin := time.Now()
 	start := begin
 
-	dci := input.(*models.DiffCalculationInput)
+	dci := JSONInput(req).(*models.DiffCalculationInput)
 
 	ctx := req.Context()
 
--- a/pkg/controllers/gauges.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/gauges.go	Thu Aug 22 10:54:08 2019 +0200
@@ -574,10 +574,8 @@
 	return values, nil
 }
 
-func nashSutcliffe(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func nashSutcliffe(req *http.Request) (jr JSONResult, err error) {
+
 	gauge := mux.Vars(req)["gauge"]
 
 	var isrs *models.Isrs
--- a/pkg/controllers/importconfig.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/importconfig.go	Thu Aug 22 10:54:08 2019 +0200
@@ -28,10 +28,7 @@
 	"gemma.intevation.de/gemma/pkg/scheduler"
 )
 
-func runImportConfig(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func runImportConfig(req *http.Request) (jr JSONResult, err error) {
 
 	id, _ := strconv.ParseInt(mux.Vars(req)["id"], 10, 64)
 
@@ -55,14 +52,11 @@
 	return
 }
 
-func modifyImportConfig(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func modifyImportConfig(req *http.Request) (jr JSONResult, err error) {
 
 	ctx := req.Context()
 
-	raw := input.(*json.RawMessage)
+	raw := JSONInput(req).(*json.RawMessage)
 
 	id, _ := strconv.ParseInt(mux.Vars(req)["id"], 10, 64)
 
@@ -149,10 +143,7 @@
 	return
 }
 
-func infoImportConfig(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func infoImportConfig(req *http.Request) (jr JSONResult, err error) {
 
 	ctx := req.Context()
 
@@ -207,10 +198,7 @@
 	return
 }
 
-func deleteImportConfig(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func deleteImportConfig(req *http.Request) (jr JSONResult, err error) {
 
 	ctx := req.Context()
 
@@ -257,12 +245,9 @@
 	return
 }
 
-func addImportConfig(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func addImportConfig(req *http.Request) (jr JSONResult, err error) {
 
-	cfg := input.(*imports.ImportConfigIn)
+	cfg := JSONInput(req).(*imports.ImportConfigIn)
 
 	kind := imports.JobKind(cfg.Kind)
 
@@ -326,10 +311,7 @@
 	return
 }
 
-func listImportConfigs(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func listImportConfigs(req *http.Request) (jr JSONResult, err error) {
 
 	ctx := req.Context()
 	configs := []*imports.ImportConfigOut{}
--- a/pkg/controllers/importqueue.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/importqueue.go	Thu Aug 22 10:54:08 2019 +0200
@@ -228,10 +228,7 @@
 	return &models.ImportTime{Time: when.UTC()}
 }
 
-func listImports(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func listImports(req *http.Request) (jr JSONResult, err error) {
 
 	var list, before, after *filledStmt
 
@@ -322,10 +319,7 @@
 	return
 }
 
-func importLogs(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func importLogs(req *http.Request) (jr JSONResult, err error) {
 
 	ctx := req.Context()
 
@@ -398,10 +392,7 @@
 	return
 }
 
-func deleteImport(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func deleteImport(req *http.Request) (jr JSONResult, err error) {
 
 	ctx := req.Context()
 	id, _ := strconv.ParseInt(mux.Vars(req)["id"], 10, 64)
@@ -465,12 +456,9 @@
 INSERT INTO import.import_logs (import_id, msg) VALUES ($1, $2)`
 )
 
-func reviewImports(
-	reviews interface{},
-	req *http.Request,
-) (JSONResult, error) {
+func reviewImports(req *http.Request) (JSONResult, error) {
 
-	rs := *reviews.(*[]models.Review)
+	rs := *JSONInput(req).(*[]models.Review)
 
 	type reviewResult struct {
 		ID      int64  `json:"id"`
@@ -499,10 +487,7 @@
 	return JSONResult{Result: results}, nil
 }
 
-func reviewImport(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func reviewImport(req *http.Request) (jr JSONResult, err error) {
 
 	vars := mux.Vars(req)
 	id, _ := strconv.ParseInt(vars["id"], 10, 64)
--- a/pkg/controllers/json.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/json.go	Thu Aug 22 10:54:08 2019 +0200
@@ -48,9 +48,7 @@
 	Input func(*http.Request) interface{}
 	// Handle is called to handle the incoming HTTP request.
 	// in is the data structure returned by Input. Its nil if Input is nil.
-	// req is the incoming HTTP request.
-	// conn is the impersonated connection to the database.
-	Handle func(in interface{}, rep *http.Request) (JSONResult, error)
+	Handle func(rep *http.Request) (JSONResult, error)
 	// NoConn if set to true no database connection is established and
 	// the conn parameter of the Handle call is nil.
 	NoConn bool
@@ -77,21 +75,29 @@
 
 type jsonHandlerType int
 
-const jsonDBKey jsonHandlerType = 0
+const (
+	jsonConnKey jsonHandlerType = iota
+	jsonInputKey
+)
 
+// JSONConn extracts the impersonated sql.Conn from the context of the request.
 func JSONConn(req *http.Request) *sql.Conn {
-	if conn, ok := req.Context().Value(jsonDBKey).(*sql.Conn); ok {
+	if conn, ok := req.Context().Value(jsonConnKey).(*sql.Conn); ok {
 		return conn
 	}
 	return nil
 }
 
+// JSONConn extracts the de-serialized input from the context of the request.
+func JSONInput(req *http.Request) interface{} {
+	return req.Context().Value(jsonInputKey)
+}
+
 // ServeHTTP makes the JSONHandler a middleware.
 func (j *JSONHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 
-	var input interface{}
 	if j.Input != nil {
-		input = j.Input(req)
+		input := j.Input(req)
 		defer req.Body.Close()
 		var r io.Reader
 		switch {
@@ -106,6 +112,9 @@
 			http.Error(rw, "error: "+err.Error(), http.StatusBadRequest)
 			return
 		}
+		parent := req.Context()
+		ctx := context.WithValue(parent, jsonInputKey, input)
+		req = req.WithContext(ctx)
 	}
 
 	var jr JSONResult
@@ -115,16 +124,16 @@
 		if session := auth.Sessions.Session(token); session != nil {
 			parent := req.Context()
 			err = auth.RunAs(parent, session.User, func(conn *sql.Conn) error {
-				ctx := context.WithValue(parent, jsonDBKey, conn)
-				r := req.WithContext(ctx)
-				jr, err = j.Handle(input, r)
+				ctx := context.WithValue(parent, jsonConnKey, conn)
+				req = req.WithContext(ctx)
+				jr, err = j.Handle(req)
 				return err
 			})
 		} else {
 			err = auth.ErrNoSuchToken
 		}
 	} else {
-		jr, err = j.Handle(input, req)
+		jr, err = j.Handle(req)
 	}
 
 	if err != nil {
--- a/pkg/controllers/manualimports.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/manualimports.go	Thu Aug 22 10:54:08 2019 +0200
@@ -37,12 +37,10 @@
 	return ctor()
 }
 
-func manualImport(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func manualImport(req *http.Request) (jr JSONResult, err error) {
 
 	kind := imports.JobKind(mux.Vars(req)["kind"])
+	input := JSONInput(req)
 	what := imports.ConvertToInternal(kind, input)
 	if what == nil {
 		err = JSONError{
--- a/pkg/controllers/printtemplates.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/printtemplates.go	Thu Aug 22 10:54:08 2019 +0200
@@ -70,10 +70,7 @@
 
 var templateTypes = []string{"map", "diagram", "report"}
 
-func listPrintTemplates(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func listPrintTemplates(req *http.Request) (jr JSONResult, err error) {
 
 	ts := mux.Vars(req)["type"]
 	if ts == "" {
@@ -130,10 +127,7 @@
 	return
 }
 
-func fetchPrintTemplate(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func fetchPrintTemplate(req *http.Request) (jr JSONResult, err error) {
 
 	vars := mux.Vars(req)
 	name, typ := vars["name"], vars["type"]
@@ -162,15 +156,12 @@
 	return
 }
 
-func createPrintTemplate(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func createPrintTemplate(req *http.Request) (jr JSONResult, err error) {
 
 	vars := mux.Vars(req)
 	name, typ := vars["name"], vars["type"]
 
-	in := input.(*json.RawMessage)
+	in := JSONInput(req).(*json.RawMessage)
 
 	if name == "" {
 		err = JSONError{
@@ -227,10 +218,7 @@
 	return
 }
 
-func deletePrintTemplate(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func deletePrintTemplate(req *http.Request) (jr JSONResult, err error) {
 
 	vars := mux.Vars(req)
 	name, typ := vars["name"], vars["type"]
@@ -279,15 +267,12 @@
 	return
 }
 
-func updatePrintTemplate(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func updatePrintTemplate(req *http.Request) (jr JSONResult, err error) {
 
 	vars := mux.Vars(req)
 	name, typ := vars["name"], vars["type"]
 
-	in := input.(*json.RawMessage)
+	in := JSONInput(req).(*json.RawMessage)
 
 	if name == "" {
 		err = JSONError{
--- a/pkg/controllers/publish.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/publish.go	Thu Aug 22 10:54:08 2019 +0200
@@ -19,7 +19,7 @@
 	"gemma.intevation.de/gemma/pkg/models"
 )
 
-func published(_ interface{}, req *http.Request) (jr JSONResult, err error) {
+func published(req *http.Request) (jr JSONResult, err error) {
 	jr = JSONResult{
 		Result: struct {
 			Internal []models.IntEntry `json:"internal"`
--- a/pkg/controllers/pwreset.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/pwreset.go	Thu Aug 22 10:54:08 2019 +0200
@@ -235,10 +235,7 @@
 	return misc.SendMail(email, "Password Reset Link", body)
 }
 
-func passwordResetRequest(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func passwordResetRequest(req *http.Request) (jr JSONResult, err error) {
 
 	// We do the checks and the emailing in background
 	// no reduce the risks of timing attacks.
@@ -248,7 +245,7 @@
 		if err := backgroundRequest(host, user); err != nil {
 			log.Printf("error: %v\n", err)
 		}
-	}(input.(*models.PWResetUser))
+	}(JSONInput(req).(*models.PWResetUser))
 
 	// Send a neutral message to avoid being an user oracle.
 	const neutralMessage = "If this account exists, a reset link will be mailed."
--- a/pkg/controllers/search.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/search.go	Thu Aug 22 10:54:08 2019 +0200
@@ -38,12 +38,9 @@
 `
 )
 
-func searchFeature(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func searchFeature(req *http.Request) (jr JSONResult, err error) {
 
-	s := input.(*models.SearchRequest)
+	s := JSONInput(req).(*models.SearchRequest)
 
 	if len(s.SearchString) == 0 {
 		err = JSONError{http.StatusBadRequest,
@@ -66,10 +63,7 @@
 	return
 }
 
-func listBottlenecks(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func listBottlenecks(req *http.Request) (jr JSONResult, err error) {
 
 	var result string
 	err = JSONConn(req).QueryRowContext(
--- a/pkg/controllers/srimports.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/srimports.go	Thu Aug 22 10:54:08 2019 +0200
@@ -189,10 +189,7 @@
 	return &m, m.Decode(r)
 }
 
-func uploadSoundingResult(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func uploadSoundingResult(req *http.Request) (jr JSONResult, err error) {
 
 	var dir string
 	if dir, err = misc.StoreUploadedFile(
--- a/pkg/controllers/surveys.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/surveys.go	Thu Aug 22 10:54:08 2019 +0200
@@ -41,10 +41,7 @@
 WHERE b.objnam = $1 AND s.date_info::timestamptz <@ b.validity`
 )
 
-func listSurveys(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func listSurveys(req *http.Request) (jr JSONResult, err error) {
 
 	bottleneckName := mux.Vars(req)["bottleneck"]
 
--- a/pkg/controllers/system.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/system.go	Thu Aug 22 10:54:08 2019 +0200
@@ -57,9 +57,7 @@
 
 // System status end points
 
-func showSystemLog(
-	_ interface{}, req *http.Request,
-) (jr JSONResult, err error) {
+func showSystemLog(req *http.Request) (jr JSONResult, err error) {
 
 	serviceName := mux.Vars(req)["service"]
 	fileName := mux.Vars(req)["file"]
@@ -99,9 +97,7 @@
 	return
 }
 
-func getSystemConfig(
-	_ interface{}, req *http.Request,
-) (jr JSONResult, err error) {
+func getSystemConfig(req *http.Request) (jr JSONResult, err error) {
 
 	cfg := config.PublishedConfig()
 	if cfg == "" {
@@ -118,10 +114,7 @@
 	return
 }
 
-func getSystemSettings(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func getSystemSettings(req *http.Request) (jr JSONResult, err error) {
 
 	var rows *sql.Rows
 	if rows, err = JSONConn(req).QueryContext(req.Context(), getSettingsSQL); err != nil {
@@ -305,12 +298,9 @@
 	}
 }
 
-func setSystemSettings(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func setSystemSettings(req *http.Request) (jr JSONResult, err error) {
 
-	settings := input.(*map[string]string)
+	settings := JSONInput(req).(*map[string]string)
 
 	ctx := req.Context()
 	var tx *sql.Tx
--- a/pkg/controllers/user.go	Thu Aug 22 10:18:13 2019 +0200
+++ b/pkg/controllers/user.go	Thu Aug 22 10:54:08 2019 +0200
@@ -97,9 +97,7 @@
 (inkluding import errors) and details on the concerned import.`))
 )
 
-func deleteUser(
-	_ interface{}, req *http.Request,
-) (jr JSONResult, err error) {
+func deleteUser(req *http.Request) (jr JSONResult, err error) {
 
 	user := mux.Vars(req)["user"]
 	if !models.UserName(user).IsValid() {
@@ -148,10 +146,7 @@
 	return
 }
 
-func updateUser(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func updateUser(req *http.Request) (jr JSONResult, err error) {
 
 	user := models.UserName(mux.Vars(req)["user"])
 	if !user.IsValid() {
@@ -159,7 +154,7 @@
 		return
 	}
 
-	newUser := input.(*models.User)
+	newUser := JSONInput(req).(*models.User)
 	var res sql.Result
 
 	db := JSONConn(req)
@@ -232,12 +227,9 @@
 	return
 }
 
-func createUser(
-	input interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func createUser(req *http.Request) (jr JSONResult, err error) {
 
-	user := input.(*models.User)
+	user := JSONInput(req).(*models.User)
 
 	db := JSONConn(req)
 
@@ -280,10 +272,7 @@
 	return
 }
 
-func listUsers(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func listUsers(req *http.Request) (jr JSONResult, err error) {
 
 	var rows *sql.Rows
 
@@ -318,10 +307,7 @@
 	return
 }
 
-func listUser(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func listUser(req *http.Request) (jr JSONResult, err error) {
 
 	user := models.UserName(mux.Vars(req)["user"])
 	if !user.IsValid() {
@@ -357,10 +343,7 @@
 	return
 }
 
-func sendTestMail(
-	_ interface{},
-	req *http.Request,
-) (jr JSONResult, err error) {
+func sendTestMail(req *http.Request) (jr JSONResult, err error) {
 
 	user := models.UserName(mux.Vars(req)["user"])
 	if !user.IsValid() {