diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/caddyhttp/matchers.go | 29 | ||||
-rw-r--r-- | modules/caddyhttp/standard/imports.go | 1 | ||||
-rw-r--r-- | modules/caddyhttp/starlarkmw/example/caddy.json | 19 | ||||
-rw-r--r-- | modules/caddyhttp/starlarkmw/internal/lib/module.go | 165 | ||||
-rw-r--r-- | modules/caddyhttp/starlarkmw/starlarkmw.go | 172 | ||||
-rw-r--r-- | modules/caddyhttp/starlarkmw/tools/gen/example.star | 40 |
6 files changed, 0 insertions, 426 deletions
diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index 49fe859..873b63d 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -28,8 +28,6 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" - "github.com/caddyserver/caddy/v2/pkg/caddyscript" - "go.starlark.net/starlark" ) type ( @@ -105,9 +103,6 @@ type ( Matchers MatcherSet `json:"-"` } - // MatchStarlarkExpr matches requests by evaluating a Starlark expression. - MatchStarlarkExpr string - // MatchTable matches requests by values in the table. MatchTable string // TODO: finish implementing ) @@ -123,7 +118,6 @@ func init() { caddy.RegisterModule(new(MatchProtocol)) caddy.RegisterModule(MatchRemoteIP{}) caddy.RegisterModule(MatchNegate{}) - caddy.RegisterModule(new(MatchStarlarkExpr)) } // CaddyModule returns the Caddy module information. @@ -646,28 +640,6 @@ func (m MatchRemoteIP) Match(r *http.Request) bool { return false } -// CaddyModule returns the Caddy module information. -func (MatchStarlarkExpr) CaddyModule() caddy.ModuleInfo { - return caddy.ModuleInfo{ - ID: "http.matchers.starlark", - New: func() caddy.Module { return new(MatchStarlarkExpr) }, - } -} - -// Match returns true if r matches m. -func (m MatchStarlarkExpr) Match(r *http.Request) bool { - input := string(m) - thread := new(starlark.Thread) - env := caddyscript.MatcherEnv(r) - val, err := starlark.Eval(thread, "", input, env) - if err != nil { - // TODO: Can we detect this in Provision or Validate instead? - log.Printf("caddyscript for matcher is invalid: attempting to evaluate expression `%v` error `%v`", input, err) - return false - } - return val.String() == "True" -} - // MatchRegexp is an embeddable type for matching // using regular expressions. It adds placeholders // to the request's replacer. @@ -834,7 +806,6 @@ var ( _ caddy.Provisioner = (*MatchRemoteIP)(nil) _ RequestMatcher = (*MatchNegate)(nil) _ caddy.Provisioner = (*MatchNegate)(nil) - _ RequestMatcher = (*MatchStarlarkExpr)(nil) _ caddy.Provisioner = (*MatchRegexp)(nil) _ caddyfile.Unmarshaler = (*MatchHost)(nil) diff --git a/modules/caddyhttp/standard/imports.go b/modules/caddyhttp/standard/imports.go index b85a984..1effb5a 100644 --- a/modules/caddyhttp/standard/imports.go +++ b/modules/caddyhttp/standard/imports.go @@ -15,6 +15,5 @@ import ( _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy" _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy/fastcgi" _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/rewrite" - _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/starlarkmw" _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/templates" ) diff --git a/modules/caddyhttp/starlarkmw/example/caddy.json b/modules/caddyhttp/starlarkmw/example/caddy.json deleted file mode 100644 index 9479d17..0000000 --- a/modules/caddyhttp/starlarkmw/example/caddy.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "apps": { - "http": { - "servers": { - "MY_SERVER": { - "listen": [":3001"], - "routes": [ - { - "handle": { - "handler": "starlark", - "script": "def setup(r):\n\t# create some middlewares specific to this request\n\ttemplates = loadModule('http.handlers.templates', {'file_root': './includes'})\n\tmidChain = execute([templates])\n\ndef serveHTTP (rw, r):\n\trw.Write('Hello world, from Starlark!')\n" - } - } - ] - } - } - } - } -}
\ No newline at end of file diff --git a/modules/caddyhttp/starlarkmw/internal/lib/module.go b/modules/caddyhttp/starlarkmw/internal/lib/module.go deleted file mode 100644 index 13c706c..0000000 --- a/modules/caddyhttp/starlarkmw/internal/lib/module.go +++ /dev/null @@ -1,165 +0,0 @@ -package lib - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/caddyserver/caddy/v2/modules/caddyhttp" - - "github.com/caddyserver/caddy/v2" - "go.starlark.net/starlark" -) - -// ResponderModule represents a module that satisfies the caddyhttp handler. -type ResponderModule struct { - Name string - Cfg json.RawMessage - Instance caddyhttp.Handler -} - -func (r ResponderModule) Freeze() {} -func (r ResponderModule) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: responder module") } -func (r ResponderModule) String() string { return "responder module" } -func (r ResponderModule) Type() string { return "responder module" } -func (r ResponderModule) Truth() starlark.Bool { return true } - -// Middleware represents a module that satisfies the starlark Value interface. -type Middleware struct { - Name string - Cfg json.RawMessage - Instance caddyhttp.MiddlewareHandler -} - -func (r Middleware) Freeze() {} -func (r Middleware) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: middleware") } -func (r Middleware) String() string { return "middleware" } -func (r Middleware) Type() string { return "middleware" } -func (r Middleware) Truth() starlark.Bool { return true } - -// LoadMiddleware represents the method exposed to starlark to load a Caddy module. -type LoadMiddleware struct { - Middleware Middleware - Ctx caddy.Context -} - -func (r LoadMiddleware) Freeze() {} -func (r LoadMiddleware) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: loadMiddleware") } -func (r LoadMiddleware) String() string { return "loadMiddleware" } -func (r LoadMiddleware) Type() string { return "function: loadMiddleware" } -func (r LoadMiddleware) Truth() starlark.Bool { return true } - -// Run is the method bound to the starlark loadMiddleware function. -func (r *LoadMiddleware) Run(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { - var name string - var cfg *starlark.Dict - err := starlark.UnpackPositionalArgs(fn.Name(), args, kwargs, 2, &name, &cfg) - if err != nil { - return starlark.None, fmt.Errorf("unpacking arguments: %v", err.Error()) - } - - js := json.RawMessage(cfg.String()) - - if !strings.Contains(name, "http.handlers.") { - name = fmt.Sprintf("http.handlers.%s", name) - } - - inst, err := r.Ctx.LoadModuleByID(name, js) - if err != nil { - return starlark.None, err - } - - mid, ok := inst.(caddyhttp.MiddlewareHandler) - if !ok { - return starlark.None, fmt.Errorf("could not assert as middleware handler") - } - - m := Middleware{ - Name: name, - Cfg: js, - Instance: mid, - } - - r.Middleware = m - - return m, nil -} - -// LoadResponder represents the method exposed to starlark to load a Caddy middleware responder. -type LoadResponder struct { - Module ResponderModule - Ctx caddy.Context -} - -func (r LoadResponder) Freeze() {} -func (r LoadResponder) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: loadModule") } -func (r LoadResponder) String() string { return "loadModule" } -func (r LoadResponder) Type() string { return "function: loadModule" } -func (r LoadResponder) Truth() starlark.Bool { return true } - -// Run is the method bound to the starlark loadResponder function. -func (r *LoadResponder) Run(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { - var name string - var cfg *starlark.Dict - err := starlark.UnpackPositionalArgs(fn.Name(), args, kwargs, 2, &name, &cfg) - if err != nil { - return starlark.None, fmt.Errorf("unpacking arguments: %v", err.Error()) - } - - js := json.RawMessage(cfg.String()) - - if !strings.Contains(name, "http.handlers.") { - name = fmt.Sprintf("http.handlers.%s", name) - } - - inst, err := r.Ctx.LoadModuleByID(name, js) - if err != nil { - return starlark.None, err - } - - res, ok := inst.(caddyhttp.Handler) - if !ok { - return starlark.None, fmt.Errorf("could not assert as responder") - } - - m := ResponderModule{ - Name: name, - Cfg: js, - Instance: res, - } - - r.Module = m - - return m, nil -} - -// Execute represents the method exposed to starlark to build a middleware chain. -type Execute struct { - Modules []Middleware -} - -func (r Execute) Freeze() {} -func (r Execute) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: execute") } -func (r Execute) String() string { return "execute" } -func (r Execute) Type() string { return "function: execute" } -func (r Execute) Truth() starlark.Bool { return true } - -// Run is the method bound to the starlark execute function. -func (r *Execute) Run(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { - var mids *starlark.List - err := starlark.UnpackPositionalArgs(fn.Name(), args, kwargs, 1, &mids) - if err != nil { - return starlark.None, fmt.Errorf("unpacking arguments: %v", err.Error()) - } - - for i := 0; i < mids.Len(); i++ { - val, ok := mids.Index(i).(Middleware) - if !ok { - return starlark.None, fmt.Errorf("cannot get module from execute") - } - - r.Modules = append(r.Modules, val) - } - - return starlark.None, nil -} 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 -} diff --git a/modules/caddyhttp/starlarkmw/tools/gen/example.star b/modules/caddyhttp/starlarkmw/tools/gen/example.star deleted file mode 100644 index 6ccab32..0000000 --- a/modules/caddyhttp/starlarkmw/tools/gen/example.star +++ /dev/null @@ -1,40 +0,0 @@ -# any module that provisions resources -proxyConfig = { - 'load_balance_type': 'round_robin', - 'upstreams': [ - { - 'host': 'http://localhost:8080', - 'circuit_breaker': { - 'type': 'status_ratio', - 'threshold': 0.5 - } - }, - { - 'host': 'http://localhost:8081' - } - ] -} - -sfConfig = { - 'root': '/Users/dev/Desktop', - 'browse': {}, -} - -proxy = loadResponder('reverse_proxy', proxyConfig) -static_files = loadResponder('file_server', sfConfig) - -def setup(r): - # create some middlewares specific to this request - mid = [] - - if r.query.get('log') == 'true': - logMid = loadMiddleware('log', {'file': 'access.log'}) - mid.append(logMid) - - execute(mid) - -def serveHTTP(w, r): - if r.url.find('static') > 0: - return static_files - - return proxy |