package main import ( "fmt" "log" "net/http" "os" "path" "time" "github.com/google/uuid" "golang.org/x/time/rate" ) type Server struct { fs http.Handler ws *WS limiter *rate.Limiter uuid string } func New() *Server { fs := http.FileServer(http.Dir(config().GetString("d"))) return &Server{ fs: fs, ws: NewWS(), limiter: rate.NewLimiter(rate.Every(time.Second), 2), uuid: uuid.New().String(), } } func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { log.Println("base", path.Base(r.URL.Path)) log.Println("dir", path.Dir(r.URL.Path)) if !s.Authorize(w, r) { return } if path.Dir(r.URL.Path) == "/ws" { s.ws.ServeHTTP(w, r) } else { r.URL.Path = "/" + path.Base(r.URL.Path) if _, err := os.Stat(path.Join(config().GetString("d"), path.Base(r.URL.Path))); os.IsNotExist(err) { r.URL.Path = "/" s.fs.ServeHTTP(w, r) } else { s.fs.ServeHTTP(w, r) } } } func (s *Server) Authorize(w http.ResponseWriter, r *http.Request) bool { if u, p, ok := r.BasicAuth(); !ok || u != "Q" || p != "Q" { s.limiter.Wait(r.Context()) w.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=%q", r.Host)) w.Header().Set("Content-Type", "text/plain") w.WriteHeader(http.StatusUnauthorized) w.Write([]byte("Unauthorized")) return false } return true }