view controllers/json.go @ 238:2b39bf2bf1fd

If no error code was given in a JSONResult assume Status OK (200).
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 26 Jul 2018 17:09:43 +0200
parents 3771788d3dae
children 713234a04a87
line wrap: on
line source

package controllers

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"net/http"

	"gemma.intevation.de/gemma/auth"
	"github.com/jackc/pgx"
)

type JSONResult struct {
	Code   int
	Result interface{}
}

type JSONHandler struct {
	Input   func() interface{}
	Process func(http.ResponseWriter, *http.Request, interface{}, *sql.DB) (JSONResult, error)
}

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
		}
	}

	token, _ := auth.GetToken(req)
	var jr JSONResult
	err := auth.ConnPool.Do(token, func(db *sql.DB) (err error) {
		jr, err = j.Process(rw, req, input, db)
		return err
	})

	if err != nil {
		switch e := err.(type) {
		case pgx.PgError:
			var res = struct {
				Result  string `json:"result"`
				Code    string `json:"code,omitempty"`
				Message string `json:"message,omitempty"`
			}{
				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")
			rw.WriteHeader(http.StatusInternalServerError)
			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:
			log.Printf("err: %v\n", err)
			http.Error(rw,
				"error: "+err.Error(),
				http.StatusInternalServerError)
		}
		return
	}

	if jr.Code == 0 {
		jr.Code = http.StatusOK
	}

	rw.Header().Set("Content-Type", "application/json")
	rw.WriteHeader(jr.Code)
	if err := json.NewEncoder(rw).Encode(jr.Result); err != nil {
		log.Printf("error: %v\n", err)
	}
}