commit 21e4432fad1a5e59554dbc2540beb44b16d255f3 Author: nemunaire Date: Wed Jan 6 19:30:57 2016 +0100 Add frontend diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 00000000..1097e68b --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1 @@ +frontend diff --git a/frontend/main.go b/frontend/main.go new file mode 100644 index 00000000..2427f571 --- /dev/null +++ b/frontend/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "flag" + "fmt" + "log" + "net/http" + "os" +) + +var SubmissionDir string + +func main() { + var bind = flag.String("bind", "0.0.0.0:8080", "Bind port/socket") + var prefix = flag.String("prefix", "", "Request path prefix to strip (from proxy)") + flag.StringVar(&SubmissionDir, "submission", "./submissions/", "Base directory where save submissions") + flag.Parse() + + log.Println("Creating submission directory...") + if _, err := os.Stat(SubmissionDir); os.IsNotExist(err) { + if err := os.MkdirAll(SubmissionDir, 0777); err != nil { + log.Fatal("Unable to create submission directory: ", err) + } + } + + log.Println("Registering handlers...") + http.Handle(fmt.Sprintf("%s/", *prefix), http.StripPrefix(*prefix, SubmissionHandler{})) + + log.Println(fmt.Sprintf("Ready, listening on %s", *bind)) + if err := http.ListenAndServe(*bind, nil); err != nil { + log.Fatal("Unable to listen and serve: ", err) + } +} diff --git a/frontend/submit.go b/frontend/submit.go new file mode 100644 index 00000000..2b66f644 --- /dev/null +++ b/frontend/submit.go @@ -0,0 +1,91 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "os" + "path" + "strconv" + "strings" +) + +type SubmissionHandler struct{} + +func (SubmissionHandler) ServeHTTP(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") + + + // Check request type and size + if r.Method != "POST" { + http.Error(w, "{errmsg:\"Bad request.\"}", http.StatusBadRequest) + return + } else if r.ContentLength < 0 || r.ContentLength > 255 { + http.Error(w, "{errmsg:\"Request too large or request size unknown\"}", http.StatusRequestEntityTooLarge) + return + } + + + // Extract URL arguments + var sURL = strings.Split(r.URL.Path, "/") + + if len(sURL) != 3 && len(sURL) != 4 { + http.Error(w, "{errmsg:\"Bad request.\"}", http.StatusBadRequest) + return + } + + // Parse arguments + if team, err := strconv.Atoi(sURL[1]); err != nil { + http.Error(w, "{errmsg:\"Bad request.\"}", http.StatusBadRequest) + return + } else if exercice, err := strconv.Atoi(sURL[2]); err != nil { + http.Error(w, "{errmsg:\"Bad request.\"}", http.StatusBadRequest) + return + } else { + if _, err := os.Stat(path.Join(SubmissionDir, fmt.Sprintf("%d", team))); os.IsNotExist(err) { + log.Println("Creating submission directory for", team) + if err := os.MkdirAll(path.Join(SubmissionDir, fmt.Sprintf("%d", team)), 0777); err != nil { + log.Println("Unable to create submission directory: ", err) + http.Error(w, "{errmsg:\"Internal server error. Please retry in few seconds.\"}", http.StatusInternalServerError) + return + } + } + + + // Previous submission not treated + if _, err := os.Stat(path.Join(SubmissionDir, fmt.Sprintf("%d", team), fmt.Sprintf("%d", exercice))); !os.IsNotExist(err) { + http.Error(w, "{errmsg:\"Calm-down. A solution is already being processed.\"}", http.StatusPaymentRequired) + return + } + + + // Read request body + 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 + } + } + } + + + // Store content in file + if file, err := os.Create(path.Join(SubmissionDir, fmt.Sprintf("%d", team), fmt.Sprintf("%d", exercice))); err != nil { + log.Println("Unable to open exercice file:", err) + http.Error(w, "{errmsg:\"Internal server error. Please retry in few seconds.\"}", http.StatusInternalServerError) + return + } else { + file.Write(body) + file.Close() + } + http.Error(w, "{errmsg:\"Submission accepted, please wait...\"}", http.StatusAccepted) + } +}