feat: better way to get default PP and also the way to get access to the outer global state in the scripts.

This commit is contained in:
Andrey Parhomenko 2024-05-20 02:34:39 +05:00
parent 625d73689a
commit 7c7d1f7766
4 changed files with 73 additions and 31 deletions

View file

@ -1,6 +1,7 @@
package httpx package httpx
import ( import (
//"github.com/d5/tengo/v2"
"surdeus.su/util/tpp" "surdeus.su/util/tpp"
"path/filepath" "path/filepath"
"net/http" "net/http"
@ -28,22 +29,61 @@ type Handler struct {
// For example "file.html.tpp" will be // For example "file.html.tpp" will be
// first preprocessed TPP and sent back as simple HTML. // first preprocessed TPP and sent back as simple HTML.
ext string ext string
// The global map accessable from all the
// request so you can keep the states
// between requests.
global any
} }
// Returns the new Handler with // Returns the new Handler with
// specified preprocessor, source path and // specified preprocessor, source path,
// extension. // preprocessor extension and the global value.
func NewHandler( func NewHandler(
pp *tpp.Preprocessor, pp *tpp.Preprocessor,
src, ext string, src, ext string,
global any,
) *Handler { ) *Handler {
ret := &Handler{} ret := &Handler{}
ret.sourcePath = src ret.sourcePath = src
ret.ext = ext ret.ext = ext
ret.pp = pp ret.pp = pp
ret.global = global
return ret return ret
} }
// Returns the default tpp.Preprocessor suitable for
// the most needs.
func DefaultPP(mod string) *tpp.Preprocessor {
t := tpp.NewTengo().SetPreCompile(func(
ctx context.Context,
s *tpp.Script,
) {
s.SetImportDir(mod)
s.SetImports(&ModuleGetter{})
s.EnableFileImport(true)
s.Add("__http_request__", ctx.Value(KeyRequest))
s.Add("__global__", ctx.Value(KeyGlobal))
}).SetPreCode(func(ctx context.Context) []byte {
return []byte(`
http := immutable({
request : __http_request__
})
context.http = http
context.pp = pp
context.global = __global__
import("./pre")(context)
`)
}).SetPostCode(func(ctx context.Context) []byte {
return []byte(`
import("./post")(context)
`)
})
return tpp.New(t)
}
func (h *Handler) ServeHTTP( func (h *Handler) ServeHTTP(
w http.ResponseWriter, w http.ResponseWriter,
r *http.Request, r *http.Request,
@ -86,6 +126,12 @@ func (h *Handler) ServeHTTP(
}, },
) )
ctx = context.WithValue(
ctx,
KeyGlobal,
h.global,
)
// Setting before the code to let it change own // Setting before the code to let it change own
// content type. // content type.
contentType := mime.TypeByExtension(urlExt) contentType := mime.TypeByExtension(urlExt)

View file

@ -1,13 +1,12 @@
package httpx package httpx
import ( import (
//"github.com/d5/tengo/v2" "github.com/d5/tengo/v2"
//"github.com/d5/tengo/v2/stdlib" //"github.com/d5/tengo/v2/stdlib"
"surdeus.su/util/tpp"
"vultras.su/core/cli/mtool" "vultras.su/core/cli/mtool"
"net/http" "net/http"
"log" "log"
"context" //"context"
) )
// Context key type for internal usage. // Context key type for internal usage.
@ -15,6 +14,7 @@ type CKey string
const ( const (
KeyRequest CKey = "http-request" KeyRequest CKey = "http-request"
KeyGlobal = "global"
) )
// Simple PHP-like server implementation. // Simple PHP-like server implementation.
@ -30,33 +30,14 @@ var Tool = mtool.T("tht").Func(func(flags *mtool.Flags) {
flags.Parse() flags.Parse()
t := tpp.NewTengo().SetPreCompile(func(
ctx context.Context,
s *tpp.Script,
) {
s.SetImportDir(mod)
s.SetImports(&ModuleGetter{})
s.EnableFileImport(true)
s.Add("__http_request__", ctx.Value(KeyRequest))
}).SetPreCode(func(ctx context.Context) []byte {
return []byte(`
http := immutable({
request : __http_request__
})
__context__.http = http
__context__.pp = pp
import("./pre")(__context__)
`)
}).SetPostCode(func(ctx context.Context) []byte {
return []byte(`
import("./post")(__context__)
`)
})
srv := &http.Server{ srv := &http.Server{
Addr: addr, Addr: addr,
Handler: NewHandler(tpp.New(t), src, ext), Handler: NewHandler(
DefaultPP(mod),
src, ext,
map[string] tengo.Object{},
),
} }
err := srv.ListenAndServe() err := srv.ListenAndServe()
if err != nil { if err != nil {

View file

@ -1,11 +1,23 @@
{{# {{#
__context__.title = "The example.site main page" context.title = "The example.site main page"
}} }}
<h1>This is the example page for the THT</h1> <h1>This is the example page for the THT</h1>
{{ {{
/*if !context.global.int {
context.global.int = 0
} else {
context.global.int++
}*/
fmt := import("fmt") fmt := import("fmt")
if !context.global.val {
context.global.val = 1
} else {
context.global.val += 1
}
fmt.println("global: ", context.global)
req := http.request req := http.request
q := req.url.query q := req.url.query
// List checking. // List checking.
@ -23,6 +35,9 @@
pp.print("<div id=\"name\">", q.name[0], "</div>") pp.print("<div id=\"name\">", q.name[0], "</div>")
} }
}} }}
<div name="counter">
{{ pp.print(context.global.val) }}
</div>
<div> <div>
Hello, Cock! Hello, Cock!
</div> </div>

View file

@ -53,7 +53,7 @@ func (pp *Tengo) Eval(
) ([][]byte, error) { ) ([][]byte, error) {
var fullCodeBuf bytes.Buffer var fullCodeBuf bytes.Buffer
const retHead = ` const retHead = `
__context__ := {} context := {}
__ret_one__ := bytes("") __ret_one__ := bytes("")
pp := immutable({ pp := immutable({
filepath: __filepath__, filepath: __filepath__,