mirror of
https://github.com/owncast/owncast.git
synced 2024-11-24 05:38:58 +03:00
feat: refactor web server + router. First step in #1749
This commit is contained in:
parent
37f3ff75de
commit
551440f3b6
32 changed files with 568 additions and 469 deletions
|
@ -1,6 +1,8 @@
|
||||||
package activitypub
|
package activitypub
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/owncast/owncast/activitypub/crypto"
|
"github.com/owncast/owncast/activitypub/crypto"
|
||||||
"github.com/owncast/owncast/activitypub/inbox"
|
"github.com/owncast/owncast/activitypub/inbox"
|
||||||
"github.com/owncast/owncast/activitypub/outbox"
|
"github.com/owncast/owncast/activitypub/outbox"
|
||||||
|
@ -13,11 +15,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Start will initialize and start the federation support.
|
// Start will initialize and start the federation support.
|
||||||
func Start(datastore *data.Datastore) {
|
func Start(datastore *data.Datastore, router *http.ServeMux) {
|
||||||
persistence.Setup(datastore)
|
persistence.Setup(datastore)
|
||||||
workerpool.InitOutboundWorkerPool()
|
workerpool.InitOutboundWorkerPool()
|
||||||
inbox.InitInboxWorkerPool()
|
inbox.InitInboxWorkerPool()
|
||||||
StartRouter()
|
StartRouter(router)
|
||||||
|
|
||||||
// Generate the keys for signing federated activity if needed.
|
// Generate the keys for signing federated activity if needed.
|
||||||
if data.GetPrivateKey() == "" {
|
if data.GetPrivateKey() == "" {
|
||||||
|
|
|
@ -4,32 +4,32 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/owncast/owncast/activitypub/controllers"
|
"github.com/owncast/owncast/activitypub/controllers"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartRouter will start the federation specific http router.
|
// StartRouter will start the federation specific http router.
|
||||||
func StartRouter() {
|
func StartRouter(router *http.ServeMux) {
|
||||||
// WebFinger
|
// WebFinger
|
||||||
http.HandleFunc("/.well-known/webfinger", controllers.WebfingerHandler)
|
router.HandleFunc("/.well-known/webfinger", controllers.WebfingerHandler)
|
||||||
|
|
||||||
// Host Metadata
|
// Host Metadata
|
||||||
http.HandleFunc("/.well-known/host-meta", controllers.HostMetaController)
|
router.HandleFunc("/.well-known/host-meta", controllers.HostMetaController)
|
||||||
|
|
||||||
// Nodeinfo v1
|
// Nodeinfo v1
|
||||||
http.HandleFunc("/.well-known/nodeinfo", controllers.NodeInfoController)
|
router.HandleFunc("/.well-known/nodeinfo", controllers.NodeInfoController)
|
||||||
|
|
||||||
// x-nodeinfo v2
|
// x-nodeinfo v2
|
||||||
http.HandleFunc("/.well-known/x-nodeinfo2", controllers.XNodeInfo2Controller)
|
router.HandleFunc("/.well-known/x-nodeinfo2", controllers.XNodeInfo2Controller)
|
||||||
|
|
||||||
// Nodeinfo v2
|
// Nodeinfo v2
|
||||||
http.HandleFunc("/nodeinfo/2.0", controllers.NodeInfoV2Controller)
|
router.HandleFunc("/nodeinfo/2.0", controllers.NodeInfoV2Controller)
|
||||||
|
|
||||||
// Instance details
|
// Instance details
|
||||||
http.HandleFunc("/api/v1/instance", controllers.InstanceV1Controller)
|
router.HandleFunc("/api/v1/instance", controllers.InstanceV1Controller)
|
||||||
|
|
||||||
// Single ActivityPub Actor
|
// Single ActivityPub Actor
|
||||||
http.HandleFunc("/federation/user/", middleware.RequireActivityPubOrRedirect(controllers.ActorHandler))
|
router.HandleFunc("/federation/user/", middleware.RequireActivityPubOrRedirect(controllers.ActorHandler))
|
||||||
|
|
||||||
// Single AP object
|
// Single AP object
|
||||||
http.HandleFunc("/federation/", middleware.RequireActivityPubOrRedirect(controllers.ObjectHandler))
|
router.HandleFunc("/federation/", middleware.RequireActivityPubOrRedirect(controllers.ObjectHandler))
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"github.com/owncast/owncast/core/data"
|
"github.com/owncast/owncast/core/data"
|
||||||
"github.com/owncast/owncast/core/transcoder"
|
"github.com/owncast/owncast/core/transcoder"
|
||||||
"github.com/owncast/owncast/models"
|
"github.com/owncast/owncast/models"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
|
||||||
"github.com/owncast/owncast/utils"
|
"github.com/owncast/owncast/utils"
|
||||||
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/owncast/owncast/core/data"
|
"github.com/owncast/owncast/core/data"
|
||||||
"github.com/owncast/owncast/metrics"
|
"github.com/owncast/owncast/metrics"
|
||||||
"github.com/owncast/owncast/models"
|
"github.com/owncast/owncast/models"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
ia "github.com/owncast/owncast/auth/indieauth"
|
ia "github.com/owncast/owncast/auth/indieauth"
|
||||||
"github.com/owncast/owncast/controllers"
|
"github.com/owncast/owncast/controllers"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandleAuthEndpoint will handle the IndieAuth auth endpoint.
|
// HandleAuthEndpoint will handle the IndieAuth auth endpoint.
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"github.com/owncast/owncast/config"
|
"github.com/owncast/owncast/config"
|
||||||
"github.com/owncast/owncast/core/chat"
|
"github.com/owncast/owncast/core/chat"
|
||||||
"github.com/owncast/owncast/core/user"
|
"github.com/owncast/owncast/core/user"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
|
||||||
"github.com/owncast/owncast/utils"
|
"github.com/owncast/owncast/utils"
|
||||||
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"github.com/owncast/owncast/config"
|
"github.com/owncast/owncast/config"
|
||||||
"github.com/owncast/owncast/core/data"
|
"github.com/owncast/owncast/core/data"
|
||||||
"github.com/owncast/owncast/models"
|
"github.com/owncast/owncast/models"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
|
||||||
"github.com/owncast/owncast/utils"
|
"github.com/owncast/owncast/utils"
|
||||||
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/owncast/owncast/models"
|
"github.com/owncast/owncast/models"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"github.com/owncast/owncast/core"
|
"github.com/owncast/owncast/core"
|
||||||
"github.com/owncast/owncast/core/data"
|
"github.com/owncast/owncast/core/data"
|
||||||
"github.com/owncast/owncast/models"
|
"github.com/owncast/owncast/models"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
|
||||||
"github.com/owncast/owncast/utils"
|
"github.com/owncast/owncast/utils"
|
||||||
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandleHLSRequest will manage all requests to HLS content.
|
// HandleHLSRequest will manage all requests to HLS content.
|
||||||
|
|
|
@ -12,9 +12,9 @@ import (
|
||||||
"github.com/owncast/owncast/core"
|
"github.com/owncast/owncast/core"
|
||||||
"github.com/owncast/owncast/core/data"
|
"github.com/owncast/owncast/core/data"
|
||||||
"github.com/owncast/owncast/models"
|
"github.com/owncast/owncast/models"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
|
||||||
"github.com/owncast/owncast/static"
|
"github.com/owncast/owncast/static"
|
||||||
"github.com/owncast/owncast/utils"
|
"github.com/owncast/owncast/utils"
|
||||||
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
|
|
||||||
"github.com/owncast/owncast/core"
|
"github.com/owncast/owncast/core"
|
||||||
"github.com/owncast/owncast/core/data"
|
"github.com/owncast/owncast/core/data"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
|
||||||
"github.com/owncast/owncast/utils"
|
"github.com/owncast/owncast/utils"
|
||||||
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetStatus gets the status of the server.
|
// GetStatus gets the status of the server.
|
||||||
|
|
7
main.go
7
main.go
|
@ -6,13 +6,13 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/owncast/owncast/logging"
|
"github.com/owncast/owncast/logging"
|
||||||
|
"github.com/owncast/owncast/webserver"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/owncast/owncast/config"
|
"github.com/owncast/owncast/config"
|
||||||
"github.com/owncast/owncast/core"
|
"github.com/owncast/owncast/core"
|
||||||
"github.com/owncast/owncast/core/data"
|
"github.com/owncast/owncast/core/data"
|
||||||
"github.com/owncast/owncast/metrics"
|
"github.com/owncast/owncast/metrics"
|
||||||
"github.com/owncast/owncast/router"
|
|
||||||
"github.com/owncast/owncast/utils"
|
"github.com/owncast/owncast/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -105,8 +105,9 @@ func main() {
|
||||||
|
|
||||||
go metrics.Start(core.GetStatus)
|
go metrics.Start(core.GetStatus)
|
||||||
|
|
||||||
if err := router.Start(); err != nil {
|
webserver := webserver.New()
|
||||||
log.Fatalln("failed to start/run the router", err)
|
if err := webserver.Start(config.WebServerIP, config.WebServerPort); err != nil {
|
||||||
|
log.Fatalln("failed to start/run the web server", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
444
router/router.go
444
router/router.go
|
@ -1,444 +0,0 @@
|
||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/CAFxX/httpcompression"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/net/http2"
|
|
||||||
"golang.org/x/net/http2/h2c"
|
|
||||||
|
|
||||||
"github.com/owncast/owncast/activitypub"
|
|
||||||
"github.com/owncast/owncast/config"
|
|
||||||
"github.com/owncast/owncast/controllers"
|
|
||||||
"github.com/owncast/owncast/controllers/admin"
|
|
||||||
fediverseauth "github.com/owncast/owncast/controllers/auth/fediverse"
|
|
||||||
"github.com/owncast/owncast/controllers/auth/indieauth"
|
|
||||||
"github.com/owncast/owncast/controllers/moderation"
|
|
||||||
"github.com/owncast/owncast/core/chat"
|
|
||||||
"github.com/owncast/owncast/core/data"
|
|
||||||
"github.com/owncast/owncast/core/user"
|
|
||||||
"github.com/owncast/owncast/router/middleware"
|
|
||||||
"github.com/owncast/owncast/utils"
|
|
||||||
"github.com/owncast/owncast/yp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Start starts the router for the http, ws, and rtmp.
|
|
||||||
func Start() error {
|
|
||||||
// The primary web app.
|
|
||||||
http.HandleFunc("/", controllers.IndexHandler)
|
|
||||||
|
|
||||||
// The admin web app.
|
|
||||||
http.HandleFunc("/admin/", middleware.RequireAdminAuth(controllers.IndexHandler))
|
|
||||||
|
|
||||||
// Images
|
|
||||||
http.HandleFunc("/thumbnail.jpg", controllers.GetThumbnail)
|
|
||||||
http.HandleFunc("/preview.gif", controllers.GetPreview)
|
|
||||||
http.HandleFunc("/logo", controllers.GetLogo)
|
|
||||||
|
|
||||||
// Custom Javascript
|
|
||||||
http.HandleFunc("/customjavascript", controllers.ServeCustomJavascript)
|
|
||||||
|
|
||||||
// Return a single emoji image.
|
|
||||||
http.HandleFunc(config.EmojiDir, controllers.GetCustomEmojiImage)
|
|
||||||
|
|
||||||
// return the logo
|
|
||||||
|
|
||||||
// return a logo that's compatible with external social networks
|
|
||||||
http.HandleFunc("/logo/external", controllers.GetCompatibleLogo)
|
|
||||||
|
|
||||||
// robots.txt
|
|
||||||
http.HandleFunc("/robots.txt", controllers.GetRobotsDotTxt)
|
|
||||||
|
|
||||||
// status of the system
|
|
||||||
http.HandleFunc("/api/status", controllers.GetStatus)
|
|
||||||
|
|
||||||
// custom emoji supported in the chat
|
|
||||||
http.HandleFunc("/api/emoji", controllers.GetCustomEmojiList)
|
|
||||||
|
|
||||||
// chat rest api
|
|
||||||
http.HandleFunc("/api/chat", middleware.RequireUserAccessToken(controllers.GetChatMessages))
|
|
||||||
|
|
||||||
// web config api
|
|
||||||
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", controllers.GetAllSocialPlatforms)
|
|
||||||
|
|
||||||
// return the list of video variants available
|
|
||||||
http.HandleFunc("/api/video/variants", controllers.GetVideoStreamOutputVariants)
|
|
||||||
|
|
||||||
// tell the backend you're an active viewer
|
|
||||||
http.HandleFunc("/api/ping", controllers.Ping)
|
|
||||||
|
|
||||||
// register a new chat user
|
|
||||||
http.HandleFunc("/api/chat/register", controllers.RegisterAnonymousChatUser)
|
|
||||||
|
|
||||||
// return remote follow details
|
|
||||||
http.HandleFunc("/api/remotefollow", controllers.RemoteFollow)
|
|
||||||
|
|
||||||
// return followers
|
|
||||||
http.HandleFunc("/api/followers", middleware.HandlePagination(controllers.GetFollowers))
|
|
||||||
|
|
||||||
// save client video playback metrics
|
|
||||||
http.HandleFunc("/api/metrics/playback", controllers.ReportPlaybackMetrics)
|
|
||||||
|
|
||||||
// Register for notifications
|
|
||||||
http.HandleFunc("/api/notifications/register", middleware.RequireUserAccessToken(controllers.RegisterForLiveNotifications))
|
|
||||||
|
|
||||||
// Authenticated admin requests
|
|
||||||
|
|
||||||
// Current inbound broadcaster
|
|
||||||
http.HandleFunc("/api/admin/status", middleware.RequireAdminAuth(admin.Status))
|
|
||||||
|
|
||||||
// Return HLS video
|
|
||||||
http.HandleFunc("/hls/", controllers.HandleHLSRequest)
|
|
||||||
|
|
||||||
// Disconnect inbound stream
|
|
||||||
http.HandleFunc("/api/admin/disconnect", middleware.RequireAdminAuth(admin.DisconnectInboundConnection))
|
|
||||||
|
|
||||||
// Server config
|
|
||||||
http.HandleFunc("/api/admin/serverconfig", middleware.RequireAdminAuth(admin.GetServerConfig))
|
|
||||||
|
|
||||||
// Get viewer count over time
|
|
||||||
http.HandleFunc("/api/admin/viewersOverTime", middleware.RequireAdminAuth(admin.GetViewersOverTime))
|
|
||||||
|
|
||||||
// Get active viewers
|
|
||||||
http.HandleFunc("/api/admin/viewers", middleware.RequireAdminAuth(admin.GetActiveViewers))
|
|
||||||
|
|
||||||
// Get hardware stats
|
|
||||||
http.HandleFunc("/api/admin/hardwarestats", middleware.RequireAdminAuth(admin.GetHardwareStats))
|
|
||||||
|
|
||||||
// Get a a detailed list of currently connected chat clients
|
|
||||||
http.HandleFunc("/api/admin/chat/clients", middleware.RequireAdminAuth(admin.GetConnectedChatClients))
|
|
||||||
|
|
||||||
// Get all logs
|
|
||||||
http.HandleFunc("/api/admin/logs", middleware.RequireAdminAuth(admin.GetLogs))
|
|
||||||
|
|
||||||
// Get warning/error logs
|
|
||||||
http.HandleFunc("/api/admin/logs/warnings", middleware.RequireAdminAuth(admin.GetWarnings))
|
|
||||||
|
|
||||||
// Get all chat messages for the admin, unfiltered.
|
|
||||||
http.HandleFunc("/api/admin/chat/messages", middleware.RequireAdminAuth(admin.GetChatMessages))
|
|
||||||
|
|
||||||
// Update chat message visibility
|
|
||||||
http.HandleFunc("/api/admin/chat/messagevisibility", middleware.RequireAdminAuth(admin.UpdateMessageVisibility))
|
|
||||||
|
|
||||||
// Enable/disable a user
|
|
||||||
http.HandleFunc("/api/admin/chat/users/setenabled", middleware.RequireAdminAuth(admin.UpdateUserEnabled))
|
|
||||||
|
|
||||||
// Ban/unban an IP address
|
|
||||||
http.HandleFunc("/api/admin/chat/users/ipbans/create", middleware.RequireAdminAuth(admin.BanIPAddress))
|
|
||||||
|
|
||||||
// Remove an IP address ban
|
|
||||||
http.HandleFunc("/api/admin/chat/users/ipbans/remove", middleware.RequireAdminAuth(admin.UnBanIPAddress))
|
|
||||||
|
|
||||||
// Return all the banned IP addresses
|
|
||||||
http.HandleFunc("/api/admin/chat/users/ipbans", middleware.RequireAdminAuth(admin.GetIPAddressBans))
|
|
||||||
|
|
||||||
// Get a list of disabled users
|
|
||||||
http.HandleFunc("/api/admin/chat/users/disabled", middleware.RequireAdminAuth(admin.GetDisabledUsers))
|
|
||||||
|
|
||||||
// Set moderator status for a user
|
|
||||||
http.HandleFunc("/api/admin/chat/users/setmoderator", middleware.RequireAdminAuth(admin.UpdateUserModerator))
|
|
||||||
|
|
||||||
// Get a list of moderator users
|
|
||||||
http.HandleFunc("/api/admin/chat/users/moderators", middleware.RequireAdminAuth(admin.GetModerators))
|
|
||||||
|
|
||||||
// return followers
|
|
||||||
http.HandleFunc("/api/admin/followers", middleware.RequireAdminAuth(middleware.HandlePagination(controllers.GetFollowers)))
|
|
||||||
|
|
||||||
// Get a list of pending follow requests
|
|
||||||
http.HandleFunc("/api/admin/followers/pending", middleware.RequireAdminAuth(admin.GetPendingFollowRequests))
|
|
||||||
|
|
||||||
// Get a list of rejected or blocked follows
|
|
||||||
http.HandleFunc("/api/admin/followers/blocked", middleware.RequireAdminAuth(admin.GetBlockedAndRejectedFollowers))
|
|
||||||
|
|
||||||
// Set the following state of a follower or follow request.
|
|
||||||
http.HandleFunc("/api/admin/followers/approve", middleware.RequireAdminAuth(admin.ApproveFollower))
|
|
||||||
|
|
||||||
// Upload custom emoji
|
|
||||||
http.HandleFunc("/api/admin/emoji/upload", middleware.RequireAdminAuth(admin.UploadCustomEmoji))
|
|
||||||
|
|
||||||
// Delete custom emoji
|
|
||||||
http.HandleFunc("/api/admin/emoji/delete", middleware.RequireAdminAuth(admin.DeleteCustomEmoji))
|
|
||||||
|
|
||||||
// Update config values
|
|
||||||
|
|
||||||
// Change the current streaming key in memory
|
|
||||||
http.HandleFunc("/api/admin/config/adminpass", middleware.RequireAdminAuth(admin.SetAdminPassword))
|
|
||||||
|
|
||||||
// Set an array of valid stream keys
|
|
||||||
http.HandleFunc("/api/admin/config/streamkeys", middleware.RequireAdminAuth(admin.SetStreamKeys))
|
|
||||||
|
|
||||||
// Change the extra page content in memory
|
|
||||||
http.HandleFunc("/api/admin/config/pagecontent", middleware.RequireAdminAuth(admin.SetExtraPageContent))
|
|
||||||
|
|
||||||
// Stream title
|
|
||||||
http.HandleFunc("/api/admin/config/streamtitle", middleware.RequireAdminAuth(admin.SetStreamTitle))
|
|
||||||
|
|
||||||
// Server name
|
|
||||||
http.HandleFunc("/api/admin/config/name", middleware.RequireAdminAuth(admin.SetServerName))
|
|
||||||
|
|
||||||
// Server summary
|
|
||||||
http.HandleFunc("/api/admin/config/serversummary", middleware.RequireAdminAuth(admin.SetServerSummary))
|
|
||||||
|
|
||||||
// Offline message
|
|
||||||
http.HandleFunc("/api/admin/config/offlinemessage", middleware.RequireAdminAuth(admin.SetCustomOfflineMessage))
|
|
||||||
|
|
||||||
// Server welcome message
|
|
||||||
http.HandleFunc("/api/admin/config/welcomemessage", middleware.RequireAdminAuth(admin.SetServerWelcomeMessage))
|
|
||||||
|
|
||||||
// Disable chat
|
|
||||||
http.HandleFunc("/api/admin/config/chat/disable", middleware.RequireAdminAuth(admin.SetChatDisabled))
|
|
||||||
|
|
||||||
// Disable chat user join messages
|
|
||||||
http.HandleFunc("/api/admin/config/chat/joinmessagesenabled", middleware.RequireAdminAuth(admin.SetChatJoinMessagesEnabled))
|
|
||||||
|
|
||||||
// Enable/disable chat established user mode
|
|
||||||
http.HandleFunc("/api/admin/config/chat/establishedusermode", middleware.RequireAdminAuth(admin.SetEnableEstablishedChatUserMode))
|
|
||||||
|
|
||||||
// Set chat usernames that are not allowed
|
|
||||||
http.HandleFunc("/api/admin/config/chat/forbiddenusernames", middleware.RequireAdminAuth(admin.SetForbiddenUsernameList))
|
|
||||||
|
|
||||||
// Set the suggested chat usernames that will be assigned automatically
|
|
||||||
http.HandleFunc("/api/admin/config/chat/suggestedusernames", middleware.RequireAdminAuth(admin.SetSuggestedUsernameList))
|
|
||||||
|
|
||||||
// Set video codec
|
|
||||||
http.HandleFunc("/api/admin/config/video/codec", middleware.RequireAdminAuth(admin.SetVideoCodec))
|
|
||||||
|
|
||||||
// Set style/color/css values
|
|
||||||
http.HandleFunc("/api/admin/config/appearance", middleware.RequireAdminAuth(admin.SetCustomColorVariableValues))
|
|
||||||
|
|
||||||
// Return all webhooks
|
|
||||||
http.HandleFunc("/api/admin/webhooks", middleware.RequireAdminAuth(admin.GetWebhooks))
|
|
||||||
|
|
||||||
// Delete a single webhook
|
|
||||||
http.HandleFunc("/api/admin/webhooks/delete", middleware.RequireAdminAuth(admin.DeleteWebhook))
|
|
||||||
|
|
||||||
// Create a single webhook
|
|
||||||
http.HandleFunc("/api/admin/webhooks/create", middleware.RequireAdminAuth(admin.CreateWebhook))
|
|
||||||
|
|
||||||
// Get all access tokens
|
|
||||||
http.HandleFunc("/api/admin/accesstokens", middleware.RequireAdminAuth(admin.GetExternalAPIUsers))
|
|
||||||
|
|
||||||
// Delete a single access token
|
|
||||||
http.HandleFunc("/api/admin/accesstokens/delete", middleware.RequireAdminAuth(admin.DeleteExternalAPIUser))
|
|
||||||
|
|
||||||
// Create a single access token
|
|
||||||
http.HandleFunc("/api/admin/accesstokens/create", middleware.RequireAdminAuth(admin.CreateExternalAPIUser))
|
|
||||||
|
|
||||||
// Return the auto-update features that are supported for this instance.
|
|
||||||
http.HandleFunc("/api/admin/update/options", middleware.RequireAdminAuth(admin.AutoUpdateOptions))
|
|
||||||
|
|
||||||
// Begin the auto update
|
|
||||||
http.HandleFunc("/api/admin/update/start", middleware.RequireAdminAuth(admin.AutoUpdateStart))
|
|
||||||
|
|
||||||
// Force quit the service to restart it
|
|
||||||
http.HandleFunc("/api/admin/update/forcequit", middleware.RequireAdminAuth(admin.AutoUpdateForceQuit))
|
|
||||||
|
|
||||||
// Send a system message to chat
|
|
||||||
http.HandleFunc("/api/integrations/chat/system", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendSystemMessages, admin.SendSystemMessage))
|
|
||||||
|
|
||||||
// Send a system message to a single client
|
|
||||||
http.HandleFunc(utils.RestEndpoint("/api/integrations/chat/system/client/{clientId}", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendSystemMessages, admin.SendSystemMessageToConnectedClient)))
|
|
||||||
|
|
||||||
// Send a user message to chat *NO LONGER SUPPORTED
|
|
||||||
http.HandleFunc("/api/integrations/chat/user", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendChatMessages, admin.SendUserMessage))
|
|
||||||
|
|
||||||
// Send a message to chat as a specific 3rd party bot/integration based on its access token
|
|
||||||
http.HandleFunc("/api/integrations/chat/send", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendChatMessages, admin.SendIntegrationChatMessage))
|
|
||||||
|
|
||||||
// Send a user action to chat
|
|
||||||
http.HandleFunc("/api/integrations/chat/action", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendSystemMessages, admin.SendChatAction))
|
|
||||||
|
|
||||||
// Hide chat message
|
|
||||||
http.HandleFunc("/api/integrations/chat/messagevisibility", middleware.RequireExternalAPIAccessToken(user.ScopeHasAdminAccess, admin.ExternalUpdateMessageVisibility))
|
|
||||||
|
|
||||||
// Stream title
|
|
||||||
http.HandleFunc("/api/integrations/streamtitle", middleware.RequireExternalAPIAccessToken(user.ScopeHasAdminAccess, admin.ExternalSetStreamTitle))
|
|
||||||
|
|
||||||
// Get chat history
|
|
||||||
http.HandleFunc("/api/integrations/chat", middleware.RequireExternalAPIAccessToken(user.ScopeHasAdminAccess, controllers.ExternalGetChatMessages))
|
|
||||||
|
|
||||||
// Connected clients
|
|
||||||
http.HandleFunc("/api/integrations/clients", middleware.RequireExternalAPIAccessToken(user.ScopeHasAdminAccess, admin.ExternalGetConnectedChatClients))
|
|
||||||
|
|
||||||
// Logo path
|
|
||||||
http.HandleFunc("/api/admin/config/logo", middleware.RequireAdminAuth(admin.SetLogo))
|
|
||||||
|
|
||||||
// Server tags
|
|
||||||
http.HandleFunc("/api/admin/config/tags", middleware.RequireAdminAuth(admin.SetTags))
|
|
||||||
|
|
||||||
// ffmpeg
|
|
||||||
http.HandleFunc("/api/admin/config/ffmpegpath", middleware.RequireAdminAuth(admin.SetFfmpegPath))
|
|
||||||
|
|
||||||
// Server http port
|
|
||||||
http.HandleFunc("/api/admin/config/webserverport", middleware.RequireAdminAuth(admin.SetWebServerPort))
|
|
||||||
|
|
||||||
// Server http listen address
|
|
||||||
http.HandleFunc("/api/admin/config/webserverip", middleware.RequireAdminAuth(admin.SetWebServerIP))
|
|
||||||
|
|
||||||
// Server rtmp port
|
|
||||||
http.HandleFunc("/api/admin/config/rtmpserverport", middleware.RequireAdminAuth(admin.SetRTMPServerPort))
|
|
||||||
|
|
||||||
// Websocket host override
|
|
||||||
http.HandleFunc("/api/admin/config/sockethostoverride", middleware.RequireAdminAuth(admin.SetSocketHostOverride))
|
|
||||||
|
|
||||||
// Custom video serving endpoint
|
|
||||||
http.HandleFunc("/api/admin/config/videoservingendpoint", middleware.RequireAdminAuth(admin.SetVideoServingEndpoint))
|
|
||||||
|
|
||||||
// Is server marked as NSFW
|
|
||||||
http.HandleFunc("/api/admin/config/nsfw", middleware.RequireAdminAuth(admin.SetNSFW))
|
|
||||||
|
|
||||||
// directory enabled
|
|
||||||
http.HandleFunc("/api/admin/config/directoryenabled", middleware.RequireAdminAuth(admin.SetDirectoryEnabled))
|
|
||||||
|
|
||||||
// social handles
|
|
||||||
http.HandleFunc("/api/admin/config/socialhandles", middleware.RequireAdminAuth(admin.SetSocialHandles))
|
|
||||||
|
|
||||||
// set the number of video segments and duration per segment in a playlist
|
|
||||||
http.HandleFunc("/api/admin/config/video/streamlatencylevel", middleware.RequireAdminAuth(admin.SetStreamLatencyLevel))
|
|
||||||
|
|
||||||
// set an array of video output configurations
|
|
||||||
http.HandleFunc("/api/admin/config/video/streamoutputvariants", middleware.RequireAdminAuth(admin.SetStreamOutputVariants))
|
|
||||||
|
|
||||||
// set s3 configuration
|
|
||||||
http.HandleFunc("/api/admin/config/s3", middleware.RequireAdminAuth(admin.SetS3Configuration))
|
|
||||||
|
|
||||||
// set server url
|
|
||||||
http.HandleFunc("/api/admin/config/serverurl", middleware.RequireAdminAuth(admin.SetServerURL))
|
|
||||||
|
|
||||||
// reset the YP registration
|
|
||||||
http.HandleFunc("/api/admin/yp/reset", middleware.RequireAdminAuth(admin.ResetYPRegistration))
|
|
||||||
|
|
||||||
// set external action links
|
|
||||||
http.HandleFunc("/api/admin/config/externalactions", middleware.RequireAdminAuth(admin.SetExternalActions))
|
|
||||||
|
|
||||||
// set custom style css
|
|
||||||
http.HandleFunc("/api/admin/config/customstyles", middleware.RequireAdminAuth(admin.SetCustomStyles))
|
|
||||||
|
|
||||||
// set custom style javascript
|
|
||||||
http.HandleFunc("/api/admin/config/customjavascript", middleware.RequireAdminAuth(admin.SetCustomJavascript))
|
|
||||||
|
|
||||||
// Video playback metrics
|
|
||||||
http.HandleFunc("/api/admin/metrics/video", middleware.RequireAdminAuth(admin.GetVideoPlaybackMetrics))
|
|
||||||
|
|
||||||
// Is the viewer count hidden from viewers
|
|
||||||
http.HandleFunc("/api/admin/config/hideviewercount", middleware.RequireAdminAuth(admin.SetHideViewerCount))
|
|
||||||
|
|
||||||
// set disabling of search indexing
|
|
||||||
http.HandleFunc("/api/admin/config/disablesearchindexing", middleware.RequireAdminAuth(admin.SetDisableSearchIndexing))
|
|
||||||
|
|
||||||
// Inline chat moderation actions
|
|
||||||
|
|
||||||
// Update chat message visibility
|
|
||||||
http.HandleFunc("/api/chat/messagevisibility", middleware.RequireUserModerationScopeAccesstoken(admin.UpdateMessageVisibility))
|
|
||||||
|
|
||||||
// Enable/disable a user
|
|
||||||
http.HandleFunc("/api/chat/users/setenabled", middleware.RequireUserModerationScopeAccesstoken(admin.UpdateUserEnabled))
|
|
||||||
|
|
||||||
// Get a user's details
|
|
||||||
http.HandleFunc("/api/moderation/chat/user/", middleware.RequireUserModerationScopeAccesstoken(moderation.GetUserDetails))
|
|
||||||
|
|
||||||
// Configure Federation features
|
|
||||||
|
|
||||||
// enable/disable federation features
|
|
||||||
http.HandleFunc("/api/admin/config/federation/enable", middleware.RequireAdminAuth(admin.SetFederationEnabled))
|
|
||||||
|
|
||||||
// set if federation activities are private
|
|
||||||
http.HandleFunc("/api/admin/config/federation/private", middleware.RequireAdminAuth(admin.SetFederationActivityPrivate))
|
|
||||||
|
|
||||||
// set if fediverse engagement appears in chat
|
|
||||||
http.HandleFunc("/api/admin/config/federation/showengagement", middleware.RequireAdminAuth(admin.SetFederationShowEngagement))
|
|
||||||
|
|
||||||
// set local federated username
|
|
||||||
http.HandleFunc("/api/admin/config/federation/username", middleware.RequireAdminAuth(admin.SetFederationUsername))
|
|
||||||
|
|
||||||
// set federated go live message
|
|
||||||
http.HandleFunc("/api/admin/config/federation/livemessage", middleware.RequireAdminAuth(admin.SetFederationGoLiveMessage))
|
|
||||||
|
|
||||||
// Federation blocked domains
|
|
||||||
http.HandleFunc("/api/admin/config/federation/blockdomains", middleware.RequireAdminAuth(admin.SetFederationBlockDomains))
|
|
||||||
|
|
||||||
// send a public message to the Fediverse from the server's user
|
|
||||||
http.HandleFunc("/api/admin/federation/send", middleware.RequireAdminAuth(admin.SendFederatedMessage))
|
|
||||||
|
|
||||||
// Return federated activities
|
|
||||||
http.HandleFunc("/api/admin/federation/actions", middleware.RequireAdminAuth(middleware.HandlePagination(admin.GetFederatedActions)))
|
|
||||||
|
|
||||||
// Prometheus metrics
|
|
||||||
http.Handle("/api/admin/prometheus", middleware.RequireAdminAuth(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
promhttp.Handler().ServeHTTP(rw, r)
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Configure outbound notification channels.
|
|
||||||
http.HandleFunc("/api/admin/config/notifications/discord", middleware.RequireAdminAuth(admin.SetDiscordNotificationConfiguration))
|
|
||||||
http.HandleFunc("/api/admin/config/notifications/browser", middleware.RequireAdminAuth(admin.SetBrowserNotificationConfiguration))
|
|
||||||
|
|
||||||
// Auth
|
|
||||||
|
|
||||||
// Start auth flow
|
|
||||||
http.HandleFunc("/api/auth/indieauth", middleware.RequireUserAccessToken(indieauth.StartAuthFlow))
|
|
||||||
http.HandleFunc("/api/auth/indieauth/callback", indieauth.HandleRedirect)
|
|
||||||
http.HandleFunc("/api/auth/provider/indieauth", indieauth.HandleAuthEndpoint)
|
|
||||||
|
|
||||||
http.HandleFunc("/api/auth/fediverse", middleware.RequireUserAccessToken(fediverseauth.RegisterFediverseOTPRequest))
|
|
||||||
http.HandleFunc("/api/auth/fediverse/verify", fediverseauth.VerifyFediverseOTPRequest)
|
|
||||||
|
|
||||||
// ActivityPub has its own router
|
|
||||||
activitypub.Start(data.GetDatastore())
|
|
||||||
|
|
||||||
// websocket
|
|
||||||
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
chat.HandleClientConnection(w, r)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Optional public static files
|
|
||||||
http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir(config.PublicFilesPath))))
|
|
||||||
|
|
||||||
port := config.WebServerPort
|
|
||||||
ip := config.WebServerIP
|
|
||||||
|
|
||||||
h2s := &http2.Server{}
|
|
||||||
|
|
||||||
// Create a custom mux handler to intercept the /debug/vars endpoint.
|
|
||||||
// This is a hack because Prometheus enables this endpoint by default
|
|
||||||
// due to its use of expvar and we do not want this exposed.
|
|
||||||
defaultMux := h2c.NewHandler(http.DefaultServeMux, h2s)
|
|
||||||
m := http.NewServeMux()
|
|
||||||
|
|
||||||
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path == "/debug/vars" {
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
} else if r.URL.Path == "/embed/chat/" || r.URL.Path == "/embed/chat" {
|
|
||||||
// Redirect /embed/chat
|
|
||||||
http.Redirect(w, r, "/embed/chat/readonly", http.StatusTemporaryRedirect)
|
|
||||||
} else {
|
|
||||||
defaultMux.ServeHTTP(w, r)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
compress, _ := httpcompression.DefaultAdapter() // Use the default configuration
|
|
||||||
server := &http.Server{
|
|
||||||
Addr: fmt.Sprintf("%s:%d", ip, port),
|
|
||||||
ReadHeaderTimeout: 4 * time.Second,
|
|
||||||
Handler: compress(m),
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip != "0.0.0.0" {
|
|
||||||
log.Infof("Web server is listening at %s:%d.", ip, port)
|
|
||||||
} else {
|
|
||||||
log.Infof("Web server is listening on port %d.", port)
|
|
||||||
}
|
|
||||||
log.Infoln("Configure this server by visiting /admin.")
|
|
||||||
|
|
||||||
return server.ListenAndServe()
|
|
||||||
}
|
|
|
@ -32,7 +32,7 @@ test('public directory is writable', async (done) => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('public static file is accessible', async (done) => {
|
test('public static file is accessible: ' + filename, async (done) => {
|
||||||
request
|
request
|
||||||
.get('/public/' + filename)
|
.get('/public/' + filename)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
1
webserver/handlers/adminApi.go
Normal file
1
webserver/handlers/adminApi.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package handlers
|
1
webserver/handlers/directory.go
Normal file
1
webserver/handlers/directory.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package handlers
|
1
webserver/handlers/externalApi.go
Normal file
1
webserver/handlers/externalApi.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package handlers
|
8
webserver/handlers/handlers.go
Normal file
8
webserver/handlers/handlers.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
type Handlers struct{}
|
||||||
|
|
||||||
|
// New creates a new instances of web server handlers.
|
||||||
|
func New() *Handlers {
|
||||||
|
return &Handlers{}
|
||||||
|
}
|
1
webserver/handlers/hls.go
Normal file
1
webserver/handlers/hls.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package handlers
|
1
webserver/handlers/internalApi.go
Normal file
1
webserver/handlers/internalApi.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package handlers
|
1
webserver/handlers/static.go
Normal file
1
webserver/handlers/static.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package handlers
|
7
webserver/handlers/testing.go
Normal file
7
webserver/handlers/testing.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func (s *Handlers) HandleTesting(w http.ResponseWriter, r *http.Request) {
|
||||||
|
_, _ = w.Write([]byte("testing"))
|
||||||
|
}
|
1
webserver/handlers/webAssets.go
Normal file
1
webserver/handlers/webAssets.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package handlers
|
420
webserver/router.go
Normal file
420
webserver/router.go
Normal file
|
@ -0,0 +1,420 @@
|
||||||
|
package webserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/owncast/owncast/activitypub"
|
||||||
|
"github.com/owncast/owncast/config"
|
||||||
|
"github.com/owncast/owncast/controllers"
|
||||||
|
"github.com/owncast/owncast/controllers/admin"
|
||||||
|
fediverseauth "github.com/owncast/owncast/controllers/auth/fediverse"
|
||||||
|
"github.com/owncast/owncast/controllers/auth/indieauth"
|
||||||
|
"github.com/owncast/owncast/controllers/moderation"
|
||||||
|
"github.com/owncast/owncast/core/chat"
|
||||||
|
"github.com/owncast/owncast/core/data"
|
||||||
|
"github.com/owncast/owncast/core/user"
|
||||||
|
"github.com/owncast/owncast/utils"
|
||||||
|
"github.com/owncast/owncast/webserver/middleware"
|
||||||
|
"github.com/owncast/owncast/yp"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *webServer) setupRoutes() {
|
||||||
|
s.router.HandleFunc("/test", s.handlers.HandleTesting)
|
||||||
|
|
||||||
|
s.setupWebAssetRoutes()
|
||||||
|
s.setupInternalAPIRoutes()
|
||||||
|
s.setupAdminAPIRoutes()
|
||||||
|
s.setupExternalThirdPartyAPIRoutes()
|
||||||
|
s.setupModerationAPIRoutes()
|
||||||
|
|
||||||
|
s.router.HandleFunc("/hls/", controllers.HandleHLSRequest)
|
||||||
|
|
||||||
|
// websocket
|
||||||
|
s.router.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
chat.HandleClientConnection(w, r)
|
||||||
|
})
|
||||||
|
|
||||||
|
s.router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// This is a hack because Prometheus enables this endpoint by default
|
||||||
|
// due to its use of expvar and we do not want this exposed.
|
||||||
|
if r.URL.Path == "/debug/vars" {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
} else if r.URL.Path == "/embed/chat/" || r.URL.Path == "/embed/chat" {
|
||||||
|
// Redirect /embed/chat
|
||||||
|
http.Redirect(w, r, "/embed/chat/readonly", http.StatusTemporaryRedirect)
|
||||||
|
} else {
|
||||||
|
controllers.IndexHandler(w, r)
|
||||||
|
// s.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// ActivityPub has its own router
|
||||||
|
activitypub.Start(data.GetDatastore(), s.router)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *webServer) setupWebAssetRoutes() {
|
||||||
|
// The admin web app.
|
||||||
|
s.router.HandleFunc("/admin/", middleware.RequireAdminAuth(controllers.IndexHandler))
|
||||||
|
|
||||||
|
// Images
|
||||||
|
s.router.HandleFunc("/thumbnail.jpg", controllers.GetThumbnail)
|
||||||
|
s.router.HandleFunc("/preview.gif", controllers.GetPreview)
|
||||||
|
s.router.HandleFunc("/logo", controllers.GetLogo)
|
||||||
|
|
||||||
|
// Custom Javascript
|
||||||
|
s.router.HandleFunc("/customjavascript", controllers.ServeCustomJavascript)
|
||||||
|
|
||||||
|
// Return a single emoji image.
|
||||||
|
s.router.HandleFunc(config.EmojiDir, controllers.GetCustomEmojiImage)
|
||||||
|
|
||||||
|
// return the logo
|
||||||
|
|
||||||
|
// return a logo that's compatible with external social networks
|
||||||
|
s.router.HandleFunc("/logo/external", controllers.GetCompatibleLogo)
|
||||||
|
|
||||||
|
// robots.txt
|
||||||
|
s.router.HandleFunc("/robots.txt", controllers.GetRobotsDotTxt)
|
||||||
|
|
||||||
|
// Optional public static files
|
||||||
|
s.router.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir(config.PublicFilesPath))))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *webServer) setupInternalAPIRoutes() {
|
||||||
|
// Internal APIs
|
||||||
|
|
||||||
|
// status of the system
|
||||||
|
s.router.HandleFunc("/api/status", controllers.GetStatus)
|
||||||
|
|
||||||
|
// custom emoji supported in the chat
|
||||||
|
s.router.HandleFunc("/api/emoji", controllers.GetCustomEmojiList)
|
||||||
|
|
||||||
|
// chat history api
|
||||||
|
s.router.HandleFunc("/api/chat", middleware.RequireUserAccessToken(controllers.GetChatMessages))
|
||||||
|
|
||||||
|
// web config api
|
||||||
|
s.router.HandleFunc("/api/config", controllers.GetWebConfig)
|
||||||
|
|
||||||
|
// return the YP protocol data
|
||||||
|
s.router.HandleFunc("/api/yp", yp.GetYPResponse)
|
||||||
|
|
||||||
|
// list of all social platforms
|
||||||
|
s.router.HandleFunc("/api/socialplatforms", controllers.GetAllSocialPlatforms)
|
||||||
|
|
||||||
|
// return the list of video variants available
|
||||||
|
s.router.HandleFunc("/api/video/variants", controllers.GetVideoStreamOutputVariants)
|
||||||
|
|
||||||
|
// tell the backend you're an active viewer
|
||||||
|
s.router.HandleFunc("/api/ping", controllers.Ping)
|
||||||
|
|
||||||
|
// register a new chat user
|
||||||
|
s.router.HandleFunc("/api/chat/register", controllers.RegisterAnonymousChatUser)
|
||||||
|
|
||||||
|
// return remote follow details
|
||||||
|
s.router.HandleFunc("/api/remotefollow", controllers.RemoteFollow)
|
||||||
|
|
||||||
|
// return followers
|
||||||
|
s.router.HandleFunc("/api/followers", middleware.HandlePagination(controllers.GetFollowers))
|
||||||
|
|
||||||
|
// save client video playback metrics
|
||||||
|
s.router.HandleFunc("/api/metrics/playback", controllers.ReportPlaybackMetrics)
|
||||||
|
|
||||||
|
// Register for notifications
|
||||||
|
s.router.HandleFunc("/api/notifications/register", middleware.RequireUserAccessToken(controllers.RegisterForLiveNotifications))
|
||||||
|
|
||||||
|
// Start auth flow
|
||||||
|
http.HandleFunc("/api/auth/indieauth", middleware.RequireUserAccessToken(indieauth.StartAuthFlow))
|
||||||
|
http.HandleFunc("/api/auth/indieauth/callback", indieauth.HandleRedirect)
|
||||||
|
http.HandleFunc("/api/auth/provider/indieauth", indieauth.HandleAuthEndpoint)
|
||||||
|
|
||||||
|
http.HandleFunc("/api/auth/fediverse", middleware.RequireUserAccessToken(fediverseauth.RegisterFediverseOTPRequest))
|
||||||
|
http.HandleFunc("/api/auth/fediverse/verify", fediverseauth.VerifyFediverseOTPRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *webServer) setupAdminAPIRoutes() {
|
||||||
|
// Current inbound broadcaster
|
||||||
|
s.router.HandleFunc("/api/admin/status", middleware.RequireAdminAuth(admin.Status))
|
||||||
|
|
||||||
|
// Disconnect inbound stream
|
||||||
|
s.router.HandleFunc("/api/admin/disconnect", middleware.RequireAdminAuth(admin.DisconnectInboundConnection))
|
||||||
|
|
||||||
|
// Server config
|
||||||
|
s.router.HandleFunc("/api/admin/serverconfig", middleware.RequireAdminAuth(admin.GetServerConfig))
|
||||||
|
|
||||||
|
// Get viewer count over time
|
||||||
|
s.router.HandleFunc("/api/admin/viewersOverTime", middleware.RequireAdminAuth(admin.GetViewersOverTime))
|
||||||
|
|
||||||
|
// Get active viewers
|
||||||
|
s.router.HandleFunc("/api/admin/viewers", middleware.RequireAdminAuth(admin.GetActiveViewers))
|
||||||
|
|
||||||
|
// Get hardware stats
|
||||||
|
s.router.HandleFunc("/api/admin/hardwarestats", middleware.RequireAdminAuth(admin.GetHardwareStats))
|
||||||
|
|
||||||
|
// Get a a detailed list of currently connected chat clients
|
||||||
|
s.router.HandleFunc("/api/admin/chat/clients", middleware.RequireAdminAuth(admin.GetConnectedChatClients))
|
||||||
|
|
||||||
|
// Get all logs
|
||||||
|
s.router.HandleFunc("/api/admin/logs", middleware.RequireAdminAuth(admin.GetLogs))
|
||||||
|
|
||||||
|
// Get warning/error logs
|
||||||
|
s.router.HandleFunc("/api/admin/logs/warnings", middleware.RequireAdminAuth(admin.GetWarnings))
|
||||||
|
|
||||||
|
// Get all chat messages for the admin, unfiltered.
|
||||||
|
s.router.HandleFunc("/api/admin/chat/messages", middleware.RequireAdminAuth(admin.GetChatMessages))
|
||||||
|
|
||||||
|
// Update chat message visibility
|
||||||
|
s.router.HandleFunc("/api/admin/chat/messagevisibility", middleware.RequireAdminAuth(admin.UpdateMessageVisibility))
|
||||||
|
|
||||||
|
// Enable/disable a user
|
||||||
|
s.router.HandleFunc("/api/admin/chat/users/setenabled", middleware.RequireAdminAuth(admin.UpdateUserEnabled))
|
||||||
|
|
||||||
|
// Ban/unban an IP address
|
||||||
|
s.router.HandleFunc("/api/admin/chat/users/ipbans/create", middleware.RequireAdminAuth(admin.BanIPAddress))
|
||||||
|
|
||||||
|
// Remove an IP address ban
|
||||||
|
s.router.HandleFunc("/api/admin/chat/users/ipbans/remove", middleware.RequireAdminAuth(admin.UnBanIPAddress))
|
||||||
|
|
||||||
|
// Return all the banned IP addresses
|
||||||
|
s.router.HandleFunc("/api/admin/chat/users/ipbans", middleware.RequireAdminAuth(admin.GetIPAddressBans))
|
||||||
|
|
||||||
|
// Get a list of disabled users
|
||||||
|
s.router.HandleFunc("/api/admin/chat/users/disabled", middleware.RequireAdminAuth(admin.GetDisabledUsers))
|
||||||
|
|
||||||
|
// Set moderator status for a user
|
||||||
|
s.router.HandleFunc("/api/admin/chat/users/setmoderator", middleware.RequireAdminAuth(admin.UpdateUserModerator))
|
||||||
|
|
||||||
|
// Get a list of moderator users
|
||||||
|
s.router.HandleFunc("/api/admin/chat/users/moderators", middleware.RequireAdminAuth(admin.GetModerators))
|
||||||
|
|
||||||
|
// return followers
|
||||||
|
s.router.HandleFunc("/api/admin/followers", middleware.RequireAdminAuth(middleware.HandlePagination(controllers.GetFollowers)))
|
||||||
|
|
||||||
|
// Get a list of pending follow requests
|
||||||
|
s.router.HandleFunc("/api/admin/followers/pending", middleware.RequireAdminAuth(admin.GetPendingFollowRequests))
|
||||||
|
|
||||||
|
// Get a list of rejected or blocked follows
|
||||||
|
s.router.HandleFunc("/api/admin/followers/blocked", middleware.RequireAdminAuth(admin.GetBlockedAndRejectedFollowers))
|
||||||
|
|
||||||
|
// Set the following state of a follower or follow request.
|
||||||
|
s.router.HandleFunc("/api/admin/followers/approve", middleware.RequireAdminAuth(admin.ApproveFollower))
|
||||||
|
|
||||||
|
// Upload custom emoji
|
||||||
|
s.router.HandleFunc("/api/admin/emoji/upload", middleware.RequireAdminAuth(admin.UploadCustomEmoji))
|
||||||
|
|
||||||
|
// Delete custom emoji
|
||||||
|
s.router.HandleFunc("/api/admin/emoji/delete", middleware.RequireAdminAuth(admin.DeleteCustomEmoji))
|
||||||
|
|
||||||
|
// Update config values
|
||||||
|
|
||||||
|
// Change the current streaming key in memory
|
||||||
|
s.router.HandleFunc("/api/admin/config/adminpass", middleware.RequireAdminAuth(admin.SetAdminPassword))
|
||||||
|
|
||||||
|
// Set an array of valid stream keys
|
||||||
|
s.router.HandleFunc("/api/admin/config/streamkeys", middleware.RequireAdminAuth(admin.SetStreamKeys))
|
||||||
|
|
||||||
|
// Change the extra page content in memory
|
||||||
|
s.router.HandleFunc("/api/admin/config/pagecontent", middleware.RequireAdminAuth(admin.SetExtraPageContent))
|
||||||
|
|
||||||
|
// Stream title
|
||||||
|
s.router.HandleFunc("/api/admin/config/streamtitle", middleware.RequireAdminAuth(admin.SetStreamTitle))
|
||||||
|
|
||||||
|
// Server name
|
||||||
|
s.router.HandleFunc("/api/admin/config/name", middleware.RequireAdminAuth(admin.SetServerName))
|
||||||
|
|
||||||
|
// Server summary
|
||||||
|
s.router.HandleFunc("/api/admin/config/serversummary", middleware.RequireAdminAuth(admin.SetServerSummary))
|
||||||
|
|
||||||
|
// Offline message
|
||||||
|
s.router.HandleFunc("/api/admin/config/offlinemessage", middleware.RequireAdminAuth(admin.SetCustomOfflineMessage))
|
||||||
|
|
||||||
|
// Server welcome message
|
||||||
|
s.router.HandleFunc("/api/admin/config/welcomemessage", middleware.RequireAdminAuth(admin.SetServerWelcomeMessage))
|
||||||
|
|
||||||
|
// Disable chat
|
||||||
|
s.router.HandleFunc("/api/admin/config/chat/disable", middleware.RequireAdminAuth(admin.SetChatDisabled))
|
||||||
|
|
||||||
|
// Disable chat user join messages
|
||||||
|
s.router.HandleFunc("/api/admin/config/chat/joinmessagesenabled", middleware.RequireAdminAuth(admin.SetChatJoinMessagesEnabled))
|
||||||
|
|
||||||
|
// Enable/disable chat established user mode
|
||||||
|
s.router.HandleFunc("/api/admin/config/chat/establishedusermode", middleware.RequireAdminAuth(admin.SetEnableEstablishedChatUserMode))
|
||||||
|
|
||||||
|
// Set chat usernames that are not allowed
|
||||||
|
s.router.HandleFunc("/api/admin/config/chat/forbiddenusernames", middleware.RequireAdminAuth(admin.SetForbiddenUsernameList))
|
||||||
|
|
||||||
|
// Set the suggested chat usernames that will be assigned automatically
|
||||||
|
s.router.HandleFunc("/api/admin/config/chat/suggestedusernames", middleware.RequireAdminAuth(admin.SetSuggestedUsernameList))
|
||||||
|
|
||||||
|
// Set video codec
|
||||||
|
s.router.HandleFunc("/api/admin/config/video/codec", middleware.RequireAdminAuth(admin.SetVideoCodec))
|
||||||
|
|
||||||
|
// Set style/color/css values
|
||||||
|
s.router.HandleFunc("/api/admin/config/appearance", middleware.RequireAdminAuth(admin.SetCustomColorVariableValues))
|
||||||
|
|
||||||
|
// Return all webhooks
|
||||||
|
s.router.HandleFunc("/api/admin/webhooks", middleware.RequireAdminAuth(admin.GetWebhooks))
|
||||||
|
|
||||||
|
// Delete a single webhook
|
||||||
|
s.router.HandleFunc("/api/admin/webhooks/delete", middleware.RequireAdminAuth(admin.DeleteWebhook))
|
||||||
|
|
||||||
|
// Create a single webhook
|
||||||
|
s.router.HandleFunc("/api/admin/webhooks/create", middleware.RequireAdminAuth(admin.CreateWebhook))
|
||||||
|
|
||||||
|
// Get all access tokens
|
||||||
|
s.router.HandleFunc("/api/admin/accesstokens", middleware.RequireAdminAuth(admin.GetExternalAPIUsers))
|
||||||
|
|
||||||
|
// Delete a single access token
|
||||||
|
s.router.HandleFunc("/api/admin/accesstokens/delete", middleware.RequireAdminAuth(admin.DeleteExternalAPIUser))
|
||||||
|
|
||||||
|
// Create a single access token
|
||||||
|
s.router.HandleFunc("/api/admin/accesstokens/create", middleware.RequireAdminAuth(admin.CreateExternalAPIUser))
|
||||||
|
|
||||||
|
// Return the auto-update features that are supported for this instance.
|
||||||
|
s.router.HandleFunc("/api/admin/update/options", middleware.RequireAdminAuth(admin.AutoUpdateOptions))
|
||||||
|
|
||||||
|
// Begin the auto update
|
||||||
|
s.router.HandleFunc("/api/admin/update/start", middleware.RequireAdminAuth(admin.AutoUpdateStart))
|
||||||
|
|
||||||
|
// Force quit the service to restart it
|
||||||
|
s.router.HandleFunc("/api/admin/update/forcequit", middleware.RequireAdminAuth(admin.AutoUpdateForceQuit))
|
||||||
|
|
||||||
|
// Logo path
|
||||||
|
s.router.HandleFunc("/api/admin/config/logo", middleware.RequireAdminAuth(admin.SetLogo))
|
||||||
|
|
||||||
|
// Server tags
|
||||||
|
s.router.HandleFunc("/api/admin/config/tags", middleware.RequireAdminAuth(admin.SetTags))
|
||||||
|
|
||||||
|
// ffmpeg
|
||||||
|
s.router.HandleFunc("/api/admin/config/ffmpegpath", middleware.RequireAdminAuth(admin.SetFfmpegPath))
|
||||||
|
|
||||||
|
// Server http port
|
||||||
|
s.router.HandleFunc("/api/admin/config/webserverport", middleware.RequireAdminAuth(admin.SetWebServerPort))
|
||||||
|
|
||||||
|
// Server http listen address
|
||||||
|
s.router.HandleFunc("/api/admin/config/webserverip", middleware.RequireAdminAuth(admin.SetWebServerIP))
|
||||||
|
|
||||||
|
// Server rtmp port
|
||||||
|
s.router.HandleFunc("/api/admin/config/rtmpserverport", middleware.RequireAdminAuth(admin.SetRTMPServerPort))
|
||||||
|
|
||||||
|
// Websocket host override
|
||||||
|
s.router.HandleFunc("/api/admin/config/sockethostoverride", middleware.RequireAdminAuth(admin.SetSocketHostOverride))
|
||||||
|
|
||||||
|
// Custom video serving endpoint
|
||||||
|
s.router.HandleFunc("/api/admin/config/videoservingendpoint", middleware.RequireAdminAuth(admin.SetVideoServingEndpoint))
|
||||||
|
|
||||||
|
// Is server marked as NSFW
|
||||||
|
s.router.HandleFunc("/api/admin/config/nsfw", middleware.RequireAdminAuth(admin.SetNSFW))
|
||||||
|
|
||||||
|
// directory enabled
|
||||||
|
s.router.HandleFunc("/api/admin/config/directoryenabled", middleware.RequireAdminAuth(admin.SetDirectoryEnabled))
|
||||||
|
|
||||||
|
// social handles
|
||||||
|
s.router.HandleFunc("/api/admin/config/socialhandles", middleware.RequireAdminAuth(admin.SetSocialHandles))
|
||||||
|
|
||||||
|
// set the number of video segments and duration per segment in a playlist
|
||||||
|
s.router.HandleFunc("/api/admin/config/video/streamlatencylevel", middleware.RequireAdminAuth(admin.SetStreamLatencyLevel))
|
||||||
|
|
||||||
|
// set an array of video output configurations
|
||||||
|
s.router.HandleFunc("/api/admin/config/video/streamoutputvariants", middleware.RequireAdminAuth(admin.SetStreamOutputVariants))
|
||||||
|
|
||||||
|
// set s3 configuration
|
||||||
|
s.router.HandleFunc("/api/admin/config/s3", middleware.RequireAdminAuth(admin.SetS3Configuration))
|
||||||
|
|
||||||
|
// set server url
|
||||||
|
s.router.HandleFunc("/api/admin/config/serverurl", middleware.RequireAdminAuth(admin.SetServerURL))
|
||||||
|
|
||||||
|
// reset the YP registration
|
||||||
|
s.router.HandleFunc("/api/admin/yp/reset", middleware.RequireAdminAuth(admin.ResetYPRegistration))
|
||||||
|
|
||||||
|
// set external action links
|
||||||
|
s.router.HandleFunc("/api/admin/config/externalactions", middleware.RequireAdminAuth(admin.SetExternalActions))
|
||||||
|
|
||||||
|
// set custom style css
|
||||||
|
s.router.HandleFunc("/api/admin/config/customstyles", middleware.RequireAdminAuth(admin.SetCustomStyles))
|
||||||
|
|
||||||
|
// set custom style javascript
|
||||||
|
s.router.HandleFunc("/api/admin/config/customjavascript", middleware.RequireAdminAuth(admin.SetCustomJavascript))
|
||||||
|
|
||||||
|
// Video playback metrics
|
||||||
|
s.router.HandleFunc("/api/admin/metrics/video", middleware.RequireAdminAuth(admin.GetVideoPlaybackMetrics))
|
||||||
|
|
||||||
|
// Is the viewer count hidden from viewers
|
||||||
|
s.router.HandleFunc("/api/admin/config/hideviewercount", middleware.RequireAdminAuth(admin.SetHideViewerCount))
|
||||||
|
|
||||||
|
// set disabling of search indexing
|
||||||
|
s.router.HandleFunc("/api/admin/config/disablesearchindexing", middleware.RequireAdminAuth(admin.SetDisableSearchIndexing))
|
||||||
|
|
||||||
|
// enable/disable federation features
|
||||||
|
s.router.HandleFunc("/api/admin/config/federation/enable", middleware.RequireAdminAuth(admin.SetFederationEnabled))
|
||||||
|
|
||||||
|
// set if federation activities are private
|
||||||
|
s.router.HandleFunc("/api/admin/config/federation/private", middleware.RequireAdminAuth(admin.SetFederationActivityPrivate))
|
||||||
|
|
||||||
|
// set if fediverse engagement appears in chat
|
||||||
|
s.router.HandleFunc("/api/admin/config/federation/showengagement", middleware.RequireAdminAuth(admin.SetFederationShowEngagement))
|
||||||
|
|
||||||
|
// set local federated username
|
||||||
|
s.router.HandleFunc("/api/admin/config/federation/username", middleware.RequireAdminAuth(admin.SetFederationUsername))
|
||||||
|
|
||||||
|
// set federated go live message
|
||||||
|
s.router.HandleFunc("/api/admin/config/federation/livemessage", middleware.RequireAdminAuth(admin.SetFederationGoLiveMessage))
|
||||||
|
|
||||||
|
// Federation blocked domains
|
||||||
|
s.router.HandleFunc("/api/admin/config/federation/blockdomains", middleware.RequireAdminAuth(admin.SetFederationBlockDomains))
|
||||||
|
|
||||||
|
// send a public message to the Fediverse from the server's user
|
||||||
|
s.router.HandleFunc("/api/admin/federation/send", middleware.RequireAdminAuth(admin.SendFederatedMessage))
|
||||||
|
|
||||||
|
// Return federated activities
|
||||||
|
s.router.HandleFunc("/api/admin/federation/actions", middleware.RequireAdminAuth(middleware.HandlePagination(admin.GetFederatedActions)))
|
||||||
|
|
||||||
|
// Prometheus metrics
|
||||||
|
s.router.Handle("/api/admin/prometheus", middleware.RequireAdminAuth(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
promhttp.Handler().ServeHTTP(rw, r)
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Configure outbound notification channels.
|
||||||
|
http.HandleFunc("/api/admin/config/notifications/discord", middleware.RequireAdminAuth(admin.SetDiscordNotificationConfiguration))
|
||||||
|
http.HandleFunc("/api/admin/config/notifications/browser", middleware.RequireAdminAuth(admin.SetBrowserNotificationConfiguration))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *webServer) setupExternalThirdPartyAPIRoutes() {
|
||||||
|
// Send a system message to chat
|
||||||
|
s.router.HandleFunc("/api/integrations/chat/system", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendSystemMessages, admin.SendSystemMessage))
|
||||||
|
|
||||||
|
// Send a system message to a single client
|
||||||
|
s.router.HandleFunc(utils.RestEndpoint("/api/integrations/chat/system/client/{clientId}", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendSystemMessages, admin.SendSystemMessageToConnectedClient)))
|
||||||
|
|
||||||
|
// Send a user message to chat *NO LONGER SUPPORTED
|
||||||
|
s.router.HandleFunc("/api/integrations/chat/user", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendChatMessages, admin.SendUserMessage))
|
||||||
|
|
||||||
|
// Send a message to chat as a specific 3rd party bot/integration based on its access token
|
||||||
|
s.router.HandleFunc("/api/integrations/chat/send", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendChatMessages, admin.SendIntegrationChatMessage))
|
||||||
|
|
||||||
|
// Send a user action to chat
|
||||||
|
s.router.HandleFunc("/api/integrations/chat/action", middleware.RequireExternalAPIAccessToken(user.ScopeCanSendSystemMessages, admin.SendChatAction))
|
||||||
|
|
||||||
|
// Hide chat message
|
||||||
|
s.router.HandleFunc("/api/integrations/chat/messagevisibility", middleware.RequireExternalAPIAccessToken(user.ScopeHasAdminAccess, admin.ExternalUpdateMessageVisibility))
|
||||||
|
|
||||||
|
// Stream title
|
||||||
|
s.router.HandleFunc("/api/integrations/streamtitle", middleware.RequireExternalAPIAccessToken(user.ScopeHasAdminAccess, admin.ExternalSetStreamTitle))
|
||||||
|
|
||||||
|
// Get chat history
|
||||||
|
s.router.HandleFunc("/api/integrations/chat", middleware.RequireExternalAPIAccessToken(user.ScopeHasAdminAccess, controllers.ExternalGetChatMessages))
|
||||||
|
|
||||||
|
// Connected clients
|
||||||
|
s.router.HandleFunc("/api/integrations/clients", middleware.RequireExternalAPIAccessToken(user.ScopeHasAdminAccess, admin.ExternalGetConnectedChatClients))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *webServer) setupModerationAPIRoutes() {
|
||||||
|
// Update chat message visibility
|
||||||
|
s.router.HandleFunc("/api/chat/messagevisibility", middleware.RequireUserModerationScopeAccesstoken(admin.UpdateMessageVisibility))
|
||||||
|
|
||||||
|
// Enable/disable a user
|
||||||
|
s.router.HandleFunc("/api/chat/users/setenabled", middleware.RequireUserModerationScopeAccesstoken(admin.UpdateUserEnabled))
|
||||||
|
|
||||||
|
// Get a user's details
|
||||||
|
s.router.HandleFunc("/api/moderation/chat/user/", middleware.RequireUserModerationScopeAccesstoken(moderation.GetUserDetails))
|
||||||
|
}
|
54
webserver/webserver.go
Normal file
54
webserver/webserver.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package webserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/CAFxX/httpcompression"
|
||||||
|
"github.com/owncast/owncast/webserver/handlers"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
|
"golang.org/x/net/http2/h2c"
|
||||||
|
)
|
||||||
|
|
||||||
|
type webServer struct {
|
||||||
|
router *http.ServeMux
|
||||||
|
handlers *handlers.Handlers
|
||||||
|
server *http.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *webServer {
|
||||||
|
s := &webServer{
|
||||||
|
router: http.NewServeMux(),
|
||||||
|
}
|
||||||
|
|
||||||
|
s.setupRoutes()
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *webServer) Start(listenIP string, listenPort int) error {
|
||||||
|
compress, _ := httpcompression.DefaultAdapter() // Use the default configuration
|
||||||
|
h2s := &http2.Server{}
|
||||||
|
http2Router := h2c.NewHandler(s.router, h2s)
|
||||||
|
|
||||||
|
s.server = &http.Server{
|
||||||
|
Addr: fmt.Sprintf("%s:%d", listenIP, listenPort),
|
||||||
|
ReadHeaderTimeout: 4 * time.Second,
|
||||||
|
Handler: compress(http2Router),
|
||||||
|
}
|
||||||
|
|
||||||
|
if listenIP != "0.0.0.0" {
|
||||||
|
log.Infof("Web server is listening at %s:%d.", listenIP, listenPort)
|
||||||
|
} else {
|
||||||
|
log.Infof("Web server is listening on port %d.", listenPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.server.ListenAndServe()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeHTTP is the entry point for all web requests.
|
||||||
|
func (s *webServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
s.router.ServeHTTP(w, r)
|
||||||
|
}
|
44
webserver/webserver_test.go
Normal file
44
webserver/webserver_test.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package webserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/owncast/owncast/core/data"
|
||||||
|
)
|
||||||
|
|
||||||
|
var srv *webServer
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
dbFile, err := os.CreateTemp(os.TempDir(), "owncast-test-db.db")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.SetupPersistence(dbFile.Name())
|
||||||
|
srv = New()
|
||||||
|
|
||||||
|
m.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPrometheusPath tests that the /debug/vars endpoint that
|
||||||
|
// Prometheus automatically enables is not exposed.
|
||||||
|
func TestPrometheusDebugPath(t *testing.T) {
|
||||||
|
r := httptest.NewRequest(http.MethodGet, "/debug/vars", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
srv.ServeHTTP(w, r)
|
||||||
|
if w.Result().StatusCode != http.StatusNotFound {
|
||||||
|
t.Errorf("Expected 404, got %d", w.Result().StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTestingEndpoint(t *testing.T) {
|
||||||
|
r := httptest.NewRequest(http.MethodGet, "/test", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
srv.ServeHTTP(w, r)
|
||||||
|
if w.Result().StatusCode != http.StatusOK {
|
||||||
|
t.Errorf("Expected 200, got %d", w.Result().StatusCode)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue