From a9a607b9b26c5d63e773deb639f2abf9d4847f8c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 10 Dec 2019 16:00:50 +0100 Subject: [PATCH] Allow plugins to add new routes References: https://todo.sr.ht/~sircmpwn/koushin/6 --- README.md | 2 ++ plugin.go | 34 ++++++++++++++++++++++++++++++++++ server.go | 4 ++++ 3 files changed, 40 insertions(+) diff --git a/README.md b/README.md index 7aa62f4..edb4aa5 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ API: * `koushin.on_render(name, f)`: prior to rendering the template `name`, call `f` with the template data * `koushin.set_filter(name, f)`: set a template function +* `koushin.set_route(method, path, f)`: register a new HTTP route, `f` will be + called with the HTTP context ## License diff --git a/plugin.go b/plugin.go index 9464d60..a25f34b 100644 --- a/plugin.go +++ b/plugin.go @@ -13,15 +13,23 @@ import ( type Plugin interface { Name() string Filters() template.FuncMap + SetRoutes(group *echo.Group) Render(name string, data interface{}) error Close() error } +type luaRoute struct { + method string + path string + f *lua.LFunction +} + type luaPlugin struct { filename string state *lua.LState renderCallbacks map[string]*lua.LFunction filters template.FuncMap + routes []luaRoute } func (p *luaPlugin) Name() string { @@ -60,6 +68,14 @@ func (p *luaPlugin) setFilter(l *lua.LState) int { return 0 } +func (p *luaPlugin) setRoute(l *lua.LState) int { + method := l.CheckString(1) + path := l.CheckString(2) + f := l.CheckFunction(3) + p.routes = append(p.routes, luaRoute{method, path, f}) + return 0 +} + func (p *luaPlugin) Render(name string, data interface{}) error { f, ok := p.renderCallbacks[name] if !ok { @@ -82,6 +98,23 @@ func (p *luaPlugin) Filters() template.FuncMap { return p.filters } +func (p *luaPlugin) SetRoutes(group *echo.Group) { + for _, r := range p.routes { + group.Match([]string{r.method}, r.path, func(ctx echo.Context) error { + err := p.state.CallByParam(lua.P{ + Fn: r.f, + NRet: 0, + Protect: true, + }, luar.New(p.state, ctx)) + if err != nil { + return fmt.Errorf("Lua plugin error: %v", err) + } + + return nil + }) + } +} + func (p *luaPlugin) Close() error { p.state.Close() return nil @@ -100,6 +133,7 @@ func loadLuaPlugin(filename string) (*luaPlugin, error) { l.SetGlobal("koushin", mt) l.SetField(mt, "on_render", l.NewFunction(p.onRender)) l.SetField(mt, "set_filter", l.NewFunction(p.setFilter)) + l.SetField(mt, "set_route", l.NewFunction(p.setRoute)) if err := l.DoFile(filename); err != nil { l.Close() diff --git a/server.go b/server.go index 0ab7f24..678a5e4 100644 --- a/server.go +++ b/server.go @@ -204,5 +204,9 @@ func New(e *echo.Echo, options *Options) error { e.Static("/assets", "public/assets") e.Static("/themes", "public/themes") + for _, p := range s.plugins { + p.SetRoutes(e.Group("")) + } + return nil }