Refactor error handling
This commit is contained in:
parent
ae15f35792
commit
819a3caad6
3 changed files with 70 additions and 28 deletions
|
@ -13,6 +13,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"git.andreafazzi.eu/andrea/oef/config"
|
||||
"git.andreafazzi.eu/andrea/oef/errors"
|
||||
"git.andreafazzi.eu/andrea/oef/i18n"
|
||||
"git.andreafazzi.eu/andrea/oef/orm"
|
||||
"git.andreafazzi.eu/andrea/oef/reflect"
|
||||
|
@ -24,6 +25,19 @@ import (
|
|||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
type handlerFuncWithError func(http.ResponseWriter, *http.Request) error
|
||||
|
||||
type rootMiddleware struct {
|
||||
h *Handlers
|
||||
fn handlerFuncWithError
|
||||
}
|
||||
|
||||
func newRootMiddleware(h *Handlers, fn func(http.ResponseWriter, *http.Request) error) *rootMiddleware {
|
||||
return &rootMiddleware{h, fn}
|
||||
}
|
||||
|
||||
// type rootHandler func(http.ResponseWriter, *http.Request) error
|
||||
|
||||
type Handlers struct {
|
||||
Config *config.ConfigT
|
||||
|
||||
|
@ -61,10 +75,12 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
|||
),
|
||||
h.JWTCookieMiddleware.Handler(
|
||||
h.Recover(
|
||||
newRootMiddleware(
|
||||
h,
|
||||
h.modelHandler(
|
||||
reflect.ModelNameLowerPlural(model),
|
||||
pattern,
|
||||
)))).Methods(pattern.Methods...)
|
||||
))))).Methods(pattern.Methods...)
|
||||
}
|
||||
|
||||
// Install API paths
|
||||
|
@ -75,10 +91,13 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
|||
),
|
||||
h.JWTHeaderMiddleware.Handler(
|
||||
h.Recover(
|
||||
newRootMiddleware(
|
||||
h,
|
||||
|
||||
h.modelHandler(
|
||||
reflect.ModelNameLowerPlural(model),
|
||||
pattern,
|
||||
)))).Methods(pattern.Methods...)
|
||||
))))).Methods(pattern.Methods...)
|
||||
}
|
||||
|
||||
// Set permissions
|
||||
|
@ -265,18 +284,16 @@ func (h *Handlers) hasPermission(role, path string) bool {
|
|||
return h.permissions[role][path]
|
||||
}
|
||||
|
||||
func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) {
|
||||
func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) error {
|
||||
format := r.URL.Query().Get("format")
|
||||
getFn, err := h.Database.GetFunc(pattern.Path(model))
|
||||
if err != nil {
|
||||
log.Println("Error:", err)
|
||||
respondWithError(h, w, r, err)
|
||||
return err
|
||||
} else {
|
||||
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||
role := claims["role"].(string)
|
||||
if !h.hasPermission(role, pattern.Path(model)) {
|
||||
h.setFlashMessage(w, r, "notAuthorized")
|
||||
h.Renderer[format].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
||||
return errors.NotAuthorized
|
||||
} else {
|
||||
data, err := getFn(h.Database, mux.Vars(r), w, r)
|
||||
if err != nil {
|
||||
|
@ -287,6 +304,7 @@ func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pat
|
|||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) error {
|
||||
|
@ -299,17 +317,17 @@ func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pa
|
|||
postFn, err := h.Database.GetFunc(pattern.Path(model))
|
||||
|
||||
if err != nil {
|
||||
respondWithError(h, w, r, err)
|
||||
return err
|
||||
} else {
|
||||
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||
|
||||
role := claims["role"].(string)
|
||||
if !h.hasPermission(role, pattern.Path(model)) {
|
||||
h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
||||
return errors.NotAuthorized
|
||||
} else {
|
||||
data, err = postFn(h.Database, mux.Vars(r), w, r)
|
||||
if err != nil {
|
||||
respondWithError(h, w, r, err)
|
||||
return err
|
||||
} else if pattern.RedirectPattern != "" {
|
||||
if id := mux.Vars(r)["id"]; id != "" {
|
||||
modelId, _ := strconv.Atoi(id)
|
||||
|
@ -327,16 +345,15 @@ func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pa
|
|||
|
||||
}
|
||||
|
||||
func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) {
|
||||
func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) error {
|
||||
var data interface{}
|
||||
|
||||
respFormat := renderer.GetContentFormat(r)
|
||||
|
||||
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||
|
||||
role := claims["role"].(string)
|
||||
if !h.hasPermission(role, pattern.Path(model)) {
|
||||
h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
||||
return errors.NotAuthorized
|
||||
} else {
|
||||
postFn, err := h.Database.GetFunc(pattern.Path(model))
|
||||
if err != nil {
|
||||
|
@ -357,12 +374,19 @@ func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string,
|
|||
h.Renderer[respFormat].Render(w, r, h.CookieStore, data.(orm.IDer).GetID())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func respondWithError(h *Handlers, w http.ResponseWriter, r *http.Request, err error) {
|
||||
respFormat := renderer.GetContentFormat(r)
|
||||
var format string
|
||||
|
||||
format = r.URL.Query().Get("format")
|
||||
if format == "" {
|
||||
format = renderer.GetContentFormat(r)
|
||||
}
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
h.Renderer[respFormat].Render(w, r, h.CookieStore, err)
|
||||
h.Renderer[format].Render(w, r, h.CookieStore, err)
|
||||
}
|
||||
|
||||
func (h *Handlers) Create(model interface{}) http.Handler {
|
||||
|
@ -389,25 +413,29 @@ func (h *Handlers) Read(model interface{}) http.Handler {
|
|||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
||||
func (h *Handlers) modelHandler(model string, pattern config.PathPattern) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *Handlers) modelHandler(model string, pattern config.PathPattern) handlerFuncWithError {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) error {
|
||||
|
||||
var err error
|
||||
|
||||
// Replace the "api" prefix.
|
||||
pattern.PathPattern = strings.Replace(pattern.PathPattern, "/api", "", -1)
|
||||
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
h.get(w, r, model, pattern)
|
||||
err = h.get(w, r, model, pattern)
|
||||
|
||||
case "POST":
|
||||
h.post(w, r, model, pattern)
|
||||
err = h.post(w, r, model, pattern)
|
||||
|
||||
case "DELETE":
|
||||
h.delete(w, r, model, pattern)
|
||||
}
|
||||
err = h.delete(w, r, model, pattern)
|
||||
}
|
||||
|
||||
return http.HandlerFunc(fn)
|
||||
return err
|
||||
}
|
||||
|
||||
return handlerFuncWithError(fn)
|
||||
}
|
||||
|
||||
func DefaultHomeHandler() http.Handler {
|
||||
|
@ -458,3 +486,14 @@ func DefaultHomeHandler() http.Handler {
|
|||
}
|
||||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
||||
func (m *rootMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
err := m.fn(w, r) // Call handler function
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
// This is where our error handling logic starts.
|
||||
log.Printf("An error accured: %v", err) // Log the error.
|
||||
|
||||
respondWithError(m.h, w, r, err)
|
||||
}
|
||||
|
|
|
@ -41,5 +41,9 @@ var (
|
|||
"outOfTime": map[string]string{
|
||||
"it": "Il tempo utile per consegnare la prova è scaduto.",
|
||||
},
|
||||
"notAuthorized": map[string]string{
|
||||
"it": "Non si è autorizzati ad accedere a questa pagina",
|
||||
},
|
||||
|
||||
}
|
||||
)
|
||||
|
|
|
@ -196,7 +196,6 @@ func (rend *HTMLRenderer) writeError(w http.ResponseWriter, r *http.Request, dat
|
|||
if !ok {
|
||||
panic(fmt.Errorf("Error template not found! Can't proceed, sorry."))
|
||||
}
|
||||
log.Println(data.(*htmlTemplateData).Data.(error))
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
|
Loading…
Reference in a new issue