Skip to content

Commit

Permalink
Merge pull request #503 from trheyi/main
Browse files Browse the repository at this point in the history
[add]  server rewrite support and fix api reload
  • Loading branch information
trheyi authored Nov 22, 2023
2 parents 3d51488 + 01d4b49 commit 293c487
Show file tree
Hide file tree
Showing 11 changed files with 257 additions and 171 deletions.
52 changes: 52 additions & 0 deletions service/fs/default.go
Original file line number Diff line number Diff line change
@@ -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 changes: 0 additions & 120 deletions service/fs/fs.go

This file was deleted.

57 changes: 57 additions & 0 deletions service/fs/spa.go
Original file line number Diff line number Diff line change
@@ -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 changes: 57 additions & 0 deletions service/fs/sui.go
Original file line number Diff line number Diff line change
@@ -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 changes: 31 additions & 0 deletions service/fs/utils.go
Original file line number Diff line number Diff line change
@@ -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
}
19 changes: 9 additions & 10 deletions service/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ import (
)

// Middlewares the middlewares
var Middlewares = []func(c *gin.Context){
var Middlewares = []gin.HandlerFunc{
gin.Logger(),
withStaticFileServer,
}

// withStaticFileServer static file server
func withStaticFileServer(c *gin.Context) {

// Handle API & websocket
length := len(c.Request.URL.Path)

if (length >= 5 && c.Request.URL.Path[0:5] == "/api/") ||
(length >= 11 && c.Request.URL.Path[0:11] == "/websocket/") { // API & websocket
c.Next()
return

}

// Xgen 1.0
Expand All @@ -31,20 +31,19 @@ func withStaticFileServer(c *gin.Context) {
return
}

// __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")
XGenFileServerV1.ServeHTTP(c.Writer, c.Request)
c.Abort()
return
}

// SPA app static file server
for root, rootLength := range SpaRoots {
if length >= rootLength && c.Request.URL.Path[0:rootLength] == root {
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, root)
spaFileServers[root].ServeHTTP(c.Writer, c.Request)
c.Abort()
return
// Rewrite
for _, rewrite := range rewriteRules {
if matches := rewrite.Pattern.FindStringSubmatch(c.Request.URL.Path); matches != nil {
c.Request.URL.Path = rewrite.Pattern.ReplaceAllString(c.Request.URL.Path, rewrite.Replacement)
break
}
}

Expand Down
Loading

0 comments on commit 293c487

Please sign in to comment.