diff --git a/README.md b/README.md index 0051a9e..4bcd393 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,15 @@ 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/flake.lock b/flake.lock index 90d377f..861cc42 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -20,8 +20,8 @@ "nixpkgs": { "locked": { "lastModified": 0, - "narHash": "sha256-8fnFlXBgM/uSvBlLWjZ0Z0sOdRBesyNdH0+esxqizGc=", - "path": "/nix/store/rqicl40jqw5d93l43s1xq0bm6yy0gpx4-source", + "narHash": "sha256-x07g4NcqGP6mQn6AISXJaks9sQYDjZmTMBlKIvajvyc=", + "path": "/nix/store/2w8kz6zh3aq80f1dypiin222fry1rv51-source", "type": "path" }, "original": { diff --git a/html/html.go b/html/html.go index ff8b6b4..ffede7f 100644 --- a/html/html.go +++ b/html/html.go @@ -3,6 +3,8 @@ package html import ( _ "embed" "net/http" + "os" + "path" "text/template" // do not use html/template here, we sanitize the message before passing it to the template "codeberg.org/codeberg/pages/server/context" @@ -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) +}