hmn/src/website/fishbowl.go

70 lines
2.1 KiB
Go

package website
import (
"errors"
"html/template"
"io"
"io/fs"
"net/http"
"path"
"strings"
"git.handmade.network/hmn/hmn/src/oops"
"git.handmade.network/hmn/hmn/src/templates"
"git.handmade.network/hmn/hmn/src/utils"
)
func FishbowlIndex(c *RequestContext) ResponseData {
var res ResponseData
err := res.WriteTemplate("fishbowl_index.html", getBaseData(c, "Fishbowls", nil), c.Perf)
if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to render fishbowl index page"))
}
return res
}
func Fishbowl(c *RequestContext) ResponseData {
// Only serve up valid fishbowls
if _, err := fs.Stat(fishbowlFS, c.PathParams["name"]); errors.Is(err, fs.ErrNotExist) {
return FourOhFour(c)
}
// Ensure trailing slash (it matters for relative URLs in the HTML)
if !strings.HasSuffix(c.URL().Path, "/") {
return c.Redirect(c.URL().Path+"/", http.StatusFound)
}
type FishbowlData struct {
templates.BaseData
Contents template.HTML
}
indexFile := utils.Must1(fishbowlFS.Open(path.Join(c.PathParams["name"], "index.html")))
tmpl := FishbowlData{
BaseData: getBaseData(c, "TODOOP", nil),
Contents: template.HTML(utils.Must1(io.ReadAll(indexFile))),
}
var res ResponseData
err := res.WriteTemplate("fishbowl.html", tmpl, c.Perf)
if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to render fishbowl index page"))
}
return res
}
// This will skip the common path prefix for fishbowl files.
// We unfortunately need to do this because we want to use http.FileServer,
// but _that_ needs an http.FS, but _that_ needs an fs.FS, and embed.FS
// doesn't import fs.SubFS, which _would_ do what we want, so here we are. >:(
var fishbowlFS = utils.Must1(fs.Sub(templates.FishbowlFS, "src/fishbowls"))
var fishbowlHTTPFS = http.StripPrefix("/fishbowl", http.FileServer(http.FS(fishbowlFS)))
func FishbowlFiles(c *RequestContext) ResponseData {
var res ResponseData
fishbowlHTTPFS.ServeHTTP(&res, c.Req)
AddCORSHeaders(c, &res)
return res
}