summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/starlarkmw/starlarkmw.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/caddyhttp/starlarkmw/starlarkmw.go')
-rw-r--r--modules/caddyhttp/starlarkmw/starlarkmw.go172
1 files changed, 0 insertions, 172 deletions
diff --git a/modules/caddyhttp/starlarkmw/starlarkmw.go b/modules/caddyhttp/starlarkmw/starlarkmw.go
deleted file mode 100644
index bd42e13..0000000
--- a/modules/caddyhttp/starlarkmw/starlarkmw.go
+++ /dev/null
@@ -1,172 +0,0 @@
-package starlarkmw
-
-import (
- "context"
- "fmt"
- "net/http"
-
- "github.com/caddyserver/caddy/v2"
- "github.com/caddyserver/caddy/v2/modules/caddyhttp"
- "github.com/caddyserver/caddy/v2/modules/caddyhttp/starlarkmw/internal/lib"
- caddyscript "github.com/caddyserver/caddy/v2/pkg/caddyscript/lib"
- "github.com/starlight-go/starlight/convert"
- "go.starlark.net/starlark"
-)
-
-func init() {
- caddy.RegisterModule(StarlarkMW{})
-}
-
-// StarlarkMW represents a middleware responder written in starlark
-type StarlarkMW struct {
- Script string `json:"script"`
- serveHTTP *starlark.Function
- setup *starlark.Function
- thread *starlark.Thread
- loadMiddleware *lib.LoadMiddleware
- execute *lib.Execute
- globals *starlark.StringDict
- gctx caddy.Context
- rctx caddy.Context
- rcancel context.CancelFunc
-}
-
-// CaddyModule returns the Caddy module information.
-func (StarlarkMW) CaddyModule() caddy.ModuleInfo {
- return caddy.ModuleInfo{
- ID: "http.handlers.starlark",
- New: func() caddy.Module { return new(StarlarkMW) },
- }
-}
-
-// ServeHTTP responds to an http request with starlark.
-func (s *StarlarkMW) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
- var mwcancel context.CancelFunc
- var mwctx caddy.Context
-
- // call setup() to prepare the middleware chain if it is defined
- if s.setup != nil {
- mwctx, mwcancel = caddy.NewContext(s.gctx)
- defer mwcancel()
-
- s.loadMiddleware.Ctx = mwctx
- args := starlark.Tuple{caddyscript.HTTPRequest{Req: r}}
-
- _, err := starlark.Call(new(starlark.Thread), s.setup, args, nil)
- if err != nil {
- return fmt.Errorf("starlark setup(), %v", err)
- }
- }
-
- // dynamically build middleware chain for each request
- var stack caddyhttp.Handler = caddyhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
- wr, err := convert.ToValue(w)
- if err != nil {
- return fmt.Errorf("cannot convert response writer to starlark value")
- }
-
- args := starlark.Tuple{wr, caddyscript.HTTPRequest{Req: r}}
- v, err := starlark.Call(new(starlark.Thread), s.serveHTTP, args, nil)
- if err != nil {
- return fmt.Errorf("starlark serveHTTP(), %v", err)
- }
-
- // if a responder type was returned from starlark we should run it otherwise it
- // is expected to handle the request
- if resp, ok := v.(lib.ResponderModule); ok {
- return resp.Instance.ServeHTTP(w, r)
- }
-
- return nil
- })
-
- // TODO :- make middlewareResponseWriter exported and wrap w with that
- var mid []caddyhttp.Middleware
- for _, m := range s.execute.Modules {
- mid = append(mid, func(next caddyhttp.Handler) caddyhttp.Handler {
- return caddyhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
- return m.Instance.ServeHTTP(w, r, next)
- })
- })
- }
-
- for i := len(mid) - 1; i >= 0; i-- {
- stack = mid[i](stack)
- }
-
- s.execute.Modules = nil
-
- return stack.ServeHTTP(w, r)
-}
-
-// Cleanup cleans up any modules loaded during the creation of a starlark route.
-func (s *StarlarkMW) Cleanup() error {
- s.rcancel()
- return nil
-}
-
-// Provision sets up the starlark env.
-func (s *StarlarkMW) Provision(ctx caddy.Context) error {
- // store global context
- s.gctx = ctx
-
- // setup context for cleaning up any modules loaded during starlark script parsing phase
- rctx, cancel := caddy.NewContext(ctx)
- s.rcancel = cancel
-
- // setup starlark global env
- env := make(starlark.StringDict)
- loadMiddleware := lib.LoadMiddleware{}
- loadResponder := lib.LoadResponder{
- Ctx: rctx,
- }
- execute := lib.Execute{}
-
- lr := starlark.NewBuiltin("loadResponder", loadResponder.Run)
- lr = lr.BindReceiver(&loadResponder)
- env["loadResponder"] = lr
-
- lm := starlark.NewBuiltin("loadMiddleware", loadMiddleware.Run)
- lm = lm.BindReceiver(&loadMiddleware)
- env["loadMiddleware"] = lm
-
- ex := starlark.NewBuiltin("execute", execute.Run)
- ex = ex.BindReceiver(&execute)
- env["execute"] = ex
-
- // import caddyscript lib
- env["time"] = caddyscript.Time{}
- env["regexp"] = caddyscript.Regexp{}
-
- // configure starlark
- thread := new(starlark.Thread)
- s.thread = thread
-
- // run starlark script
- globals, err := starlark.ExecFile(thread, "", s.Script, env)
- if err != nil {
- return fmt.Errorf("starlark exec file: %v", err.Error())
- }
-
- // extract defined methods to setup middleware chain and responder, setup is not required
- var setup *starlark.Function
- if _, ok := globals["setup"]; ok {
- setup, ok = globals["setup"].(*starlark.Function)
- if !ok {
- return fmt.Errorf("setup function not defined in starlark script")
- }
- }
-
- serveHTTP, ok := globals["serveHTTP"].(*starlark.Function)
- if !ok {
- return fmt.Errorf("serveHTTP function not defined in starlark script")
- }
-
- s.setup = setup
- s.serveHTTP = serveHTTP
- s.loadMiddleware = &loadMiddleware
- s.execute = &execute
- s.globals = &globals
-
- return nil
-}