commit
06a73db117
6 changed files with 118 additions and 117 deletions
|
|
@ -1,57 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
@ -47,6 +47,14 @@ func withStaticFileServer(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sui file server
|
||||||
|
if strings.HasSuffix(c.Request.URL.Path, ".sui") {
|
||||||
|
data := []byte(`SUI Server: ` + c.Request.URL.Path)
|
||||||
|
c.Data(200, "text/html; charset=utf-8", data)
|
||||||
|
c.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// static file server
|
// static file server
|
||||||
AppFileServer.ServeHTTP(c.Writer, c.Request)
|
AppFileServer.ServeHTTP(c.Writer, c.Request)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,20 @@ func (page *Page) Compile(option *BuildOption) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if page.Codes.DATA.Code != "" {
|
if page.Codes.DATA.Code != "" {
|
||||||
doc.Find("body").AppendHtml(`<script name="data" type="json">` +
|
doc.Find("body").AppendHtml("\n\n" + `<script name="data" type="json">` + "\n" +
|
||||||
fmt.Sprintf("\n%s\n", page.Codes.DATA.Code) +
|
page.Codes.DATA.Code +
|
||||||
"</script>\n",
|
"\n</script>\n\n",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add the route data
|
||||||
|
doc.Find("body").AppendHtml(`<script name="route" type="json">` + "\n" +
|
||||||
|
fmt.Sprintf(
|
||||||
|
`{"sui": "%s", "template": "%s", "route": "%s"}`,
|
||||||
|
page.SuiID, page.TemplateID, page.Route,
|
||||||
|
) +
|
||||||
|
"\n</script>\n")
|
||||||
|
|
||||||
html, err := doc.Html()
|
html, err := doc.Html()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
||||||
98
sui/core/fs.go
Normal file
98
sui/core/fs.go
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/yaoapp/gou/application"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SuiFile is a custom implementation of http.File
|
||||||
|
type SuiFile struct {
|
||||||
|
reader io.Reader
|
||||||
|
size int64
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// SuiFileInfo is a custom implementation of os.FileInfo
|
||||||
|
type SuiFileInfo struct {
|
||||||
|
size int64
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open is a custom implementation of http.FileSystem
|
||||||
|
func Open(c *gin.Context, path string, name string) (http.File, error) {
|
||||||
|
root := application.App.Root()
|
||||||
|
pathName := filepath.Join(root, path, name)
|
||||||
|
data := []byte(fmt.Sprintf(`SUI Server: %s`, pathName))
|
||||||
|
return &SuiFile{
|
||||||
|
reader: bytes.NewReader(data),
|
||||||
|
size: int64(len(data)),
|
||||||
|
name: filepath.Base(name) + ".html",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close is a custom implementation of the Close method for SuiFile
|
||||||
|
func (file *SuiFile) Close() error {
|
||||||
|
file.reader = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read is a custom implementation of the Read method for SuiFile
|
||||||
|
func (file *SuiFile) Read(b []byte) (n int, err error) {
|
||||||
|
// Use the custom SuiFile reader
|
||||||
|
return file.reader.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek is a custom implementation of the Seek method for SuiFile
|
||||||
|
func (file *SuiFile) Seek(offset int64, whence int) (int64, error) {
|
||||||
|
// Use the Seek method of the underlying os.File
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Readdir is a custom implementation of the Readdir method for SuiFile
|
||||||
|
func (file *SuiFile) Readdir(n int) ([]os.FileInfo, error) {
|
||||||
|
// Use the Readdir method of the underlying os.File
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat is a custom implementation of the Stat method for SuiFile
|
||||||
|
func (file *SuiFile) Stat() (os.FileInfo, error) {
|
||||||
|
return &SuiFileInfo{size: file.size, name: file.name}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size is a custom implementation of os.FileInfo
|
||||||
|
func (info *SuiFileInfo) Size() int64 {
|
||||||
|
return info.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name is a custom implementation of os.FileInfo
|
||||||
|
func (info *SuiFileInfo) Name() string {
|
||||||
|
return info.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mode is a custom implementation of os.FileInfo
|
||||||
|
func (info *SuiFileInfo) Mode() os.FileMode {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModTime is a custom implementation of os.FileInfo
|
||||||
|
func (info *SuiFileInfo) ModTime() time.Time {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDir is a custom implementation of os.FileInfo
|
||||||
|
func (info *SuiFileInfo) IsDir() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sys is a custom implementation of os.FileInfo
|
||||||
|
func (info *SuiFileInfo) Sys() interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
1
sui/core/fs_test.go
Normal file
1
sui/core/fs_test.go
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
package core
|
||||||
Loading…
Add table
Reference in a new issue