Mercurial > gemma
view pkg/controllers/json.go @ 1556:6869eb94ead2
Don't error if an action is not defined if bound.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 11 Dec 2018 20:47:11 +0100 |
parents | cabf4789e02b |
children | 8f5a5c86f2a9 |
line wrap: on
line source
// This is Free Software under GNU Affero General Public License v >= 3.0 // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // // Copyright (C) 2018 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> package controllers import ( "database/sql" "encoding/json" "fmt" "io" "log" "net/http" "github.com/jackc/pgx" "gemma.intevation.de/gemma/pkg/auth" ) type JSONResult struct { Code int Result interface{} } type JSONHandler struct { Input func() interface{} Handle func(interface{}, *http.Request, *sql.Conn) (JSONResult, error) NoConn bool } type JSONError struct { Code int Message string } func (je JSONError) Error() string { return fmt.Sprintf("%d: %s", je.Code, je.Message) } func (j *JSONHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { var input interface{} if j.Input != nil { input = j.Input() defer req.Body.Close() if err := json.NewDecoder(req.Body).Decode(input); err != nil { http.Error(rw, "error: "+err.Error(), http.StatusBadRequest) return } } var jr JSONResult var err error if token, ok := auth.GetToken(req); ok && !j.NoConn { if session := auth.Sessions.Session(token); session != nil { err = auth.RunAs(req.Context(), session.User, func(conn *sql.Conn) error { jr, err = j.Handle(input, req, conn) return err }) } else { err = auth.ErrNoSuchToken } } else { jr, err = j.Handle(input, req, nil) } if err != nil { log.Printf("error: %v\n", err) switch e := err.(type) { case pgx.PgError: var res = struct { Result string `json:"result"` Code string `json:"code"` Message string `json:"message"` }{ Result: "failure", Code: e.Code, Message: e.Message, } rw.Header().Set("Content-Type", "application/json") rw.WriteHeader(http.StatusInternalServerError) if err := json.NewEncoder(rw).Encode(&res); err != nil { log.Printf("error: %v\n", err) } case JSONError: rw.Header().Set("Content-Type", "application/json") if e.Code == 0 { e.Code = http.StatusInternalServerError } rw.WriteHeader(e.Code) var res = struct { Message string `json:"message"` }{ Message: e.Message, } if err := json.NewEncoder(rw).Encode(&res); err != nil { log.Printf("error: %v\n", err) } default: http.Error(rw, "error: "+err.Error(), http.StatusInternalServerError) } return } if jr.Code == 0 { jr.Code = http.StatusOK } if jr.Code != http.StatusNoContent { rw.Header().Set("Content-Type", "application/json") } rw.WriteHeader(jr.Code) if jr.Code != http.StatusNoContent { var err error if r, ok := jr.Result.(io.Reader); ok { _, err = io.Copy(rw, r) } else { err = json.NewEncoder(rw).Encode(jr.Result) } if err != nil { log.Printf("error: %v\n", err) } } } func SendJSON(rw http.ResponseWriter, code int, data interface{}) { rw.Header().Set("Content-Type", "application/json") rw.WriteHeader(code) if err := json.NewEncoder(rw).Encode(data); err != nil { log.Printf("error: %v\n", err) } }