package main import ( "code.mrmelon54.xyz/sean/melon-tools/module/gitea" "code.mrmelon54.xyz/sean/melon-tools/utils" "encoding/gob" "fmt" "github.com/google/uuid" "github.com/gorilla/mux" "github.com/gorilla/sessions" "github.com/joho/godotenv" "log" "net/http" "os" "sync" ) var ( modules = map[string]utils.IModule{ "/gitea": gitea.New(), } sessionStore = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY"))) ) func main() { err := godotenv.Load() if err != nil { fmt.Println(err) os.Exit(1) } stateManager := StateManager{&sync.RWMutex{}, make(map[uuid.UUID]*utils.State)} router := mux.NewRouter() router.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Content-Type", "text/html") rw.WriteHeader(http.StatusOK) _, _ = rw.Write([]byte("Melon Tools
\n")) _, _ = rw.Write([]byte("Gitea\n")) }) gob.Register(uuid.UUID{}) for k, v := range modules { router.HandleFunc(k, func(rw http.ResponseWriter, req *http.Request) { http.Redirect(rw, req, k+"/", http.StatusTemporaryRedirect) }) v.SetupModule(router.PathPrefix(k).Subrouter(), stateManager.sessionWrapper) } s := &http.Server{ Addr: os.Getenv("LISTEN"), Handler: router, } err = s.ListenAndServe() if err != nil { if err == http.ErrServerClosed { log.Println("Server closed successfully") } else { log.Fatalln(err) } return } } type StateManager struct { MSync *sync.RWMutex States map[uuid.UUID]*utils.State } func (m *StateManager) sessionWrapper(cb func(http.ResponseWriter, *http.Request, *utils.State)) func(rw http.ResponseWriter, req *http.Request) { return func(rw http.ResponseWriter, req *http.Request) { session, _ := sessionStore.Get(req, "melon-tools-session") if a, ok := session.Values["session-key"]; ok { if b, ok := a.(uuid.UUID); ok { m.MSync.RLock() c, ok := m.States[b] m.MSync.RUnlock() if ok { cb(rw, req, c) return } } } u := utils.NewState() m.MSync.Lock() m.States[u.Uuid] = u m.MSync.Unlock() session.Values["session-key"] = u.Uuid _ = session.Save(req, rw) cb(rw, req, u) } }