diff --git a/Makefile b/Makefile index 9dfd4f89..b70b616b 100644 --- a/Makefile +++ b/Makefile @@ -18,10 +18,17 @@ test: check_go_env go test ./... -v # @(cd ./ui && npm test -- --watchAll=false) +.PHONY: testall +testall: check_go_env test + @(cd ./ui && npm test -- --watchAll=false) + .PHONY: build build: check_go_env go build -# @(cd ./ui && npm run build) + +.PHONY: build +buildall: check_go_env build + @(cd ./ui && npm run build) .PHONY: setup setup: Jamstash-master diff --git a/main.go b/main.go index 556372e1..f93c333c 100644 --- a/main.go +++ b/main.go @@ -7,7 +7,8 @@ import ( func main() { conf.Load() - a := CreateApp(conf.Sonic.MusicFolder) - a.MountRouter("/rest/", CreateSubsonicAPIRouter()) + a := CreateServer(conf.Sonic.MusicFolder) + a.MountRouter("/rest", CreateSubsonicAPIRouter()) + a.MountRouter("/app", CreateAppRouter("/app")) a.Run(":" + conf.Sonic.Port) } diff --git a/server/app/app.go b/server/app/app.go new file mode 100644 index 00000000..a745b1b2 --- /dev/null +++ b/server/app/app.go @@ -0,0 +1,33 @@ +package app + +import ( + "net/http" + + "github.com/cloudsonic/sonic-server/model" + "github.com/cloudsonic/sonic-server/server" + "github.com/go-chi/chi" +) + +type Router struct { + ds model.DataStore + mux http.Handler + path string +} + +func New(ds model.DataStore, path string) *Router { + r := &Router{ds: ds, path: path} + r.mux = r.routes() + return r +} + +func (app *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) { + app.mux.ServeHTTP(w, r) +} + +func (app *Router) routes() http.Handler { + r := chi.NewRouter() + server.FileServer(r, app.path, "/", http.Dir("ui/build")) + r.Get("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`{"response":"pong"}`)) }) + + return r +} diff --git a/server/fileserver.go b/server/fileserver.go new file mode 100644 index 00000000..deedb52a --- /dev/null +++ b/server/fileserver.go @@ -0,0 +1,47 @@ +package server + +import ( + "net/http" + "os" + "strings" + + "github.com/go-chi/chi" +) + +func FileServer(r chi.Router, fullPath, subPath string, root http.FileSystem) { + if strings.ContainsAny(fullPath, "{}*") { + panic("FileServer does not permit URL parameters.") + } + + fs := http.StripPrefix(fullPath, http.FileServer(justFilesFilesystem{root})) + + if subPath != "/" && subPath[len(subPath)-1] != '/' { + r.Get(subPath, http.RedirectHandler(fullPath+"/", 302).ServeHTTP) + subPath += "/" + } + subPath += "*" + + r.Get(subPath, func(w http.ResponseWriter, r *http.Request) { + fs.ServeHTTP(w, r) + }) +} + +type justFilesFilesystem struct { + fs http.FileSystem +} + +func (fs justFilesFilesystem) Open(name string) (http.File, error) { + f, err := fs.fs.Open(name) + if err != nil { + return nil, err + } + return neuteredReaddirFile{f}, nil +} + +type neuteredReaddirFile struct { + http.File +} + +func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) { + return nil, nil +} diff --git a/server/server.go b/server/server.go index b4668c36..cfd283c4 100644 --- a/server/server.go +++ b/server/server.go @@ -4,7 +4,6 @@ import ( "net/http" "os" "path/filepath" - "strings" "time" "github.com/cloudsonic/sonic-server/conf" @@ -34,7 +33,7 @@ func New(scanner *scanner.Scanner) *Server { } func (a *Server) MountRouter(path string, subRouter http.Handler) { - log.Info("Mounting API", "path", path) + log.Info("Mounting routes", "path", path) a.router.Group(func(r chi.Router) { r.Use(middleware.Logger) r.Mount(path, subRouter) @@ -58,11 +57,12 @@ func (a *Server) initRoutes() { r.Use(InjectLogger) r.Get("/", func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/Jamstash", 302) + http.Redirect(w, r, "/app", 302) }) + workDir, _ := os.Getwd() filesDir := filepath.Join(workDir, "Jamstash-master/dist") - FileServer(r, "/Jamstash", http.Dir(filesDir)) + FileServer(r, "/Jamstash", "/Jamstash", http.Dir(filesDir)) a.router = r } @@ -81,24 +81,6 @@ func (a *Server) initScanner() { }() } -func FileServer(r chi.Router, path string, root http.FileSystem) { - if strings.ContainsAny(path, "{}*") { - panic("FileServer does not permit URL parameters.") - } - - fs := http.StripPrefix(path, http.FileServer(root)) - - if path != "/" && path[len(path)-1] != '/' { - r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) - path += "/" - } - path += "*" - - r.Get(path, func(w http.ResponseWriter, r *http.Request) { - fs.ServeHTTP(w, r) - }) -} - func InjectLogger(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() diff --git a/ui/package.json b/ui/package.json index 6fc602e0..621cc64a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -19,7 +19,7 @@ "test": "react-scripts test", "eject": "react-scripts eject" }, - "homepage": "https://localhost/ui/", + "homepage": "https://localhost/app/", "proxy": "http://localhost:4633/", "eslintConfig": { "extends": "react-app" diff --git a/wire_gen.go b/wire_gen.go index 18711361..b2174e44 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -10,19 +10,26 @@ import ( "github.com/cloudsonic/sonic-server/persistence" "github.com/cloudsonic/sonic-server/scanner" "github.com/cloudsonic/sonic-server/server" + "github.com/cloudsonic/sonic-server/server/app" "github.com/cloudsonic/sonic-server/server/subsonic" "github.com/google/wire" ) // Injectors from wire_injectors.go: -func CreateApp(musicFolder string) *server.Server { +func CreateServer(musicFolder string) *server.Server { dataStore := persistence.New() scannerScanner := scanner.New(dataStore) serverServer := server.New(scannerScanner) return serverServer } +func CreateAppRouter(path string) *app.Router { + dataStore := persistence.New() + router := app.New(dataStore, path) + return router +} + func CreateSubsonicAPIRouter() *subsonic.Router { dataStore := persistence.New() browser := engine.NewBrowser(dataStore) @@ -39,4 +46,4 @@ func CreateSubsonicAPIRouter() *subsonic.Router { // wire_injectors.go: -var allProviders = wire.NewSet(engine.Set, scanner.New, subsonic.New, persistence.New) +var allProviders = wire.NewSet(engine.Set, scanner.New, subsonic.New, app.New, persistence.New) diff --git a/wire_injectors.go b/wire_injectors.go index f4d33393..595ae09d 100644 --- a/wire_injectors.go +++ b/wire_injectors.go @@ -7,6 +7,7 @@ import ( "github.com/cloudsonic/sonic-server/persistence" "github.com/cloudsonic/sonic-server/scanner" "github.com/cloudsonic/sonic-server/server" + "github.com/cloudsonic/sonic-server/server/app" "github.com/cloudsonic/sonic-server/server/subsonic" "github.com/google/wire" ) @@ -15,16 +16,21 @@ var allProviders = wire.NewSet( engine.Set, scanner.New, subsonic.New, + app.New, persistence.New, ) -func CreateApp(musicFolder string) *server.Server { +func CreateServer(musicFolder string) *server.Server { panic(wire.Build( server.New, allProviders, )) } +func CreateAppRouter(path string) *app.Router { + panic(wire.Build(allProviders)) +} + func CreateSubsonicAPIRouter() *subsonic.Router { panic(wire.Build(allProviders)) }