package main import ( "crypto/sha256" "crypto/subtle" "fmt" "io" "log" "net/http" "os" "strings" ) func uploadFile(w http.ResponseWriter, r *http.Request) { // Maximum upload of 10 MB files r.ParseMultipartForm(10 << 20) // Get handler for filename, size and headers file, handler, err := r.FormFile("myFile") if err != nil { fmt.Println("Error Retrieving the File") fmt.Println(err) return } defer file.Close() fmt.Printf("Uploaded File: %+v\n", handler.Filename) fmt.Printf("File Size: %+v\n", handler.Size) fmt.Printf("MIME Header: %+v\n", handler.Header) // Create file dst, err := os.Create(handler.Filename) defer dst.Close() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Copy the uploaded file to the created file on the filesystem if _, err := io.Copy(dst, file); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fmt.Fprintf(w, "Successfully Uploaded File\n") } func deleteFile(w http.ResponseWriter, r *http.Request) { file := strings.ReplaceAll(r.URL.Path, "/", "") fmt.Printf("Deleting file %s\n", file) err := os.Remove(file) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } } func basicAuth(w http.ResponseWriter, r *http.Request) bool { username, password, ok := r.BasicAuth() if ok { // Calculate SHA-256 hashes for the provided and expected // usernames and passwords. usernameHash := sha256.Sum256([]byte(username)) passwordHash := sha256.Sum256([]byte(password)) expectedUsernameHash := sha256.Sum256([]byte(os.Getenv("BASIC_AUTH_USER"))) expectedPasswordHash := sha256.Sum256([]byte(os.Getenv("BASIC_AUTH_PASSWORD"))) // Use the subtle.ConstantTimeCompare() function to check if // the provided username and password hashes equal the // expected username and password hashes. ConstantTimeCompare // will return 1 if the values are equal, or 0 otherwise. // Importantly, we should to do the work to evaluate both the // username and password before checking the return values to // avoid leaking information. usernameMatch := (subtle.ConstantTimeCompare(usernameHash[:], expectedUsernameHash[:]) == 1) passwordMatch := (subtle.ConstantTimeCompare(passwordHash[:], expectedPasswordHash[:]) == 1) // If the username and password are correct, then call // the next handler in the chain. Make sure to return // afterwards, so that none of the code below is run. if usernameMatch && passwordMatch { return true } } return false } func coreHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": // Get should be always possible h := http.FileServer(http.Dir("")) h.ServeHTTP(w, r) case "POST": if !basicAuth(w, r) { http.Error(w, "Invalid credentials", http.StatusUnauthorized) return } uploadFile(w, r) case "DELETE": if !basicAuth(w, r) { http.Error(w, "Invalid credentials", http.StatusUnauthorized) return } deleteFile(w, r) } fmt.Println("TEST") } func main() { // Upload route http.HandleFunc("/", coreHandler) //Listen on port 8080 log.Fatal(http.ListenAndServe(":8081", nil)) }