Started server

This commit is contained in:
Simon Martens
2026-02-19 15:09:44 +01:00
parent df79656c77
commit 59fb813c85
7 changed files with 115 additions and 94 deletions

46
:wq Normal file
View File

@@ -0,0 +1,46 @@
package main
import (
"log/slog"
"github.com/Theodor-Springmann-Stiftung/lenz-web/app"
"github.com/Theodor-Springmann-Stiftung/lenz-web/server"
)
func main() {
cfg, err := GetConfig()
if err != nil {
panic(err)
}
if cfg.Debug {
slog.SetLogLoggerLevel(slog.LevelDebug)
}
application, err := app.New(cfg)
if err != nil {
panic(err)
}
err = Serve(application)
if err != nil {
panic(err)
}
}
func Serve(app *app.App) error {
server, err := server.NewServer(app)
if err != nil {
return err
}
server.Start()
return nil
}
func GetConfig() (app.Config, error) {
cp := app.NewConfigProvider([]string{"config.dev.json", "config.json"})
if err := cp.Read(); err != nil {
return app.Config{}, err
}
return *cp.Config, nil
}

View File

@@ -1,7 +1,6 @@
package app
import (
"fmt"
"html/template"
"path/filepath"
"sync"
@@ -15,9 +14,8 @@ type App struct {
mu sync.Mutex
lib atomic.Pointer[xmlmodels.Library]
repo atomic.Pointer[git.Repo]
tmpl *template.Template
routes []Route
err error
tmpl atomic.Pointer[*template.Template]
cfg Config
}
func New(cfg Config) (*App, error) {
@@ -37,39 +35,15 @@ func (a *App) Repo() *git.Repo {
}
func (a *App) Templates() *template.Template {
return a.tmpl
return *a.tmpl.Load()
}
func (a *App) Routes() []Route {
a.mu.Lock()
defer a.mu.Unlock()
ret := make([]Route, len(a.routes))
copy(ret, a.routes)
return ret
func (a *App) Config() Config {
return a.cfg
}
func (a *App) RenderPath(path string) ([]byte, error) {
a.mu.Lock()
var route *Route
for i := range a.routes {
if a.routes[i].Path == path {
r := a.routes[i]
route = &r
break
}
}
a.mu.Unlock()
if route == nil || route.page == nil {
return nil, fmt.Errorf("no route for path: %s", path)
}
model, err := route.page.Model(a, *route)
if err != nil {
return nil, err
}
return route.page.Render(a, *route, model)
func (a *App) Pages() []Page {
return RegisteredPages()
}
func (a *App) init(cfg Config) error {
@@ -103,15 +77,9 @@ func (a *App) init(cfg Config) error {
a.repo.Store(repo)
a.lib.Store(lib)
a.tmpl = tmpl
a.tmpl.Store(&tmpl)
routes, err := discoverPages(a)
if err != nil {
return err
}
a.routes = routes
a.err = nil
a.cfg = cfg
return nil
}
@@ -126,12 +94,5 @@ func (a *App) RefreshLibrary(dir string, commit *git.Commit) (*xmlmodels.Library
a.lib.Store(lib)
routes, err := discoverPages(a)
if err != nil {
return nil, err
}
a.routes = routes
a.err = nil
return lib, nil
}

View File

@@ -1,7 +1,5 @@
package app
import "sync"
type Route struct {
Path string
Kind string
@@ -12,28 +10,19 @@ type Route struct {
type Page interface {
Discover(app *App) ([]Route, error)
Model(app *App, route Route) (map[string]any, error)
Render(app *App, route Route, model map[string]any) ([]byte, error)
}
var (
pagesMu sync.RWMutex
pages []Page
)
var pages []Page
func RegisterPage(page Page) {
if page == nil {
panic("cannot register nil page")
}
pagesMu.Lock()
defer pagesMu.Unlock()
pages = append(pages, page)
}
func RegisteredPages() []Page {
pagesMu.RLock()
defer pagesMu.RUnlock()
ret := make([]Page, len(pages))
copy(ret, pages)
return ret

26
lenz.go
View File

@@ -1,13 +1,10 @@
package main
import (
"io/fs"
"log/slog"
"github.com/Theodor-Springmann-Stiftung/lenz-web/app"
_ "github.com/Theodor-Springmann-Stiftung/lenz-web/pages"
"github.com/Theodor-Springmann-Stiftung/lenz-web/templates"
"github.com/labstack/echo/v5"
"github.com/Theodor-Springmann-Stiftung/lenz-web/server"
)
func main() {
@@ -25,28 +22,19 @@ func main() {
panic(err)
}
e := echo.New()
publicFS, err := fs.Sub(templates.PublicFS, "public")
err = Serve(application)
if err != nil {
panic(err)
}
e.StaticFS("/public", publicFS)
}
for _, route := range application.Routes() {
routePath := route.Path
e.GET(routePath, func(c *echo.Context) error {
out, err := application.RenderPath(routePath)
func Serve(app *app.App) error {
server, err := server.NewServer(app)
if err != nil {
return err
}
return c.HTMLBlob(200, out)
})
}
addr := cfg.Address + ":" + cfg.Port
if err := e.Start(addr); err != nil {
panic(err)
}
server.Start()
return nil
}
func GetConfig() (app.Config, error) {

View File

@@ -1,8 +1,6 @@
package pages
import (
"bytes"
"github.com/Theodor-Springmann-Stiftung/lenz-web/app"
)
@@ -23,11 +21,3 @@ func (p HomePage) Model(a *app.App, route app.Route) (map[string]any, error) {
"Message": "Template system is working.",
}, nil
}
func (p HomePage) Render(a *app.App, route app.Route, model map[string]any) ([]byte, error) {
var buf bytes.Buffer
if err := a.Templates().ExecuteTemplate(&buf, "home", model); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

11
server/endpoints.go Normal file
View File

@@ -0,0 +1,11 @@
package server
import (
"github.com/Theodor-Springmann-Stiftung/lenz-web/templates"
"github.com/labstack/echo/v5"
)
func MapStatic(e *echo.Echo) {
// INFO: Static files here:
e.StaticFS("/public", templates.PublicFS)
}

36
server/server.go Normal file
View File

@@ -0,0 +1,36 @@
package server
import (
"html/template"
"github.com/Theodor-Springmann-Stiftung/lenz-web/app"
"github.com/labstack/echo/v5"
)
// WARNING: this is not thread-safe. You can not write and read from the server at the same time!
type Server struct {
server *echo.Echo
cfg app.Config
tmpl *template.Template
}
func NewServer(app *app.App) (*Server, error) {
s := &Server{
server: echo.New(),
cfg: app.Config(),
tmpl: app.Templates(),
}
// INFO: Endpoint mapping here:
MapStatic(s.server)
return s, nil
}
func (s *Server) Start() error {
addr := s.cfg.Address + ":" + s.cfg.Port
if err := s.server.Start(addr); err != nil {
return err
}
return nil
}