2021-12-05 13:45:17 +00:00
|
|
|
package html
|
|
|
|
|
2023-11-16 17:11:35 +00:00
|
|
|
import (
|
|
|
|
_ "embed"
|
|
|
|
"net/http"
|
2024-11-17 16:28:52 +00:00
|
|
|
"os"
|
|
|
|
"path"
|
2023-11-16 17:11:35 +00:00
|
|
|
"text/template" // do not use html/template here, we sanitize the message before passing it to the template
|
2021-12-05 13:45:17 +00:00
|
|
|
|
2023-11-16 17:11:35 +00:00
|
|
|
"codeberg.org/codeberg/pages/server/context"
|
|
|
|
"github.com/microcosm-cc/bluemonday"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
)
|
2022-11-12 19:37:20 +00:00
|
|
|
|
2023-11-16 17:11:35 +00:00
|
|
|
//go:embed templates/error.html
|
|
|
|
var errorPage string
|
|
|
|
|
|
|
|
var (
|
2024-11-17 16:28:52 +00:00
|
|
|
errorTemplate = template.Must(template.New("error").Parse(loadCustomTemplateOrDefault()))
|
2023-11-16 17:11:35 +00:00
|
|
|
sanitizer = createBlueMondayPolicy()
|
|
|
|
)
|
|
|
|
|
|
|
|
type TemplateContext struct {
|
|
|
|
StatusCode int
|
|
|
|
StatusText string
|
|
|
|
Message string
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReturnErrorPage sets the response status code and writes the error page to the response body.
|
|
|
|
// The error page contains a sanitized version of the message and the statusCode both in text and numeric form.
|
|
|
|
//
|
|
|
|
// Currently, only the following html tags are supported: <code>
|
|
|
|
func ReturnErrorPage(ctx *context.Context, msg string, statusCode int) {
|
|
|
|
ctx.RespWriter.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
|
|
ctx.RespWriter.WriteHeader(statusCode)
|
|
|
|
|
|
|
|
templateContext := TemplateContext{
|
|
|
|
StatusCode: statusCode,
|
|
|
|
StatusText: http.StatusText(statusCode),
|
|
|
|
Message: sanitizer.Sanitize(msg),
|
|
|
|
}
|
|
|
|
|
|
|
|
err := errorTemplate.Execute(ctx.RespWriter, templateContext)
|
|
|
|
if err != nil {
|
|
|
|
log.Err(err).Str("message", msg).Int("status", statusCode).Msg("could not write response")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func createBlueMondayPolicy() *bluemonday.Policy {
|
|
|
|
p := bluemonday.NewPolicy()
|
|
|
|
|
|
|
|
p.AllowElements("code")
|
|
|
|
|
|
|
|
return p
|
|
|
|
}
|
2024-11-17 16:28:52 +00:00
|
|
|
|
|
|
|
func loadCustomTemplateOrDefault() string {
|
|
|
|
contents, err := os.ReadFile("custom/error.html")
|
|
|
|
if err != nil {
|
|
|
|
if !os.IsNotExist(err) {
|
|
|
|
wd, wdErr := os.Getwd()
|
|
|
|
if wdErr != nil {
|
|
|
|
log.Err(err).Msg("could not load custom error page 'custom/error.html'")
|
|
|
|
} else {
|
|
|
|
log.Err(err).Msgf("could not load custom error page '%v'", path.Join(wd, "custom/error.html"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errorPage
|
|
|
|
}
|
|
|
|
return string(contents)
|
|
|
|
}
|