diff options
Diffstat (limited to 'src/http.go')
-rw-r--r-- | src/http.go | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/http.go b/src/http.go new file mode 100644 index 0000000..9f97352 --- /dev/null +++ b/src/http.go @@ -0,0 +1,143 @@ +package main + +import ( + "flag" + "github.com/gorilla/mux" + "net/http" + "fmt" + "strings" + "io/ioutil" + "time" +) + +var ( + port *int +) + +func registerHTTPFlags() { + port = flag.Int("port", 8080, "The port for HTTP") +} + +func runHTTPServer() (error) { + r := mux.NewRouter() + + r.HandleFunc("/", indexHandler) + r.HandleFunc("/files/{file}", fileHandler) + r.HandleFunc("/login", loginGetHandler).Methods("GET") + r.HandleFunc("/login", loginPostHandler).Methods("POST") + r.HandleFunc("/logout", logoutHandler).Methods("GET") + + address := fmt.Sprintf(":%d", *port) + return http.ListenAndServe(address, r) +} + +// Host the index file +func indexHandler(w http.ResponseWriter, r *http.Request) { + session, cookieNotFoundError := r.Cookie("session") + + if cookieNotFoundError != nil || !isValidSession(session.Value) { + // either no session cookie found, or it contains an invalid session token. Redirect. + http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) + } else { + // valid session token found, redirect to frontpage + readFileToResponse(w, "/index.html") + } +} + +// Static host files +func fileHandler(w http.ResponseWriter, r *http.Request) { + readFileToResponse(w, mux.Vars(r)["file"]) +} + +// Helper function to host files off of "hosted/" directory +func readFileToResponse(w http.ResponseWriter, path string) { + requestedFile := strings.Replace(path, "..", "", -1) + + contents, readError := ioutil.ReadFile(fmt.Sprintf("hosted/%s", requestedFile)) + + if readError != nil { + w.Write([]byte(fmt.Sprintf("unable to read %s", requestedFile))) + } else { + w.Write([]byte(contents)) + } +} + +// Read login page +func loginGetHandler(w http.ResponseWriter, r *http.Request) { + session, cookieNotFoundError := r.Cookie("session") + + // we need to verify that the client doesn't already have a valid session + if cookieNotFoundError == nil && isValidSession(session.Value) { + // session already valid, redirect the user + http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + } else { + readFileToResponse(w, "/login.html") + } +} + +// Process login data +func loginPostHandler(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + username := r.Form.Get("username") + accessCode := r.Form.Get("accesscode") + session, cookieNotFoundError := r.Cookie("session") + + validRedirect := false + + // we need to verify that the client doesn't already have a valid session + if cookieNotFoundError == nil && isValidSession(session.Value) { + // session already valid, redirect the user + validRedirect = true + } else { + // no valid session present, check the given credentials + + if verifyCredentials(username, accessCode) { + // credentials valid, create session + newSessionToken := createSession() + http.SetCookie(w, &http.Cookie{ + Name: "session", + Value: newSessionToken, + Path: "/", + Expires: time.Now().Add(time.Hour * 24), + }) + validRedirect = true + } + } + + if validRedirect { + // Redirect to frontpage + http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + return + } else { + // credentials invalid or database error occured + w.Write([]byte("Wrong credentials")) + return + } + + // Something else weird happened. + w.WriteHeader(500) + w.Write([]byte("Server Error")) +} + +// Process logout and deletion of cookie +func logoutHandler(w http.ResponseWriter, r *http.Request) { + session, cookieNotFoundError := r.Cookie("session") + + if cookieNotFoundError == nil { + // cookie was found + if isValidSession(session.Value) { + // and it contains a valid session. Delete the session... + destroySession(session.Value) + } + + // and delete the cookie + http.SetCookie(w, &http.Cookie{ + Name: "session", + Value: "", + Path: "/", + Expires: time.Unix(0, 0), + }) + } + + http.Redirect(w, r, "/", http.StatusTemporaryRedirect) +} |