package api import ( "encoding/json" "fmt" "io" "log" "net/http" "strconv" "srs.epita.fr/fic-server/libfic" "github.com/gorilla/mux" ) type DispatchFunction func([]string, []byte) (interface{}, error) func apiHandler(f func (map[string]string,[]byte) (interface{}, error)) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { log.Printf("Handling %s request from %s: %s [%s]\n", r.Method, r.RemoteAddr, r.URL.Path, r.UserAgent()) w.Header().Set("Content-Type", "application/json") var ret interface{} var err error = nil // Read the body if r.ContentLength < 0 || r.ContentLength > 6553600 { http.Error(w, fmt.Sprintf("{errmsg:\"Request too large or request size unknown\"}", err), http.StatusRequestEntityTooLarge) return } var body []byte if r.ContentLength > 0 { tmp := make([]byte, 1024) for { n, err := r.Body.Read(tmp) for j := 0; j < n; j++ { body = append(body, tmp[j]) } if err != nil || n <= 0 { break } } } ret, err = f(mux.Vars(r), body) // Format response resStatus := http.StatusOK if err != nil { ret = map[string]string{"errmsg": err.Error()} resStatus = http.StatusBadRequest log.Println(r.RemoteAddr, resStatus, err.Error()) } if ret == nil { ret = map[string]string{"errmsg": "Page not found"} resStatus = http.StatusNotFound } if str, found := ret.(string); found { w.WriteHeader(resStatus) io.WriteString(w, str) } else if bts, found := ret.([]byte); found { w.WriteHeader(resStatus) w.Write(bts) } else if j, err := json.Marshal(ret); err != nil { http.Error(w, fmt.Sprintf("{\"errmsg\":\"%q\"}", err), http.StatusInternalServerError) } else { w.WriteHeader(resStatus) w.Write(j) } } } func teamHandler(f func(fic.Team,map[string]string,[]byte) (interface{}, error)) func (map[string]string,[]byte) (interface{}, error) { return func (args map[string]string, body []byte) (interface{}, error) { if tid, err := strconv.Atoi(string(args["tid"])); err != nil { if team, err := fic.GetTeamByInitialName(args["tid"]); err != nil { return nil, err } else { return f(team, args, body) } } else if team, err := fic.GetTeam(tid); err != nil { return nil, err } else { return f(team, args, body) } } } func themeHandler(f func(fic.Theme,map[string]string,[]byte) (interface{}, error)) func (map[string]string,[]byte) (interface{}, error) { return func (args map[string]string, body []byte) (interface{}, error) { if tid, err := strconv.Atoi(string(args["tid"])); err != nil { return nil, err } else if theme, err := fic.GetTheme(tid); err != nil { return nil, err } else { return f(theme, args, body) } } } func exerciceHandler(f func(fic.Exercice,map[string]string,[]byte) (interface{}, error)) func (map[string]string,[]byte) (interface{}, error) { return func (args map[string]string, body []byte) (interface{}, error) { if eid, err := strconv.Atoi(string(args["eid"])); err != nil { return nil, err } else if exercice, err := fic.GetExercice(int64(eid)); err != nil { return nil, err } else { return f(exercice, args, body) } } } func themedExerciceHandler(f func(fic.Theme,fic.Exercice,map[string]string,[]byte) (interface{}, error)) func (fic.Theme,map[string]string,[]byte) (interface{}, error) { return func (theme fic.Theme, args map[string]string, body []byte) (interface{}, error) { if eid, err := strconv.Atoi(string(args["eid"])); err != nil { return nil, err } else if exercice, err := fic.GetExercice(int64(eid)); err != nil { return nil, err } else { return f(theme, exercice, args, body) } } } func notFound(args map[string]string, body []byte) (interface{}, error) { return nil, nil }