package main import ( "fmt" "net/http" "strings" "github.com/nikolalohinski/gonja/v2" "github.com/nikolalohinski/gonja/v2/exec" ) func renderGonja(templateContent string, templatePath string, r *http.Request, extraData map[string]any) (string, error) { ctx := buildRequestContext(r, extraData) // Use FromFile to support extends/include resolution tmpl, err := gonja.FromFile(templatePath) if err != nil { return "", fmt.Errorf("parsing template %s: %w", templatePath, err) } // Execute template with context result, err := tmpl.ExecuteToString(ctx) if err != nil { return "", fmt.Errorf("executing template %s: %w", templatePath, err) } return result, nil } func buildRequestContext(r *http.Request, extraData map[string]any) *exec.Context { // Parse form data form := make(map[string]any) if err := r.ParseForm(); err == nil { for key, values := range r.Form { form[key] = values[0] } } query := make(map[string]any) for key, values := range r.URL.Query() { if len(values) == 1 { query[key] = values[0] } else { query[key] = values } } headers := make(map[string]any) for key, values := range r.Header { headers[strings.ToLower(key)] = values[0] } data := map[string]any{ "request": map[string]any{ "method": r.Method, "path": r.URL.Path, "query": query, "form": form, "headers": headers, }, "base_url": fmt.Sprintf("%s://%s", r.URL.Scheme, r.Host), } // Merge extra data from companion Lua data files for k, v := range extraData { data[k] = v } return exec.NewContext(data) }