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