mirror of
https://github.com/owncast/owncast.git
synced 2024-11-23 21:28:29 +03:00
chore: reverting the current implementation of http response caching
This commit is contained in:
parent
df7eb5e38d
commit
37f3ff75de
7 changed files with 33 additions and 201 deletions
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
5
go.mod
5
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
|
||||
|
|
14
go.sum
14
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=
|
||||
|
|
5
main.go
5
main.go
|
@ -28,7 +28,6 @@ var (
|
|||
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")
|
||||
)
|
||||
|
||||
// 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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
|
Loading…
Reference in a new issue