package main import ( "embed" "errors" "log" "net/http" "time" "git.1e99.eu/1e99/passed/config" "git.1e99.eu/1e99/passed/middlewares" "git.1e99.eu/1e99/passed/routes" "git.1e99.eu/1e99/passed/storage" ) //go:embed static/* var embedFS embed.FS func run() error { store, err := newStore() if err != nil { return err } var address string var logRequests bool var maxPasswordLength int config.Env("PASSED_ADDRESS", &address, ":3000") config.Env("PASSED_LOG_REQUESTS", &logRequests, "true") config.Env("PASSED_MAX_LENGTH", &maxPasswordLength, "12288") mux := http.NewServeMux() handler := http.Handler(mux) mux.Handle("GET /", routes.ServeFiles(embedFS, "static")) mux.Handle( "POST /api/password", middlewares.RateLimiter( routes.CreatePassword(store, maxPasswordLength), 1*time.Minute, 5, ), ) mux.Handle("GET /api/password/{id}", routes.GetPassword(store)) mux.Handle("HEAD /api/password/{id}", routes.HasPassword(store)) if logRequests { handler = middlewares.Logger(handler) } log.Printf("Listening on %s.", address) err = http.ListenAndServe(address, handler) if err != nil { return err } return nil } func newStore() (store storage.Store, err error) { var storeType string var clearInterval int config.Env("PASSED_STORE_TYPE", &storeType, "ram") config.Env("PASSED_STORE_CLEAR_INTERVAL", &clearInterval, "30") switch storeType { case "ram": store = storage.NewRamStore() case "dir", "directory": var path string config.Env("PASSED_STORE_DIR_PATH", &path, "passwords") store = storage.NewDirStore(path) default: err = errors.New("unknown storage type") return } go func() { ticker := time.Tick(time.Duration(clearInterval) * time.Second) for { <-ticker err := store.ClearExpired() if err != nil { log.Printf("Failed to clear expired passwords: %s", err) continue } log.Printf("Cleared expired passwords.") } }() return } func main() { err := run() if err != nil { log.Fatalf("%s", err) } }