package server import ( "context" "crypto/rand" "github.com/gorilla/mux" "github.com/gorilla/sessions" "html/template" "io" "net" "net/http" "time" "git.giftfish.de/ston1th/gowiki/pkg/db" ) const ( keyLen = 32 authLen = keyLen * 2 cookieName = "gosession" ) type HTTPServer struct { Version string SecCookie bool Store *sessions.CookieStore DB *db.DB listener net.Listener srv *http.Server templ map[string]*template.Template res map[string][]byte } func NewHTTPServer(l net.Listener, versin string, secCookie bool) (srv *HTTPServer) { srv = &HTTPServer{ Version: version, SecCookie: secCookie, listener: l, } srv.cookieStore() srv.loadTemplates() srv.srv = &http.Server{ Handler: srv.buildRoutes(), } return } func (s *HTTPServer) Start() (err error) { s.BS, err = NewBoltStore() if err != nil { return } s.Index, err = NewIndex(blevePath) if err != nil { return } go func() { log.Println(s.srv.Serve(s.listener)) }() return } func (s *HTTPServer) Stop() error { s.BS.Close() s.Index.Close() ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() return s.srv.Shutdown(ctx) } func (s *HTTPServer) buildRoutes() http.Handler { m := mux.NewRouter() m.NotFoundHandler = ¬FoundHandler{s} for _, v := range routes { m.HandleFunc(v.Path, s.contextWrapper(v.Handler)).Methods(v.Methods...) } return m } func (s *HTTPServer) contextWrapper(h ctxHandler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { h(newContext(w, r, s)) } } func (s *HTTPServer) cookieStore() { options := &sessions.Options{ Path: "/", MaxAge: 3600 * 12, Secure: s.SecCookie, HttpOnly: true, } authKey := genKey(authLen) encKey := genKey(keyLen) s.Store = sessions.NewCookieStore(authKey, encKey) s.Store.Options = options go func() { for { time.Sleep(time.Hour * 12) newAuthKey := genKey(authLen) newEncKey := genKey(keyLen) newStore := sessions.NewCookieStore(newAuthKey, newEncKey, authKey, encKey) newStore.Options = options s.Store = newStore authKey = newAuthKey encKey = newEncKey } }() } func genKey(length int) (bytes []byte) { bytes = make([]byte, length) if _, err := io.ReadFull(rand.Reader, bytes); err != nil { log.Println("genKey:", err) } return }