func TestAssets(t *testing.T) { assets := auto.Assets() idx, ok := assets["index.html"] if !ok { t.Fatal("No index.html in compiled in assets") } if !bytes.Contains(idx, []byte("<html")) { t.Fatal("No html in index.html") } }
func TestAssets(t *testing.T) { assets := auto.Assets() idx, ok := assets["index.html"] if !ok { t.Fatal("No index.html in compiled in assets") } var gr *gzip.Reader gr, _ = gzip.NewReader(bytes.NewReader(idx)) idx, _ = ioutil.ReadAll(gr) if !bytes.Contains(idx, []byte("<html")) { t.Fatal("No html in index.html") } }
func embeddedStatic(assetDir string) http.Handler { assets := auto.Assets() return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { file := r.URL.Path if file[0] == '/' { file = file[1:] } if len(file) == 0 { file = "index.html" } if assetDir != "" { p := filepath.Join(assetDir, filepath.FromSlash(file)) _, err := os.Stat(p) if err == nil { http.ServeFile(w, r, p) return } } bs, ok := assets[file] if !ok { http.NotFound(w, r) return } mtype := mimeTypeForFile(file) if len(mtype) != 0 { w.Header().Set("Content-Type", mtype) } w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bs))) w.Header().Set("Last-Modified", modt) w.Write(bs) }) }
func (s *apiSvc) Serve() { s.stop = make(chan struct{}) l.AddHandler(logger.LevelWarn, s.showGuiError) // The GET handlers getRestMux := http.NewServeMux() getRestMux.HandleFunc("/rest/db/completion", s.getDBCompletion) // device folder getRestMux.HandleFunc("/rest/db/file", s.getDBFile) // folder file getRestMux.HandleFunc("/rest/db/ignores", s.getDBIgnores) // folder getRestMux.HandleFunc("/rest/db/need", s.getDBNeed) // folder [perpage] [page] getRestMux.HandleFunc("/rest/db/status", s.getDBStatus) // folder getRestMux.HandleFunc("/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels] getRestMux.HandleFunc("/rest/events", s.getEvents) // since [limit] getRestMux.HandleFunc("/rest/stats/device", s.getDeviceStats) // - getRestMux.HandleFunc("/rest/stats/folder", s.getFolderStats) // - getRestMux.HandleFunc("/rest/svc/deviceid", s.getDeviceID) // id getRestMux.HandleFunc("/rest/svc/lang", s.getLang) // - getRestMux.HandleFunc("/rest/svc/report", s.getReport) // - getRestMux.HandleFunc("/rest/system/browse", s.getSystemBrowse) // current getRestMux.HandleFunc("/rest/system/config", s.getSystemConfig) // - getRestMux.HandleFunc("/rest/system/config/insync", s.getSystemConfigInsync) // - getRestMux.HandleFunc("/rest/system/connections", s.getSystemConnections) // - getRestMux.HandleFunc("/rest/system/discovery", s.getSystemDiscovery) // - getRestMux.HandleFunc("/rest/system/error", s.getSystemError) // - getRestMux.HandleFunc("/rest/system/ping", s.restPing) // - getRestMux.HandleFunc("/rest/system/status", s.getSystemStatus) // - getRestMux.HandleFunc("/rest/system/upgrade", s.getSystemUpgrade) // - getRestMux.HandleFunc("/rest/system/version", s.getSystemVersion) // - // The POST handlers postRestMux := http.NewServeMux() postRestMux.HandleFunc("/rest/db/prio", s.postDBPrio) // folder file [perpage] [page] postRestMux.HandleFunc("/rest/db/ignores", s.postDBIgnores) // folder postRestMux.HandleFunc("/rest/db/override", s.postDBOverride) // folder postRestMux.HandleFunc("/rest/db/scan", s.postDBScan) // folder [sub...] [delay] postRestMux.HandleFunc("/rest/system/config", s.postSystemConfig) // <body> postRestMux.HandleFunc("/rest/system/discovery", s.postSystemDiscovery) // device addr postRestMux.HandleFunc("/rest/system/error", s.postSystemError) // <body> postRestMux.HandleFunc("/rest/system/error/clear", s.postSystemErrorClear) // - postRestMux.HandleFunc("/rest/system/ping", s.restPing) // - postRestMux.HandleFunc("/rest/system/reset", s.postSystemReset) // [folder] postRestMux.HandleFunc("/rest/system/restart", s.postSystemRestart) // - postRestMux.HandleFunc("/rest/system/shutdown", s.postSystemShutdown) // - postRestMux.HandleFunc("/rest/system/upgrade", s.postSystemUpgrade) // - // Debug endpoints, not for general use getRestMux.HandleFunc("/rest/debug/peerCompletion", s.getPeerCompletion) // A handler that splits requests between the two above and disables // caching restMux := noCacheMiddleware(getPostHandler(getRestMux, postRestMux)) // The main routing handler mux := http.NewServeMux() mux.Handle("/rest/", restMux) mux.HandleFunc("/qr/", s.getQR) // Serve compiled in assets unless an asset directory was set (for development) mux.Handle("/", embeddedStatic{ assetDir: s.assetDir, assets: auto.Assets(), }) // Wrap everything in CSRF protection. The /rest prefix should be // protected, other requests will grant cookies. handler := csrfMiddleware(s.id.String()[:5], "/rest", s.cfg.APIKey, mux) // Add our version and ID as a header to responses handler = withDetailsMiddleware(s.id, handler) // Wrap everything in basic auth, if user/password is set. if len(s.cfg.User) > 0 && len(s.cfg.Password) > 0 { handler = basicAuthAndSessionMiddleware("sessionid-"+s.id.String()[:5], s.cfg, handler) } // Redirect to HTTPS if we are supposed to if s.cfg.UseTLS { handler = redirectToHTTPSMiddleware(handler) } if debugHTTP { handler = debugMiddleware(handler) } srv := http.Server{ Handler: handler, ReadTimeout: 10 * time.Second, } s.fss = newFolderSummarySvc(s.model) defer s.fss.Stop() s.fss.ServeBackground() l.Infoln("API listening on", s.listener.Addr()) err := srv.Serve(s.listener) // The return could be due to an intentional close. Wait for the stop // signal before returning. IF there is no stop signal within a second, we // assume it was unintentional and log the error before retrying. select { case <-s.stop: case <-time.After(time.Second): l.Warnln("API:", err) } }