Merge pull request #503 from trheyi/main
[add] server rewrite support and fix api reload
This commit is contained in:
commit
293c487cd9
11 changed files with 255 additions and 169 deletions
52
service/fs/default.go
Normal file
52
service/fs/default.go
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/application"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dir http root path
|
||||||
|
type Dir string
|
||||||
|
|
||||||
|
// Open implements FileSystem using os.Open, opening files for reading rooted
|
||||||
|
// and relative to the directory d.
|
||||||
|
func (d Dir) Open(name string) (http.File, error) {
|
||||||
|
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
|
||||||
|
return nil, errors.New("http: invalid character in file path")
|
||||||
|
}
|
||||||
|
|
||||||
|
dir := string(d)
|
||||||
|
if dir == "" {
|
||||||
|
dir = "."
|
||||||
|
}
|
||||||
|
|
||||||
|
name = filepath.FromSlash(path.Clean("/" + name))
|
||||||
|
relName := filepath.Join(dir, name)
|
||||||
|
|
||||||
|
// Close dir views Disable directory listing
|
||||||
|
absName := filepath.Join(application.App.Root(), relName)
|
||||||
|
stat, err := os.Stat(absName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stat.IsDir() {
|
||||||
|
if _, err := os.Stat(filepath.Join(absName, "index.html")); os.IsNotExist(err) {
|
||||||
|
return nil, mapOpenError(fs.ErrNotExist, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := application.App.FS(string(d)).Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
120
service/fs/fs.go
120
service/fs/fs.go
|
|
@ -1,120 +0,0 @@
|
||||||
package fs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io/fs"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/yaoapp/gou/application"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Dir http root path
|
|
||||||
type Dir string
|
|
||||||
|
|
||||||
// DirPWA is the PWA path
|
|
||||||
type DirPWA string
|
|
||||||
|
|
||||||
// Open implements FileSystem using os.Open, opening files for reading rooted
|
|
||||||
// and relative to the directory d.
|
|
||||||
func (d Dir) Open(name string) (http.File, error) {
|
|
||||||
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
|
|
||||||
return nil, errors.New("http: invalid character in file path")
|
|
||||||
}
|
|
||||||
|
|
||||||
dir := string(d)
|
|
||||||
if dir == "" {
|
|
||||||
dir = "."
|
|
||||||
}
|
|
||||||
|
|
||||||
name = filepath.FromSlash(path.Clean("/" + name))
|
|
||||||
relName := filepath.Join(dir, name)
|
|
||||||
|
|
||||||
// Close dir views Disable directory listing
|
|
||||||
absName := filepath.Join(application.App.Root(), relName)
|
|
||||||
stat, err := os.Stat(absName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
|
||||||
}
|
|
||||||
|
|
||||||
if stat.IsDir() {
|
|
||||||
if _, err := os.Stat(filepath.Join(absName, "index.html")); os.IsNotExist(err) {
|
|
||||||
return nil, mapOpenError(fs.ErrNotExist, relName, filepath.Separator, os.Stat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := application.App.FS(string(d)).Open(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
|
||||||
}
|
|
||||||
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open implements FileSystem using os.Open, opening files for reading rooted
|
|
||||||
// and relative to the directory d.
|
|
||||||
func (d DirPWA) Open(name string) (http.File, error) {
|
|
||||||
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
|
|
||||||
return nil, errors.New("http: invalid character in file path")
|
|
||||||
}
|
|
||||||
|
|
||||||
dir := string(d)
|
|
||||||
if dir == "" {
|
|
||||||
dir = "."
|
|
||||||
}
|
|
||||||
|
|
||||||
name = filepath.FromSlash(path.Clean("/" + name))
|
|
||||||
relName := filepath.Join(dir, name)
|
|
||||||
|
|
||||||
if filepath.Ext(relName) == "" && relName != dir {
|
|
||||||
relName = filepath.Join(dir, "index.html")
|
|
||||||
name = filepath.Join(string(os.PathSeparator), "index.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close dir views Disable directory listing
|
|
||||||
absName := filepath.Join(application.App.Root(), relName)
|
|
||||||
stat, err := os.Stat(absName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
|
||||||
}
|
|
||||||
|
|
||||||
if stat.IsDir() {
|
|
||||||
if _, err := os.Stat(filepath.Join(absName, "index.html")); os.IsNotExist(err) {
|
|
||||||
return nil, mapOpenError(fs.ErrNotExist, relName, filepath.Separator, os.Stat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := application.App.FS(string(d)).Open(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
|
||||||
}
|
|
||||||
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// mapOpenError maps the provided non-nil error from opening name
|
|
||||||
// to a possibly better non-nil error. In particular, it turns OS-specific errors
|
|
||||||
// about opening files in non-directories into fs.ErrNotExist. See Issues 18984 and 49552.
|
|
||||||
func mapOpenError(originalErr error, name string, sep rune, stat func(string) (fs.FileInfo, error)) error {
|
|
||||||
if errors.Is(originalErr, fs.ErrNotExist) || errors.Is(originalErr, fs.ErrPermission) {
|
|
||||||
return originalErr
|
|
||||||
}
|
|
||||||
|
|
||||||
parts := strings.Split(name, string(sep))
|
|
||||||
for i := range parts {
|
|
||||||
if parts[i] == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fi, err := stat(strings.Join(parts[:i+1], string(sep)))
|
|
||||||
if err != nil {
|
|
||||||
return originalErr
|
|
||||||
}
|
|
||||||
if !fi.IsDir() {
|
|
||||||
return fs.ErrNotExist
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return originalErr
|
|
||||||
}
|
|
||||||
57
service/fs/spa.go
Normal file
57
service/fs/spa.go
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/application"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DirSPA is the PWA path
|
||||||
|
type DirSPA string
|
||||||
|
|
||||||
|
// Open implements FileSystem using os.Open, opening files for reading rooted
|
||||||
|
// and relative to the directory d.
|
||||||
|
func (d DirSPA) Open(name string) (http.File, error) {
|
||||||
|
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
|
||||||
|
return nil, errors.New("http: invalid character in file path")
|
||||||
|
}
|
||||||
|
|
||||||
|
dir := string(d)
|
||||||
|
if dir == "" {
|
||||||
|
dir = "."
|
||||||
|
}
|
||||||
|
|
||||||
|
name = filepath.FromSlash(path.Clean("/" + name))
|
||||||
|
relName := filepath.Join(dir, name)
|
||||||
|
|
||||||
|
if filepath.Ext(relName) == "" && relName != dir {
|
||||||
|
relName = filepath.Join(dir, "index.html")
|
||||||
|
name = filepath.Join(string(os.PathSeparator), "index.html")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close dir views Disable directory listing
|
||||||
|
absName := filepath.Join(application.App.Root(), relName)
|
||||||
|
stat, err := os.Stat(absName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stat.IsDir() {
|
||||||
|
if _, err := os.Stat(filepath.Join(absName, "index.html")); os.IsNotExist(err) {
|
||||||
|
return nil, mapOpenError(fs.ErrNotExist, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := application.App.FS(string(d)).Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
57
service/fs/sui.go
Normal file
57
service/fs/sui.go
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/application"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DirSUI is the PWA path
|
||||||
|
type DirSUI string
|
||||||
|
|
||||||
|
// Open implements FileSystem using os.Open, opening files for reading rooted
|
||||||
|
// and relative to the directory d.
|
||||||
|
func (d DirSUI) Open(name string) (http.File, error) {
|
||||||
|
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
|
||||||
|
return nil, errors.New("http: invalid character in file path")
|
||||||
|
}
|
||||||
|
|
||||||
|
dir := string(d)
|
||||||
|
if dir == "" {
|
||||||
|
dir = "."
|
||||||
|
}
|
||||||
|
|
||||||
|
name = filepath.FromSlash(path.Clean("/" + name))
|
||||||
|
relName := filepath.Join(dir, name)
|
||||||
|
|
||||||
|
if filepath.Ext(relName) == "" && relName != dir {
|
||||||
|
relName = filepath.Join(dir, "index.html")
|
||||||
|
name = filepath.Join(string(os.PathSeparator), "index.html")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close dir views Disable directory listing
|
||||||
|
absName := filepath.Join(application.App.Root(), relName)
|
||||||
|
stat, err := os.Stat(absName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stat.IsDir() {
|
||||||
|
if _, err := os.Stat(filepath.Join(absName, "index.html")); os.IsNotExist(err) {
|
||||||
|
return nil, mapOpenError(fs.ErrNotExist, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := application.App.FS(string(d)).Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, mapOpenError(err, relName, filepath.Separator, os.Stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
31
service/fs/utils.go
Normal file
31
service/fs/utils.go
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// mapOpenError maps the provided non-nil error from opening name
|
||||||
|
// to a possibly better non-nil error. In particular, it turns OS-specific errors
|
||||||
|
// about opening files in non-directories into fs.ErrNotExist. See Issues 18984 and 49552.
|
||||||
|
func mapOpenError(originalErr error, name string, sep rune, stat func(string) (fs.FileInfo, error)) error {
|
||||||
|
if errors.Is(originalErr, fs.ErrNotExist) || errors.Is(originalErr, fs.ErrPermission) {
|
||||||
|
return originalErr
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(name, string(sep))
|
||||||
|
for i := range parts {
|
||||||
|
if parts[i] == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fi, err := stat(strings.Join(parts[:i+1], string(sep)))
|
||||||
|
if err != nil {
|
||||||
|
return originalErr
|
||||||
|
}
|
||||||
|
if !fi.IsDir() {
|
||||||
|
return fs.ErrNotExist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return originalErr
|
||||||
|
}
|
||||||
|
|
@ -7,20 +7,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Middlewares the middlewares
|
// Middlewares the middlewares
|
||||||
var Middlewares = []func(c *gin.Context){
|
var Middlewares = []gin.HandlerFunc{
|
||||||
|
gin.Logger(),
|
||||||
withStaticFileServer,
|
withStaticFileServer,
|
||||||
}
|
}
|
||||||
|
|
||||||
// withStaticFileServer static file server
|
// withStaticFileServer static file server
|
||||||
func withStaticFileServer(c *gin.Context) {
|
func withStaticFileServer(c *gin.Context) {
|
||||||
|
|
||||||
|
// Handle API & websocket
|
||||||
length := len(c.Request.URL.Path)
|
length := len(c.Request.URL.Path)
|
||||||
|
|
||||||
if (length >= 5 && c.Request.URL.Path[0:5] == "/api/") ||
|
if (length >= 5 && c.Request.URL.Path[0:5] == "/api/") ||
|
||||||
(length >= 11 && c.Request.URL.Path[0:11] == "/websocket/") { // API & websocket
|
(length >= 11 && c.Request.URL.Path[0:11] == "/websocket/") { // API & websocket
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Xgen 1.0
|
// Xgen 1.0
|
||||||
|
|
@ -31,6 +31,7 @@ func withStaticFileServer(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// __yao_admin_root
|
||||||
if length >= 18 && c.Request.URL.Path[0:18] == "/__yao_admin_root/" {
|
if length >= 18 && c.Request.URL.Path[0:18] == "/__yao_admin_root/" {
|
||||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, "/__yao_admin_root")
|
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, "/__yao_admin_root")
|
||||||
XGenFileServerV1.ServeHTTP(c.Writer, c.Request)
|
XGenFileServerV1.ServeHTTP(c.Writer, c.Request)
|
||||||
|
|
@ -38,13 +39,11 @@ func withStaticFileServer(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPA app static file server
|
// Rewrite
|
||||||
for root, rootLength := range SpaRoots {
|
for _, rewrite := range rewriteRules {
|
||||||
if length >= rootLength && c.Request.URL.Path[0:rootLength] == root {
|
if matches := rewrite.Pattern.FindStringSubmatch(c.Request.URL.Path); matches != nil {
|
||||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, root)
|
c.Request.URL.Path = rewrite.Pattern.ReplaceAllString(c.Request.URL.Path, rewrite.Replacement)
|
||||||
spaFileServers[root].ServeHTTP(c.Writer, c.Request)
|
break
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,17 +24,16 @@ func Start(cfg config.Config) (*http.Server, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
router.Use(gin.Logger())
|
router.Use(Middlewares...)
|
||||||
api.SetGuards(Guards)
|
api.SetGuards(Guards)
|
||||||
api.SetRoutes(router, "/api", cfg.AllowFrom...)
|
api.SetRoutes(router, "/api", cfg.AllowFrom...)
|
||||||
|
|
||||||
srv := http.New(router, http.Option{
|
srv := http.New(router, http.Option{
|
||||||
Host: cfg.Host,
|
Host: cfg.Host,
|
||||||
Port: cfg.Port,
|
Port: cfg.Port,
|
||||||
Root: "/api",
|
Root: "/api",
|
||||||
Allows: cfg.AllowFrom,
|
Allows: cfg.AllowFrom,
|
||||||
Timeout: 5 * time.Second,
|
Timeout: 5 * time.Second,
|
||||||
}).With(Middlewares...)
|
})
|
||||||
|
|
||||||
// Neo API
|
// Neo API
|
||||||
if neo.Neo != nil {
|
if neo.Neo != nil {
|
||||||
|
|
@ -48,6 +47,16 @@ func Start(cfg config.Config) (*http.Server, error) {
|
||||||
return srv, nil
|
return srv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restart the yao service
|
||||||
|
func Restart(srv *http.Server, cfg config.Config) error {
|
||||||
|
router := gin.New()
|
||||||
|
router.Use(Middlewares...)
|
||||||
|
api.SetGuards(Guards)
|
||||||
|
api.SetRoutes(router, "/api", cfg.AllowFrom...)
|
||||||
|
srv.Reset(router)
|
||||||
|
return srv.Restart()
|
||||||
|
}
|
||||||
|
|
||||||
// Stop the yao service
|
// Stop the yao service
|
||||||
func Stop(srv *http.Server) error {
|
func Stop(srv *http.Server) error {
|
||||||
err := srv.Stop()
|
err := srv.Stop()
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ package service
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/yaoapp/kun/log"
|
||||||
"github.com/yaoapp/yao/data"
|
"github.com/yaoapp/yao/data"
|
||||||
"github.com/yaoapp/yao/service/fs"
|
"github.com/yaoapp/yao/service/fs"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
|
|
@ -14,12 +15,6 @@ import (
|
||||||
// AppFileServer static file server
|
// AppFileServer static file server
|
||||||
var AppFileServer http.Handler
|
var AppFileServer http.Handler
|
||||||
|
|
||||||
// spaFileServers spa static file server
|
|
||||||
var spaFileServers map[string]http.Handler = map[string]http.Handler{}
|
|
||||||
|
|
||||||
// SpaRoots SPA static file server
|
|
||||||
var SpaRoots map[string]int = map[string]int{}
|
|
||||||
|
|
||||||
// XGenFileServerV1 XGen v1.0
|
// XGenFileServerV1 XGen v1.0
|
||||||
var XGenFileServerV1 http.Handler = http.FileServer(data.XgenV1())
|
var XGenFileServerV1 http.Handler = http.FileServer(data.XgenV1())
|
||||||
|
|
||||||
|
|
@ -29,42 +24,49 @@ var AdminRoot = ""
|
||||||
// AdminRootLen cache
|
// AdminRootLen cache
|
||||||
var AdminRootLen = 0
|
var AdminRootLen = 0
|
||||||
|
|
||||||
|
var rewriteRules = []rewriteRule{}
|
||||||
|
|
||||||
|
type rewriteRule struct {
|
||||||
|
Pattern *regexp.Regexp
|
||||||
|
Replacement string
|
||||||
|
}
|
||||||
|
|
||||||
// SetupStatic setup static file server
|
// SetupStatic setup static file server
|
||||||
func SetupStatic() error {
|
func SetupStatic() error {
|
||||||
|
setupAdminRoot()
|
||||||
// SetAdmin Root
|
setupRewrite()
|
||||||
adminRoot()
|
|
||||||
|
|
||||||
if isPWA() {
|
|
||||||
AppFileServer = http.FileServer(fs.DirPWA("public"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, root := range spaApps() {
|
|
||||||
spaFileServers[root] = http.FileServer(fs.DirPWA(filepath.Join("public", root)))
|
|
||||||
SpaRoots[root] = len(root)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppFileServer = http.FileServer(fs.Dir("public"))
|
AppFileServer = http.FileServer(fs.Dir("public"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewrite path
|
func setupRewrite() {
|
||||||
func isPWA() bool {
|
if share.App.Static.Rewrite != nil {
|
||||||
|
for _, rule := range share.App.Static.Rewrite {
|
||||||
|
|
||||||
return share.App.Static.PWA
|
pattern := ""
|
||||||
}
|
replacement := ""
|
||||||
|
for key, value := range rule {
|
||||||
|
pattern = key
|
||||||
|
replacement = value
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// rewrite path
|
re, err := regexp.Compile(pattern)
|
||||||
func spaApps() []string {
|
if err != nil {
|
||||||
if share.App.Static.Apps == nil {
|
log.Error("Invalid rewrite rule: %s", pattern)
|
||||||
return []string{}
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rewriteRules = append(rewriteRules, rewriteRule{
|
||||||
|
Pattern: re,
|
||||||
|
Replacement: replacement,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return share.App.Static.Apps
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupAdmin setup admin static root
|
// rewrite path
|
||||||
func adminRoot() (string, int) {
|
func setupAdminRoot() (string, int) {
|
||||||
if AdminRoot != "" {
|
if AdminRoot != "" {
|
||||||
return AdminRoot, AdminRootLen
|
return AdminRoot, AdminRootLen
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func Watch(srv *http.Server, interrupt chan uint8) (err error) {
|
||||||
|
|
||||||
// Restart
|
// Restart
|
||||||
if strings.HasPrefix(name, "/apis") {
|
if strings.HasPrefix(name, "/apis") {
|
||||||
err = srv.Restart()
|
err = Restart(srv, config.Conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(color.RedString("[Watch] Restart: %s", err.Error()))
|
fmt.Println(color.RedString("[Watch] Restart: %s", err.Error()))
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,7 @@ type Moapi struct {
|
||||||
|
|
||||||
// Static setting
|
// Static setting
|
||||||
type Static struct {
|
type Static struct {
|
||||||
PWA bool `json:"pwa,omitempty"`
|
Rewrite []map[string]string `json:"rewrite,omitempty"`
|
||||||
Apps []string `json:"apps,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppStorage 应用存储
|
// AppStorage 应用存储
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ func (page *Page) publicFile() string {
|
||||||
|
|
||||||
// writeHTMLTo write the html to file
|
// writeHTMLTo write the html to file
|
||||||
func (page *Page) writeHTML(html []byte) error {
|
func (page *Page) writeHTML(html []byte) error {
|
||||||
htmlFile := fmt.Sprintf("%s.html", page.publicFile())
|
htmlFile := fmt.Sprintf("%s.sui", page.publicFile())
|
||||||
dir := filepath.Dir(htmlFile)
|
dir := filepath.Dir(htmlFile)
|
||||||
if exist, _ := os.Stat(dir); exist == nil {
|
if exist, _ := os.Stat(dir); exist == nil {
|
||||||
os.MkdirAll(dir, os.ModePerm)
|
os.MkdirAll(dir, os.ModePerm)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue