diff --git a/config/constants.go b/config/constants.go index 2aeafde61..36fa69109 100644 --- a/config/constants.go +++ b/config/constants.go @@ -30,8 +30,4 @@ var ( // PublicFilesPath is the optional directory for hosting public files. PublicFilesPath = filepath.Join(DataDirectory, "public") - - // DisableResponseCaching will disable caching of API and resource - // responses. Disable this feature to turn off the optimizations. - DisableResponseCaching = false ) diff --git a/controllers/hls.go b/controllers/hls.go index 1b951aca5..8b9651677 100644 --- a/controllers/hls.go +++ b/controllers/hls.go @@ -6,7 +6,6 @@ import ( "path/filepath" "strconv" "strings" - "time" "github.com/owncast/owncast/config" "github.com/owncast/owncast/core" @@ -14,24 +13,8 @@ import ( "github.com/owncast/owncast/models" "github.com/owncast/owncast/router/middleware" "github.com/owncast/owncast/utils" - log "github.com/sirupsen/logrus" - cache "github.com/victorspringer/http-cache" - "github.com/victorspringer/http-cache/adapter/memory" ) -var ( - hlsCacheAdapter *cache.Adapter - hlsResponseCache *cache.Client -) - -type FileServerHandler struct { - HLSPath string -} - -func (fsh *FileServerHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) { - http.ServeFile(rw, r, fsh.HLSPath) -} - // HandleHLSRequest will manage all requests to HLS content. func HandleHLSRequest(w http.ResponseWriter, r *http.Request) { // Sanity check to limit requests to HLS file types. @@ -40,32 +23,6 @@ func HandleHLSRequest(w http.ResponseWriter, r *http.Request) { return } - if hlsCacheAdapter == nil { - ca, err := memory.NewAdapter( - memory.AdapterWithAlgorithm(memory.LRU), - memory.AdapterWithCapacity(50), - memory.AdapterWithStorageCapacity(104_857_600), - ) - hlsCacheAdapter = &ca - if err != nil { - log.Warn("unable to create web cache", err) - } - } - - // Since HLS segments cannot be changed once they're rendered, we can cache - // individual segments for a long time. - if hlsResponseCache == nil { - rc, err := cache.NewClient( - cache.ClientWithAdapter(*hlsCacheAdapter), - cache.ClientWithTTL(30*time.Second), - cache.ClientWithExpiresHeader(), - ) - hlsResponseCache = rc - if err != nil { - log.Warn("unable to create web cache client", err) - } - } - requestedPath := r.URL.Path relativePath := strings.Replace(requestedPath, "/hls/", "", 1) fullPath := filepath.Join(config.HLSStoragePath, relativePath) @@ -91,10 +48,6 @@ func HandleHLSRequest(w http.ResponseWriter, r *http.Request) { } else { cacheTime := utils.GetCacheDurationSecondsForPath(relativePath) w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(cacheTime)) - - fileServer := &FileServerHandler{HLSPath: fullPath} - hlsResponseCache.Middleware(fileServer).ServeHTTP(w, r) - return } middleware.EnableCors(w) diff --git a/controllers/index.go b/controllers/index.go index 437857b5e..9ae240abd 100644 --- a/controllers/index.go +++ b/controllers/index.go @@ -7,7 +7,6 @@ import ( "net/url" "path/filepath" "strings" - "time" "github.com/owncast/owncast/config" "github.com/owncast/owncast/core" @@ -17,45 +16,12 @@ import ( "github.com/owncast/owncast/static" "github.com/owncast/owncast/utils" log "github.com/sirupsen/logrus" - cache "github.com/victorspringer/http-cache" - "github.com/victorspringer/http-cache/adapter/memory" -) - -var ( - indexCacheAdapter *cache.Adapter - indexBotSearchCache *cache.Client ) // IndexHandler handles the default index route. func IndexHandler(w http.ResponseWriter, r *http.Request) { middleware.EnableCors(w) - if indexCacheAdapter == nil { - ca, err := memory.NewAdapter( - memory.AdapterWithAlgorithm(memory.LFU), - memory.AdapterWithCapacity(50), - memory.AdapterWithStorageCapacity(104_857_600), - ) - indexCacheAdapter = &ca - if err != nil { - log.Warn("unable to create web cache", err) - } - } - - if indexBotSearchCache == nil { - rc, err := cache.NewClient( - cache.ClientWithAdapter(*indexCacheAdapter), - cache.ClientWithTTL(30*time.Second), - cache.ClientWithExpiresHeader(), - cache.ClientWithRefreshKey("bot-search-page"), - cache.ClientWithExpiresHeader(), - ) - indexBotSearchCache = rc - if err != nil { - log.Warn("unable to create web cache client", err) - } - } - isIndexRequest := r.URL.Path == "/" || filepath.Base(r.URL.Path) == "index.html" || filepath.Base(r.URL.Path) == "" if utils.IsUserAgentAPlayer(r.UserAgent()) && isIndexRequest { @@ -66,7 +32,7 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { // For search engine bots and social scrapers return a special // server-rendered page. if utils.IsUserAgentABot(r.UserAgent()) && isIndexRequest { - indexBotSearchCache.Middleware(http.HandlerFunc(handleScraperMetadataPage)) + handleScraperMetadataPage(w, r) return } diff --git a/go.mod b/go.mod index e30c620d0..afd9089d7 100644 --- a/go.mod +++ b/go.mod @@ -31,9 +31,9 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - golang.org/x/crypto v0.17.0 // indirect + golang.org/x/crypto v0.15.0 // indirect golang.org/x/net v0.18.0 - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.14.0 // indirect ) require github.com/prometheus/client_golang v1.17.0 @@ -75,7 +75,6 @@ require ( github.com/CAFxX/httpcompression v0.0.9 github.com/andybalholm/cascadia v1.3.2 github.com/mssola/user_agent v0.6.0 - github.com/victorspringer/http-cache v0.0.0-20231006141456-6446fe59efba github.com/yuin/goldmark-emoji v1.0.2 gopkg.in/evanphx/json-patch.v5 v5.7.0 mvdan.cc/xurls v1.1.0 diff --git a/go.sum b/go.sum index a8bd9fc0d..f08e0acc2 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,6 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/valyala/gozstd v1.20.1 h1:xPnnnvjmaDDitMFfDxmQ4vpx0+3CdTg2o3lALvXTU/g= github.com/valyala/gozstd v1.20.1/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ= -github.com/victorspringer/http-cache v0.0.0-20231006141456-6446fe59efba h1:+oqDKQIOdkkvro1psUKtI4oH9WBeKkGY2S8h9/lo288= -github.com/victorspringer/http-cache v0.0.0-20231006141456-6446fe59efba/go.mod h1:D1AD6nlXv7HkIfTVd8ZWK1KQEiXYNy/LbLkx8H9tIQw= github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= @@ -149,8 +147,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= @@ -184,15 +182,15 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/main.go b/main.go index 0a74859f9..a304d9d58 100644 --- a/main.go +++ b/main.go @@ -17,18 +17,17 @@ import ( ) var ( - dbFile = flag.String("database", "", "Path to the database file.") - logDirectory = flag.String("logdir", "", "Directory where logs will be written to") - backupDirectory = flag.String("backupdir", "", "Directory where backups will be written to") - enableDebugOptions = flag.Bool("enableDebugFeatures", false, "Enable additional debugging options.") - enableVerboseLogging = flag.Bool("enableVerboseLogging", false, "Enable additional logging.") - restoreDatabaseFile = flag.String("restoreDatabase", "", "Restore an Owncast database backup") - newAdminPassword = flag.String("adminpassword", "", "Set your admin password") - newStreamKey = flag.String("streamkey", "", "Set a temporary stream key for this session") - webServerPortOverride = flag.String("webserverport", "", "Force the web server to listen on a specific port") - webServerIPOverride = flag.String("webserverip", "", "Force web server to listen on this IP address") - rtmpPortOverride = flag.Int("rtmpport", 0, "Set listen port for the RTMP server") - disableResponseCaching = flag.Bool("disableResponseCaching", false, "Do not optimize performance by caching of web responses") + dbFile = flag.String("database", "", "Path to the database file.") + logDirectory = flag.String("logdir", "", "Directory where logs will be written to") + backupDirectory = flag.String("backupdir", "", "Directory where backups will be written to") + enableDebugOptions = flag.Bool("enableDebugFeatures", false, "Enable additional debugging options.") + enableVerboseLogging = flag.Bool("enableVerboseLogging", false, "Enable additional logging.") + restoreDatabaseFile = flag.String("restoreDatabase", "", "Restore an Owncast database backup") + newAdminPassword = flag.String("adminpassword", "", "Set your admin password") + newStreamKey = flag.String("streamkey", "", "Set a temporary stream key for this session") + webServerPortOverride = flag.String("webserverport", "", "Force the web server to listen on a specific port") + webServerIPOverride = flag.String("webserverip", "", "Force web server to listen on this IP address") + rtmpPortOverride = flag.Int("rtmpport", 0, "Set listen port for the RTMP server") ) // nolint:cyclop @@ -43,10 +42,6 @@ func main() { config.BackupDirectory = *backupDirectory } - if *disableResponseCaching { - config.DisableResponseCaching = *disableResponseCaching - } - // Create the data directory if needed if !utils.DoesFileExists("data") { if err := os.Mkdir("./data", 0o700); err != nil { diff --git a/router/router.go b/router/router.go index 98d2bc457..c1866eb5f 100644 --- a/router/router.go +++ b/router/router.go @@ -24,45 +24,10 @@ import ( "github.com/owncast/owncast/router/middleware" "github.com/owncast/owncast/utils" "github.com/owncast/owncast/yp" - - cache "github.com/victorspringer/http-cache" - "github.com/victorspringer/http-cache/adapter/memory" ) // Start starts the router for the http, ws, and rtmp. func Start() error { - // Setup a web response cache - enableCache := !config.DisableResponseCaching - - responseCache, err := memory.NewAdapter( - memory.AdapterWithAlgorithm(memory.LRU), - memory.AdapterWithCapacity(50), - ) - if err != nil { - log.Warn("unable to create web cache", err) - } - - superShortCacheClient, err := cache.NewClient( - cache.ClientWithAdapter(responseCache), - cache.ClientWithTTL(3*time.Second), - ) - if err != nil { - log.Warn("unable to create web cache client", err) - } - reasonableDurationCacheClient, err := cache.NewClient( - cache.ClientWithAdapter(responseCache), - cache.ClientWithTTL(8*time.Second), - ) - if err != nil { - log.Warn("unable to create web cache client", err) - } - longerDurationCacheClient, err := cache.NewClient( - cache.ClientWithAdapter(responseCache), - cache.ClientWithTTL(3*time.Minute), - ) - if err != nil { - log.Warn("unable to create web cache client", err) - } // The primary web app. http.HandleFunc("/", controllers.IndexHandler) @@ -70,79 +35,41 @@ func Start() error { http.HandleFunc("/admin/", middleware.RequireAdminAuth(controllers.IndexHandler)) // Images - http.HandleFunc("/thumbnail.jpg", func(rw http.ResponseWriter, r *http.Request) { - superShortCacheClient.Middleware(http.HandlerFunc(controllers.GetThumbnail)).ServeHTTP(rw, r) - }) - - http.HandleFunc("/preview.gif", func(rw http.ResponseWriter, r *http.Request) { - superShortCacheClient.Middleware(http.HandlerFunc(controllers.GetPreview)).ServeHTTP(rw, r) - }) - - http.HandleFunc("/logo", func(rw http.ResponseWriter, r *http.Request) { - longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetLogo)).ServeHTTP(rw, r) - }) + http.HandleFunc("/thumbnail.jpg", controllers.GetThumbnail) + http.HandleFunc("/preview.gif", controllers.GetPreview) + http.HandleFunc("/logo", controllers.GetLogo) // Custom Javascript - http.HandleFunc("/customjavascript", func(rw http.ResponseWriter, r *http.Request) { - longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.ServeCustomJavascript)).ServeHTTP(rw, r) - }) + http.HandleFunc("/customjavascript", controllers.ServeCustomJavascript) // Return a single emoji image. - http.HandleFunc(config.EmojiDir, func(rw http.ResponseWriter, r *http.Request) { - longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetCustomEmojiImage)).ServeHTTP(rw, r) - }) + http.HandleFunc(config.EmojiDir, controllers.GetCustomEmojiImage) // return the logo // return a logo that's compatible with external social networks - http.HandleFunc("/logo/external", func(rw http.ResponseWriter, r *http.Request) { - longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetCompatibleLogo)).ServeHTTP(rw, r) - }) + http.HandleFunc("/logo/external", controllers.GetCompatibleLogo) // robots.txt - http.HandleFunc("/robots.txt", func(rw http.ResponseWriter, r *http.Request) { - longerDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetRobotsDotTxt)).ServeHTTP(rw, r) - }) + http.HandleFunc("/robots.txt", controllers.GetRobotsDotTxt) // status of the system - if enableCache { - http.HandleFunc("/api/status", func(rw http.ResponseWriter, r *http.Request) { - superShortCacheClient.Middleware(http.HandlerFunc(controllers.GetStatus)).ServeHTTP(rw, r) - }) - } else { - http.HandleFunc("/api/status", controllers.GetStatus) - } + http.HandleFunc("/api/status", controllers.GetStatus) // custom emoji supported in the chat - http.HandleFunc("/api/emoji", func(rw http.ResponseWriter, r *http.Request) { - reasonableDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetCustomEmojiList)).ServeHTTP(rw, r) - }) + http.HandleFunc("/api/emoji", controllers.GetCustomEmojiList) // chat rest api - if enableCache { - http.HandleFunc("/api/chat", func(rw http.ResponseWriter, r *http.Request) { - superShortCacheClient.Middleware(middleware.RequireUserAccessToken(controllers.GetChatMessages)) - }) - } else { - http.HandleFunc("/api/chat", middleware.RequireUserAccessToken(controllers.GetChatMessages)) - } + http.HandleFunc("/api/chat", middleware.RequireUserAccessToken(controllers.GetChatMessages)) // web config api - if enableCache { - http.HandleFunc("/api/config", func(rw http.ResponseWriter, r *http.Request) { - superShortCacheClient.Middleware(http.HandlerFunc(controllers.GetWebConfig)).ServeHTTP(rw, r) - }) - } else { - http.HandleFunc("/api/config", controllers.GetWebConfig) - } + http.HandleFunc("/api/config", controllers.GetWebConfig) // return the YP protocol data http.HandleFunc("/api/yp", yp.GetYPResponse) // list of all social platforms - http.HandleFunc("/api/socialplatforms", func(rw http.ResponseWriter, r *http.Request) { - reasonableDurationCacheClient.Middleware(http.HandlerFunc(controllers.GetAllSocialPlatforms)).ServeHTTP(rw, r) - }) + http.HandleFunc("/api/socialplatforms", controllers.GetAllSocialPlatforms) // return the list of video variants available http.HandleFunc("/api/video/variants", controllers.GetVideoStreamOutputVariants) @@ -157,9 +84,7 @@ func Start() error { http.HandleFunc("/api/remotefollow", controllers.RemoteFollow) // return followers - http.HandleFunc("/api/followers", func(rw http.ResponseWriter, r *http.Request) { - reasonableDurationCacheClient.Middleware(middleware.HandlePagination(controllers.GetFollowers)).ServeHTTP(rw, r) - }) + http.HandleFunc("/api/followers", middleware.HandlePagination(controllers.GetFollowers)) // save client video playback metrics http.HandleFunc("/api/metrics/playback", controllers.ReportPlaybackMetrics) diff --git a/test/automated/tools.sh b/test/automated/tools.sh index f9cc42f5a..97e3ced49 100755 --- a/test/automated/tools.sh +++ b/test/automated/tools.sh @@ -43,7 +43,7 @@ function start_owncast() { go build -o owncast main.go echo "Running owncast..." - ./owncast -disableResponseCaching -database "$TEMP_DB" & + ./owncast -database "$TEMP_DB" & SERVER_PID=$! popd >/dev/null