package api import ( "encoding/json" "fmt" "io" "log" "net/http" "os" "path" "strconv" "time" "github.com/julienschmidt/httprouter" ) var Simulator string var TeamsDir string type QAUser struct { User string `json:"name"` TeamId int64 `json:"id_team"` } type DispatchFunction func(QAUser, httprouter.Params, []byte) (interface{}, error) func apiHandler(f DispatchFunction) func(http.ResponseWriter, *http.Request, httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { ficteam := Simulator if t := r.Header.Get("X-FIC-Team"); t != "" { ficteam = t } var teamid int64 var err error if ficteam == "" { log.Printf("%s 401 \"%s %s\" [%s]\n", r.RemoteAddr, r.Method, r.URL.Path, r.UserAgent()) w.Header().Set("Content-Type", "application/json") http.Error(w, fmt.Sprintf("{errmsg:\"Need to authenticate.\"}"), http.StatusUnauthorized) return } else if teamid, err = strconv.ParseInt(ficteam, 10, 64); err != nil { if lnk, err := os.Readlink(path.Join(TeamsDir, ficteam)); err != nil { log.Printf("[ERR] Unable to readlink %q: %s\n", path.Join(TeamsDir, ficteam), err) return } else if teamid, err = strconv.ParseInt(lnk, 10, 64); err != nil { log.Printf("[ERR] Error during ParseInt team %q: %s\n", lnk, err) return } } log.Printf("%s \"%s %s\" [%s]\n", r.RemoteAddr, r.Method, r.URL.Path, r.UserAgent()) // Read the body if r.ContentLength < 0 || r.ContentLength > 6553600 { http.Error(w, fmt.Sprintf("{errmsg:\"Request too large or request size unknown\"}"), 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 } } } var ret interface{} ret, err = f(QAUser{ficteam, teamid}, ps, 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 } w.Header().Set("X-FIC-Time", fmt.Sprintf("%f", float64(time.Now().UnixNano()/1000)/1000000)) if str, found := ret.(string); found { w.Header().Set("Content-Type", "application/json") w.WriteHeader(resStatus) io.WriteString(w, str) } else if bts, found := ret.([]byte); found { w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Disposition", "attachment") w.Header().Set("Content-Transfer-Encoding", "binary") w.WriteHeader(resStatus) w.Write(bts) } else if j, err := json.Marshal(ret); err != nil { w.Header().Set("Content-Type", "application/json") http.Error(w, fmt.Sprintf("{\"errmsg\":%q}", err), http.StatusInternalServerError) } else { w.Header().Set("Content-Type", "application/json") w.WriteHeader(resStatus) w.Write(j) } } }