Bundle and serve admin (#317)

* WIP with admin bundling

* Current state of the admin is bundled

* Update admin bundler to work with binary bundling

* Log detail about the admin interface. Closes #312

* Move bundle script to the build dir

* Update to current version of admin

* Commit updated API documentation

Co-authored-by: Owncast <owncast@owncast.online>
This commit is contained in:
Gabe Kangas 2020-11-06 15:12:35 -08:00 committed by GitHub
parent 2517e9944e
commit 1dbd550134
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 117 additions and 17 deletions

1
.gitignore vendored
View file

@ -25,6 +25,7 @@ webroot/static/content.md
hls/
dist/
data/
admin/
transcoder.log
chat.db
.yp.key

40
build/admin/bundleAdmin.sh Executable file
View file

@ -0,0 +1,40 @@
#!/usr/bin/env bash
# shellcheck disable=SC2059
set -o errexit
set -o nounset
set -o pipefail
INSTALL_TEMP_DIRECTORY="$(mktemp -d)"
PROJECT_SOURCE_DIR=$(pwd)
cd $INSTALL_TEMP_DIRECTORY
shutdown () {
rm -rf "$PROJECT_SOURCE_DIR/admin"
rm -rf "$INSTALL_TEMP_DIRECTORY"
}
trap shutdown INT TERM ABRT EXIT
echo "Cloning owncast admin into $INSTALL_TEMP_DIRECTORY..."
git clone --depth 1 https://github.com/owncast/owncast-admin 2> /dev/null
cd owncast-admin
echo "Installing npm modules for the owncast admin..."
npm --silent install 2> /dev/null
echo "Building owncast admin..."
rm -rf .next
(node_modules/.bin/next build && node_modules/.bin/next export) | grep info
echo "Copying admin to project directory..."
ADMIN_BUILD_DIR=$(pwd)
cd $PROJECT_SOURCE_DIR
mkdir -p admin 2> /dev/null
cd admin
cp -R ${ADMIN_BUILD_DIR}/out/* .
echo "Bundling admin into owncast codebase..."
~/go/bin/pkger
shutdown
echo "Done."

View file

@ -0,0 +1,44 @@
package admin
import (
"io/ioutil"
"mime"
"net/http"
"path/filepath"
"github.com/markbates/pkger"
"github.com/owncast/owncast/router/middleware"
log "github.com/sirupsen/logrus"
)
// ServeAdmin will return admin web assets
func ServeAdmin(w http.ResponseWriter, r *http.Request) {
// Set a cache control max-age header
middleware.SetCachingHeaders(w, r)
path := r.URL.Path
if path == "/admin" || path == "/admin/" {
path = "/admin/index.html"
}
f, err := pkger.Open(path)
if err != nil {
log.Warnln(err, path)
errorHandler(w, r, http.StatusNotFound)
return
}
b, err := ioutil.ReadAll(f)
if err != nil {
log.Warnln(err)
return
}
mimeType := mime.TypeByExtension(filepath.Ext(path))
w.Header().Set("Content-Type", mimeType)
w.Write(b)
}
func errorHandler(w http.ResponseWriter, r *http.Request, status int) {
w.WriteHeader(status)
}

View file

@ -28,7 +28,6 @@ type MetadataPage struct {
//IndexHandler handles the default index route
func IndexHandler(w http.ResponseWriter, r *http.Request) {
middleware.EnableCors(&w)
isIndexRequest := r.URL.Path == "/" || filepath.Base(r.URL.Path) == "index.html" || filepath.Base(r.URL.Path) == ""
// For search engine bots and social scrapers return a special

View file

@ -65,6 +65,10 @@ func Start() error {
// start the rtmp server
go rtmp.Start(setStreamAsConnected, setBroadcaster)
port := config.Config.GetPublicWebServerPort()
log.Infof("Web server is listening on port %d, RTMP is accepting inbound streams on port 1935.", port)
log.Infoln("The web admin interface is available at /admin.")
return nil
}

View file

@ -53,7 +53,7 @@ func Start(setStreamAsConnected func(), setBroadcaster func(models.Broadcaster))
if err != nil {
log.Panicln(err)
}
log.Infof("RTMP server is listening for incoming stream on port: %d", port)
log.Tracef("RTMP server is listening for incoming stream on port: %d", port)
for {
nc, err := lis.Accept()

1
go.mod
View file

@ -8,6 +8,7 @@ require (
github.com/aws/aws-sdk-go v1.35.22
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/grafov/m3u8 v0.11.1
github.com/markbates/pkger v0.17.1
github.com/mattn/go-sqlite3 v1.14.4
github.com/microcosm-cc/bluemonday v1.0.4
github.com/mssola/user_agent v0.5.2

7
go.sum
View file

@ -13,6 +13,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/grafov/m3u8 v0.11.1 h1:igZ7EBIB2IAsPPazKwRKdbhxcoBKO3lO1UY57PZDeNA=
@ -21,9 +23,12 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI=
github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
@ -79,9 +84,11 @@ golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View file

@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"github.com/markbates/pkger"
"github.com/owncast/owncast/logging"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
@ -29,6 +30,8 @@ func main() {
configureLogging()
log.Infoln(getReleaseString())
// Enable bundling of admin assets
pkger.Include("/admin")
configFile := flag.String("configFile", "config.yaml", "Config File full path. Defaults to current folder")
dbFile := flag.String("database", "", "Path to the database file.")
@ -72,7 +75,6 @@ func main() {
log.Error("failed to start/run the router")
panic(err)
}
}
//getReleaseString gets the version string

12
pkged.go Normal file

File diff suppressed because one or more lines are too long

View file

@ -19,6 +19,9 @@ func Start() error {
// static files
http.HandleFunc("/", controllers.IndexHandler)
// admin static files
http.HandleFunc("/admin/", middleware.RequireAdminAuth(admin.ServeAdmin))
// status of the system
http.HandleFunc("/api/status", controllers.GetStatus)
@ -76,7 +79,7 @@ func Start() error {
port := config.Config.GetPublicWebServerPort()
log.Infof("Web server running on port: %d", port)
log.Tracef("Web server running on port: %d", port)
return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}

View file

@ -1,13 +0,0 @@
PROJECT_SOURCE_DIR=$(pwd)
mkdir $TMPDIR/admin 2> /dev/null
cd $TMPDIR/admin
git clone --depth 1 https://github.com/owncast/owncast-admin 2> /dev/null
cd owncast-admin
npm --silent install 2> /dev/null
(node_modules/.bin/next build && node_modules/.bin/next export) | grep info
ADMIN_BUILD_DIR=$(pwd)
cd $PROJECT_SOURCE_DIR
mkdir webroot/admin 2> /dev/null
cd webroot/admin
cp -R ${ADMIN_BUILD_DIR}/out/* .
rm -rf $TMPDIR/admin