diff --git a/README.md b/README.md index 0051a9e..7b73bb4 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,14 @@ This will trigger a build of the PR which will build a docker image to be used f - `PAGES_DOMAIN` (default: `codeberg.page`): main domain for pages. - `RAW_DOMAIN` (default: `raw.codeberg.page`): domain for raw resources (must be subdomain of `PAGES_DOMAIN`). +### Custom Error Page + +A custom error page template can be served by creating `custom/error.html`. +Data available to the template includes: +- `{{ .StatusCode }}`: The HTTP status code (e.g. 404) +- `{{ .StatusText }}`: The textual name associated with the status code (e.g. Not Found) +- `{{ .Message }}`: The reason for the error + ## Contributing to the development The Codeberg team is very open to your contribution. diff --git a/html/html.go b/html/html.go index ff8b6b4..8b34e9f 100644 --- a/html/html.go +++ b/html/html.go @@ -4,6 +4,8 @@ import ( _ "embed" "net/http" "text/template" // do not use html/template here, we sanitize the message before passing it to the template + "os" + "path" "codeberg.org/codeberg/pages/server/context" "github.com/microcosm-cc/bluemonday" @@ -14,7 +16,7 @@ import ( var errorPage string var ( - errorTemplate = template.Must(template.New("error").Parse(errorPage)) + errorTemplate = template.Must(template.New("error").Parse(loadCustomTemplateOrDefault())) sanitizer = createBlueMondayPolicy() ) @@ -51,3 +53,19 @@ func createBlueMondayPolicy() *bluemonday.Policy { return p } + +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) +}