diff --git a/sui/api/request.go b/sui/api/request.go
index f2a134d1b..bc38f9053 100644
--- a/sui/api/request.go
+++ b/sui/api/request.go
@@ -2,11 +2,14 @@ package api
import (
"fmt"
+ "net/url"
+ "os"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
"github.com/yaoapp/gou/application"
+ "github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/sui/core"
)
@@ -37,7 +40,7 @@ func NewRequestContext(c *gin.Context) (*Request, int, error) {
Body: body,
Payload: payload,
Referer: c.Request.Referer(),
- Headers: c.Request.Header,
+ Headers: url.Values(c.Request.Header),
Params: params,
},
}, 200, nil
@@ -45,7 +48,53 @@ func NewRequestContext(c *gin.Context) (*Request, int, error) {
// Render is the response for the page API.
func (r *Request) Render() (string, int, error) {
- return r.File, 200, nil
+
+ c := core.GetCache(r.File)
+ if c == nil {
+ // Read the file
+ content, err := application.App.Read(r.File)
+ if err != nil {
+ return "", 404, err
+ }
+
+ doc, err := core.NewDocument(content)
+ if err != nil {
+ return "", 500, err
+ }
+
+ dataText := ""
+ dataSel := doc.Find("script[name=data]")
+ if dataSel != nil && dataSel.Length() > 0 {
+ dataText = dataSel.Text()
+ dataSel.Remove()
+ }
+
+ html, err := doc.Html()
+ if err != nil {
+ return "", 500, fmt.Errorf("parse error, please re-complie the page %s", err.Error())
+ }
+
+ // Save to The Cache
+ c = core.SetCache(r.File, html, dataText)
+ log.Trace("The page %s is cached", r.File)
+ }
+
+ var err error
+ data := core.Data{}
+ if c.Data != "" {
+ data, err = r.Request.ExecString(c.Data)
+ if err != nil {
+ return "", 500, fmt.Errorf("data error, please re-complie the page %s", err.Error())
+ }
+ }
+
+ parser := core.NewTemplateParser(data, nil)
+ html, err := parser.Render(c.HTML)
+ if err != nil {
+ return "", 500, fmt.Errorf("render error, please re-complie the page %s", err.Error())
+ }
+
+ return html, 200, nil
}
func parserPath(c *gin.Context) (string, map[string]string, error) {
@@ -57,7 +106,7 @@ func parserPath(c *gin.Context) (string, map[string]string, error) {
return "", nil, fmt.Errorf("no route matchers")
}
- fileParts := []string{application.App.Root(), "public"}
+ fileParts := []string{string(os.PathSeparator), "public"}
// Match the sui
matchers := core.RouteExactMatchers[parts[0]]
@@ -101,7 +150,7 @@ func parserPath(c *gin.Context) (string, map[string]string, error) {
} else if matcher.Regex != nil {
if matcher.Regex.MatchString(part) {
- file := matcher.Ref.(string)
+ file := matcher.Ref
key := strings.TrimRight(strings.TrimLeft(file, "["), "]")
params[key] = part
fileParts = append(fileParts, file)
diff --git a/sui/core/compile.go b/sui/core/compile.go
index 6ac2e74f6..c3fc0955f 100644
--- a/sui/core/compile.go
+++ b/sui/core/compile.go
@@ -1,7 +1,6 @@
package core
import (
- "fmt"
"regexp"
"github.com/evanw/esbuild/pkg/api"
@@ -30,13 +29,13 @@ func (page *Page) Compile(option *BuildOption) (string, error) {
)
}
- // add the route data
- doc.Find("body").AppendHtml(`\n")
+ // // add the route data
+ // doc.Find("body").AppendHtml(`\n")
html, err := doc.Html()
if err != nil {
diff --git a/sui/core/request.go b/sui/core/request.go
index 468a14e20..1f1841662 100644
--- a/sui/core/request.go
+++ b/sui/core/request.go
@@ -9,6 +9,15 @@ import (
"github.com/yaoapp/kun/any"
)
+// Cache the cache
+type Cache struct {
+ Data string
+ HTML string
+}
+
+// Caches the caches
+var Caches = map[string]*Cache{}
+
// ExecString get the data
func (r *Request) ExecString(data string) (Data, error) {
var res Data
@@ -50,6 +59,39 @@ func (r *Request) Exec(m Data) error {
func (r *Request) execValue(value interface{}) (interface{}, error) {
switch v := value.(type) {
case string:
+
+ if strings.HasPrefix(v, "$query.") {
+ key := strings.TrimLeft(v, "$query.")
+ if r.Query.Has(key) {
+ return r.Query.Get(key), nil
+ }
+ return "", nil
+ }
+
+ if strings.HasPrefix(v, "$header.") {
+ key := strings.TrimLeft(v, "$header.")
+ if r.Headers.Has(key) {
+ return r.Headers.Get(key), nil
+ }
+ return "", nil
+ }
+
+ if strings.HasPrefix(v, "$param.") {
+ key := strings.TrimLeft(v, "$param.")
+ if value, has := r.Params[key]; has {
+ return value, nil
+ }
+ return "", nil
+ }
+
+ if strings.HasPrefix(v, "$payload.") {
+ key := strings.TrimLeft(v, "$payload.")
+ if value, has := r.Payload[key]; has {
+ return value, nil
+ }
+ return "", nil
+ }
+
if strings.HasPrefix(v, "$") {
return r.call(strings.TrimLeft(v, "$"))
}
@@ -127,6 +169,10 @@ func (r *Request) call(p interface{}) (interface{}, error) {
return nil, err
}
+ if r.Sid != "" {
+ process.WithSID(r.Sid)
+ }
+
return process.Exec()
}
@@ -183,3 +229,30 @@ func (r *Request) parseArgs(args []interface{}) ([]interface{}, error) {
return args, nil
}
+
+// SetCache set the cache
+func SetCache(file string, html string, data string) *Cache {
+ Caches[file] = &Cache{
+ Data: data,
+ HTML: html,
+ }
+ return Caches[file]
+}
+
+// GetCache get the cache
+func GetCache(file string) *Cache {
+ if cache, has := Caches[file]; has {
+ return cache
+ }
+ return nil
+}
+
+// RemoveCache remove the cache
+func RemoveCache(file string) {
+ delete(Caches, file)
+}
+
+// CleanCache clean the cache
+func CleanCache() {
+ Caches = map[string]*Cache{}
+}
diff --git a/sui/core/sui.go b/sui/core/sui.go
index 139aa222f..7845e4c45 100644
--- a/sui/core/sui.go
+++ b/sui/core/sui.go
@@ -30,7 +30,6 @@ func (sui *DSL) WithSid(sid string) {
// PublicRootMatcher returns the public root matcher
func (sui *DSL) PublicRootMatcher() *Matcher {
- var ref SUI = sui
pub := sui.GetPublic()
if varRe.MatchString(pub.Root) {
if pub.Matcher != "" {
@@ -41,9 +40,9 @@ func (sui *DSL) PublicRootMatcher() *Matcher {
}
return &Matcher{Regex: re}
}
- return &Matcher{Regex: RouteRegexp, Ref: ref}
+ return &Matcher{Regex: RouteRegexp}
}
- return &Matcher{Exact: pub.Root, Ref: ref}
+ return &Matcher{Exact: pub.Root}
}
// PublicRoot returns the public root path
diff --git a/sui/core/types.go b/sui/core/types.go
index e797afc37..04a8db22d 100644
--- a/sui/core/types.go
+++ b/sui/core/types.go
@@ -147,8 +147,9 @@ type Request struct {
Payload map[string]interface{} `json:"payload,omitempty"`
Query url.Values `json:"query,omitempty"`
Params map[string]string `json:"params,omitempty"`
- Headers map[string][]string `json:"headers,omitempty"`
+ Headers url.Values `json:"headers,omitempty"`
Body interface{} `json:"body,omitempty"`
+ Sid string `json:"sid,omitempty"`
Theme string `json:"theme,omitempty"`
Locale string `json:"locale,omitempty"`
}
@@ -266,7 +267,7 @@ type Matcher struct {
Regex *regexp.Regexp `json:"regex,omitempty"`
Exact string `json:"exact,omitempty"`
Parent string `json:"-"`
- Ref interface{} `json:"-"`
+ Ref string `json:"-"`
}
// DocumentDefault is the default document
diff --git a/sui/storages/local/build.go b/sui/storages/local/build.go
index 7afcd7485..bc598cb5c 100644
--- a/sui/storages/local/build.go
+++ b/sui/storages/local/build.go
@@ -99,28 +99,23 @@ func (page *Page) publicFile() string {
log.Error("publicFile: Get the public root error: %s. use %s", err.Error(), page.tmpl.local.DSL.Public.Root)
root = page.tmpl.local.DSL.Public.Root
}
- return filepath.Join(application.App.Root(), "public", root, page.Route)
+ return filepath.Join("/", "public", root, page.Route)
}
// writeHTMLTo write the html to file
func (page *Page) writeHTML(html []byte) error {
htmlFile := fmt.Sprintf("%s.sui", page.publicFile())
- dir := filepath.Dir(htmlFile)
+ htmlFileAbs := filepath.Join(application.App.Root(), htmlFile)
+ dir := filepath.Dir(htmlFileAbs)
if exist, _ := os.Stat(dir); exist == nil {
os.MkdirAll(dir, os.ModePerm)
}
- return os.WriteFile(htmlFile, html, 0644)
-}
-
-// writeHTMLTo write the html to file
-func (page *Page) writeData() error {
- if page.Codes.DATA.Code == "" {
- return nil
- }
- dataFile := fmt.Sprintf("%s.json", page.publicFile())
- dir := filepath.Dir(dataFile)
- if exist, _ := os.Stat(dir); exist == nil {
- os.MkdirAll(dir, os.ModePerm)
+ err := os.WriteFile(htmlFileAbs, html, 0644)
+ if err != nil {
+ return err
}
- return os.WriteFile(dataFile, []byte(page.Codes.DATA.Code), 0644)
+
+ core.RemoveCache(htmlFile)
+ log.Trace("The page %s is removed", htmlFile)
+ return nil
}