feat: added access to the request in preprocessing in THT.

This commit is contained in:
Andrey Parhomenko 2024-05-06 23:08:56 +05:00
parent b22c57a80c
commit 8ac7b3bb31
9 changed files with 173 additions and 17 deletions

View file

@ -1,11 +1,11 @@
package main package main
import ( import (
"vultras.su/util/tpp/server" "vultras.su/util/tpp/httpx"
"os" "os"
) )
func main() { func main() {
server.Tool.Run(os.Args[1:]) httpx.Tool.Run(os.Args[1:])
} }

View file

@ -1,9 +1,10 @@
package server package httpx
import ( import (
"vultras.su/util/tpp" "vultras.su/util/tpp"
"path/filepath" "path/filepath"
"net/http" "net/http"
"context"
"path" "path"
"mime" "mime"
"log" "log"
@ -58,8 +59,11 @@ func (h *Handler) ServeHTTP(
return return
} }
ctx := context.WithValue(r.Context(), KeyRequest, &Request{
Request: r,
})
processedData, err := h.PP.Process( processedData, err := h.PP.Process(
r.Context(), ctx,
true, true,
filePathTpp, filePathTpp,
fileData, fileData,

2
httpx/http.go Normal file
View file

@ -0,0 +1,2 @@
package httpx

40
httpx/request.go Normal file
View file

@ -0,0 +1,40 @@
package httpx
import (
"github.com/d5/tengo/v2"
"net/http"
//"log"
)
type Request struct {
tengo.ObjectImpl
*http.Request
}
func (r *Request) TypeName() string {
return "*http.Request"
}
func (r *Request) String() string {
return "*http.Request{...}"
}
func (r *Request) IndexGet(
index tengo.Object,
) (tengo.Object, error) {
key, ok := tengo.ToString(index)
if !ok {
return nil, tengo.ErrInvalidIndexValueType
}
switch key {
case "url" :
return &URL{
URL: r.URL,
}, nil
}
// Nothing found.
return nil, nil
}

View file

@ -1,4 +1,4 @@
package server package httpx
import ( import (
//"github.com/d5/tengo/v2" //"github.com/d5/tengo/v2"
@ -7,8 +7,16 @@ import (
"vultras.su/core/cli/mtool" "vultras.su/core/cli/mtool"
"net/http" "net/http"
"log" "log"
"context"
) )
// Context key type for internal usage.
type CKey string
const (
KeyRequest CKey = "http-request"
)
// Simple PHP-like server implementation.
var Tool = mtool.T("tht").Func(func(flags *mtool.Flags){ var Tool = mtool.T("tht").Func(func(flags *mtool.Flags){
var ( var (
addr string addr string
@ -21,12 +29,23 @@ var Tool = mtool.T("tht").Func(func(flags *mtool.Flags){
flags.Parse() flags.Parse()
t := tpp.NewTengo().SetPreCompile(func(s *tpp.Script){ t := tpp.NewTengo().SetPreCompile(func(
ctx context.Context,
s *tpp.Script,
){
s.SetImportDir(handler.SourcePath)
s.SetImports(stdlib.GetModuleMap( s.SetImports(stdlib.GetModuleMap(
stdlib.AllModuleNames()..., stdlib.AllModuleNames()...,
)) ))
s.EnableFileImport(true) s.EnableFileImport(true)
s.SetImportDir(handler.SourcePath)
s.Add("__http_request__", ctx.Value(KeyRequest))
}).SetPreCode(func(ctx context.Context) []byte {
return []byte(`
http := {
request : __http_request__
}
`)
}) })
handler.PP = tpp.New(t) handler.PP = tpp.New(t)

76
httpx/url.go Normal file
View file

@ -0,0 +1,76 @@
package httpx
import (
"github.com/d5/tengo/v2"
"net/url"
"fmt"
)
var _ = tengo.Object(&Values{})
type Values struct {
tengo.ObjectImpl
url.Values
}
func (vs *Values) TypeName() string {
return "*url.Values"
}
func (vs *Values) String() string {
return fmt.Sprintf("%v", vs.Values)
}
func (vs *Values) IndexGet(
index tengo.Object,
) (tengo.Object, error) {
key, ok := tengo.ToString(index)
if !ok {
return nil, tengo.ErrInvalidIndexValueType
}
val, ok := vs.Values[key]
if !ok {
return nil, nil
}
arr := make([]tengo.Object, len(val))
for i, v := range val {
arr[i], _ = tengo.FromInterface(v)
}
return &tengo.Array{Value: arr}, nil
}
type URL struct {
tengo.ObjectImpl
*url.URL
}
func (u *URL) TypeName() string {
return "<URL>"
}
func (u *URL) String() string {
return u.URL.String()
}
func (u *URL) IndexGet(
index tengo.Object,
) (tengo.Object, error) {
key, ok := tengo.ToString(index)
if !ok {
return nil, tengo.ErrInvalidIndexValueType
}
switch key {
case "path" :
return tengo.FromInterface(u.Path)
case "query" :
return tengo.FromInterface(&Values{
Values: u.Query(),
})
}
// Nothing found.
return nil, nil
}

View file

@ -1,11 +1,26 @@
{{ {{
fmt := import("fmt")
req := http.request
q := req.url.query
// List checking.
list := [1, 2, 3, 4, 123] list := [1, 2, 3, 4, 123]
}}<!doctype html> }}<!doctype html>
<html><head> <html><head>
</head><body> </head><body>
{{
if q.name {
pp.print("<div id=\"name\">", q.name[0], "</div>")
}
}}
<div> <div>
Hello, Cock! Hello, Cock!
</div> </div>
<div>
{{
pp.print(req.url.path)
}}
</div>
<ul>{{ <ul>{{
for v in list { for v in list {
pp.print("<li>", v, "</li>") pp.print("<li>", v, "</li>")

View file

@ -16,9 +16,9 @@ type Tengo struct {
// Functions to modify // Functions to modify
// preprocessor for // preprocessor for
// more specific purposes. // more specific purposes.
preCode func() []byte preCode func(context.Context) []byte
postCode func() []byte postCode func(context.Context) []byte
preCompile func(*Script) preCompile func(context.Context, *Script)
} }
// Returns the new Tengo preprocessor // Returns the new Tengo preprocessor
@ -28,17 +28,17 @@ func NewTengo() *Tengo {
return ret return ret
} }
func (tengo *Tengo) SetPreCode(fn func() []byte) *Tengo { func (tengo *Tengo) SetPreCode(fn func(context.Context) []byte) *Tengo {
tengo.preCode = fn tengo.preCode = fn
return tengo return tengo
} }
func (tengo *Tengo) SetPostCode(fn func() []byte) *Tengo { func (tengo *Tengo) SetPostCode(fn func(context.Context) []byte) *Tengo {
tengo.postCode = fn tengo.postCode = fn
return tengo return tengo
} }
func (tengo *Tengo) SetPreCompile(fn func(*Script)) *Tengo { func (tengo *Tengo) SetPreCompile(fn func(context.Context, *Script)) *Tengo {
tengo.preCompile = fn tengo.preCompile = fn
return tengo return tengo
} }
@ -80,18 +80,18 @@ func (pp *Tengo) Eval(
fmt.Fprint(&fullCodeBuf, retHead) fmt.Fprint(&fullCodeBuf, retHead)
if pp.preCode != nil { if pp.preCode != nil {
fullCodeBuf.Write(pp.preCode()) fullCodeBuf.Write(pp.preCode(ctx))
} }
for _, code := range codes { for _, code := range codes {
fmt.Fprintln(&fullCodeBuf, "\n" + string(code) + retSeparator) fmt.Fprintln(&fullCodeBuf, "\n" + string(code) + retSeparator)
} }
if pp.postCode != nil { if pp.postCode != nil {
fullCodeBuf.Write(pp.postCode()) fullCodeBuf.Write(pp.postCode(ctx))
} }
script := tengo.NewScript(fullCodeBuf.Bytes()) script := tengo.NewScript(fullCodeBuf.Bytes())
if pp.preCompile != nil { if pp.preCompile != nil {
pp.preCompile(script) pp.preCompile(ctx, script)
} }
err := script.Add("__sprintf__", &tengo.UserFunction{ err := script.Add("__sprintf__", &tengo.UserFunction{

View file

@ -13,7 +13,7 @@ import (
var Tool = mtool.T("pp").Func(func(flags *mtool.Flags){ var Tool = mtool.T("pp").Func(func(flags *mtool.Flags){
t := NewTengo(). t := NewTengo().
SetPreCompile(func(s *Script){ SetPreCompile(func(ctx context.Context, s *Script){
s.SetImports(stdlib.GetModuleMap( s.SetImports(stdlib.GetModuleMap(
stdlib.AllModuleNames()..., stdlib.AllModuleNames()...,
)) ))