// Package server. package server import ( "fmt" "net" "net/http" "time" "github.com/abbot/go-http-auth" "github.com/gen2brain/cam2ip/handlers" ) // Server struct. type Server struct { Name string Version string Index int Device string Delay int Width float64 Height float64 Quality int Rotate int Flip string NoWebGL bool Timestamp bool TimeFormat string Bind string Htpasswd string Lazy bool Open func() (handlers.ImageReader, error) } // NewServer returns new Server. func NewServer() *Server { s := &Server{} return s } // ListenAndServe listens on the TCP address and serves requests. func (s *Server) ListenAndServe() error { var basic *auth.BasicAuth if s.Htpasswd != "" { realm := fmt.Sprintf("%s/%s", s.Name, s.Version) basic = auth.NewBasicAuthenticator(realm, auth.HtpasswdFileProvider(s.Htpasswd)) } stream := handlers.NewStream(s.Open, s.Delay, s.Quality, s.Lazy) mux := http.NewServeMux() mux.Handle("/html", newAuthHandler(handlers.NewHTML(s.Width, s.Height, s.NoWebGL), basic)) mux.Handle("/jpeg", newAuthHandler(handlers.NewJPEG(stream), basic)) mux.Handle("/mjpeg", newAuthHandler(handlers.NewMJPEG(stream), basic)) mux.Handle("/socket", newAuthHandler(handlers.NewSocket(stream), basic)) mux.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) mux.Handle("/", newAuthHandler(handlers.NewIndex(), basic)) srv := &http.Server{ Handler: mux, ReadHeaderTimeout: 5 * time.Second, } listener, err := net.Listen("tcp", s.Bind) if err != nil { return err } return srv.Serve(listener) } // newAuthHandler wraps handler and checks auth. func newAuthHandler(handler http.Handler, authenticator *auth.BasicAuth) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if authenticator != nil { w.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=\"%s\"", authenticator.Realm)) if authenticator.CheckAuth(r) == "" { http.Error(w, "401 Unauthorized", http.StatusUnauthorized) return } } handler.ServeHTTP(w, r) }) }