Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ The following templates are built-in and available for use without any additiona
[app-down-light]:https://github.com/user-attachments/assets/c5f42b53-51cd-47c4-a22f-553d44d2a288
[app-down-dark]:https://github.com/user-attachments/assets/135bac8c-983f-461c-97ba-e653e9b9adfe
[cats-link]:https://tarampampam.github.io/error-pages/cats/404.html
[cats-light]:https://github.com/tarampampam/error-pages/assets/7326800/056cd00e-bc9a-4120-8325-310d7b0ebd1b
[cats-dark]:https://github.com/tarampampam/error-pages/assets/7326800/5689880b-f770-406c-81dd-2d28629e6f2e
[cats-light]:https://github.com/user-attachments/assets/7bea967e-a427-4ba2-a3a3-d71b9986ecfc
[cats-dark]:https://github.com/user-attachments/assets/f9b945b2-3e19-44d5-842b-0c43c55d9b70
[connection-link]:https://tarampampam.github.io/error-pages/connection/404.html
[connection-light]:https://github.com/tarampampam/error-pages/assets/7326800/099ecc2d-e724-4d9c-b5ed-66ddabd71139
[connection-dark]:https://github.com/tarampampam/error-pages/assets/7326800/3f03dc1b-c1ee-4a91-b3d7-e3b93c79020e
Expand Down
11 changes: 11 additions & 0 deletions cmd/builder/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type App struct {
customTemplate string
l10nDisabled bool
homepageURL string
links []tpl.Link
}
}

Expand All @@ -60,6 +61,7 @@ func NewApp(name string) *App {
templateFlag = newTemplateFlag()
disableL10nFlag = shared.NewDisableL10nFlag()
homepageURLFlag = shared.NewHomepageURLFlag(app.opt.homepageURL)
addLinksFlag = shared.NewAddLinksFlag()
)

app.cmd.Flags = []cli.Flagger{
Expand All @@ -70,6 +72,7 @@ func NewApp(name string) *App {
&templateFlag,
&disableL10nFlag,
&homepageURLFlag,
&addLinksFlag,
}

app.cmd.Action = func(ctx context.Context, _ *cli.Command, _ []string) error {
Expand All @@ -89,6 +92,12 @@ func NewApp(name string) *App {
setIfFlagIsSet(&app.opt.customTemplate, templateFlag)
setIfFlagIsSet(&app.opt.homepageURL, homepageURLFlag)

if addLinksFlag.Value != nil && addLinksFlag.IsSet() {
if parsed, err := shared.ParseLinks(*addLinksFlag.Value); err == nil {
app.opt.links = parsed
}
}

// load custom template content if a source is provided (either URL, file path, or raw template string)
if src := app.opt.customTemplate; src != "" {
t, err := tploader.LoadTemplateContent(ctx, src)
Expand Down Expand Up @@ -194,6 +203,7 @@ func (a *App) renderCustomTemplate(httpCodes codes.Codes, history map[string][]h
Message: desc.Short,
Description: desc.Full,
HomepageURL: a.opt.homepageURL,
Links: a.opt.links,
Config: tpl.Config{L10nDisabled: a.opt.l10nDisabled},
})
if renderErr != nil {
Expand Down Expand Up @@ -254,6 +264,7 @@ func (a *App) renderBuiltInTemplates(httpCodes codes.Codes, history map[string][
Message: desc.Short,
Description: desc.Full,
HomepageURL: a.opt.homepageURL,
Links: a.opt.links,
Config: tpl.Config{L10nDisabled: a.opt.l10nDisabled},
})
if renderErr != nil {
Expand Down
12 changes: 12 additions & 0 deletions cmd/error-pages/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type App struct {
templateName string
rotationMode tpl.RotationMode
homepageURL string
links []tpl.Link
customTemplates struct {
html, json, xml, text string
}
Expand Down Expand Up @@ -88,6 +89,7 @@ func NewApp(name string) *App { //nolint:funlen
templateNameFlag = newTemplateNameFlag(allTemplateNames, app.opt.errorPages.templateName)
rotationModeFlag = newRotationModeFlag(app.opt.errorPages.rotationMode)
homepageURLFlag = shared.NewHomepageURLFlag(app.opt.errorPages.homepageURL)
addLinksFlag = shared.NewAddLinksFlag()
htmlTemplateFlag = newHTMLTemplateFlag()
jsonTemplateFlag = newJSONTemplateFlag()
xmlTemplateFlag = newXMLTemplateFlag()
Expand All @@ -109,6 +111,7 @@ func NewApp(name string) *App { //nolint:funlen
&templateNameFlag,
&rotationModeFlag,
&homepageURLFlag,
&addLinksFlag,
&htmlTemplateFlag,
&jsonTemplateFlag,
&xmlTemplateFlag,
Expand Down Expand Up @@ -155,6 +158,13 @@ func NewApp(name string) *App { //nolint:funlen
}

setIfFlagIsSet(&app.opt.errorPages.homepageURL, homepageURLFlag)

if addLinksFlag.Value != nil && addLinksFlag.IsSet() {
if parsed, err := shared.ParseLinks(*addLinksFlag.Value); err == nil {
app.opt.errorPages.links = parsed
}
}

setIfFlagIsSet(&app.opt.errorPages.customTemplates.html, htmlTemplateFlag)
setIfFlagIsSet(&app.opt.errorPages.customTemplates.json, jsonTemplateFlag)
setIfFlagIsSet(&app.opt.errorPages.customTemplates.xml, xmlTemplateFlag)
Expand Down Expand Up @@ -303,6 +313,7 @@ func (a *App) run(ctx context.Context, log *logger.Logger) error {
a.opt.errorPages.showDetails,
a.opt.errorPages.l10nDisabled,
a.opt.errorPages.homepageURL,
a.opt.errorPages.links,
),
httpserver.WithErrorLog(logger.NewStdLog(log, logger.ErrorLevel)),
)
Expand All @@ -320,6 +331,7 @@ func (a *App) run(ctx context.Context, log *logger.Logger) error {
logger.Bool("show_details", a.opt.errorPages.showDetails),
logger.Strings("proxy_headers", a.opt.errorPages.proxyHeaders...),
logger.String("homepage_url", a.opt.errorPages.homepageURL),
logger.Int("links_count", len(a.opt.errorPages.links)),
logger.Bool("l10n_disabled", a.opt.errorPages.l10nDisabled),
)

Expand Down
41 changes: 38 additions & 3 deletions deploy/helm/README.tpl.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,44 @@ Override descriptions or add non-standard codes (e.g. `499`, `4**` wildcard):

```yaml
config:
addCode: |
499=Client Closed Request|The client closed the connection before the server finished responding.
4**=Client Error|Something went wrong on the client side.
addCode:
- {code: "4**", message: "Client Error", description: "Something went wrong on the client side"}
- code: "499"
message: "Client Closed Request"
description: "The client closed the connection before the server finished responding"
```

Via `--set` (`--set-string` is required for numeric-looking codes like `499`):

```shell
helm install error-pages oci://ghcr.io/tarampampam/error-pages/charts/error-pages \
--set-string 'config.addCode[0].code=4**' \
--set 'config.addCode[0].message=Client Error' \
--set-string 'config.addCode[1].code=499' \
--set 'config.addCode[1].message=Client Closed Request' \
--set 'config.addCode[1].description=The client closed the connection before the server finished responding'
```

### Adding extra links

Display additional links (status page, contact, privacy policy, etc.) on all error pages:

```yaml
config:
addLink:
- {label: "Status Page", url: "https://status.example.com"}
- {label: "Contact Support", url: "https://example.com/contact"}
- {label: "Privacy Policy", url: "https://example.com/privacy"}
```

Via `--set`:

```shell
helm install error-pages oci://ghcr.io/tarampampam/error-pages/charts/error-pages \
--set 'config.addLink[0].label=Status Page' \
--set 'config.addLink[0].url=https://status.example.com' \
--set 'config.addLink[1].label=Contact Support' \
--set 'config.addLink[1].url=https://example.com/contact'
```

## 💊 Support
Expand Down
19 changes: 18 additions & 1 deletion deploy/helm/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,15 @@ spec:
- {name: DISABLE_BUILT_IN_CODES, value: "true"}
{{- end }}
{{- if .addCode }}
- {name: ADD_CODE, value: {{ .addCode | toJson }}}
{{- $parts := list -}}
{{- range .addCode -}}
{{- $e := printf "%s=%s" .code .message -}}
{{- if .description -}}{{- $e = printf "%s|%s" $e .description -}}{{- end -}}
{{- $parts = append $parts $e -}}
{{- end }}
- name: ADD_CODE
value: |
{{ join "\n" $parts | indent 16 }}
{{- end }}
{{- if .htmlTemplate.name }}
- {name: TEMPLATE_NAME, value: "{{ .htmlTemplate.name }}"}
Expand All @@ -101,6 +109,15 @@ spec:
{{- end }}
{{- if .homepageUrl }}
- {name: HOMEPAGE_URL, value: "{{ .homepageUrl }}"}
{{- end }}
{{- if .addLink }}
{{- $parts := list -}}
{{- range .addLink -}}
{{- $parts = append $parts (printf "%s=%s" .label .url) -}}
{{- end }}
- name: ADD_LINK
value: |
{{ join "\n" $parts | indent 16 }}
{{- end }}
{{- if .disableL10n }}
- {name: DISABLE_L10N, value: "true"}
Expand Down
31 changes: 30 additions & 1 deletion deploy/helm/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,19 @@
},
"addCode": {
"oneOf": [
{"type": "string", "minLength": 1, "examples": ["599=Custom Error|Something went wrong"]},
{
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {"type": "string", "minLength": 1},
"message": {"type": "string", "minLength": 1},
"description": {"type": "string", "minLength": 1}
},
"required": ["code", "message"],
"additionalProperties": false
}
},
{"type": "null"}
]
},
Expand Down Expand Up @@ -355,6 +367,23 @@
{"type": "null"}
]
},
"addLink": {
"oneOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {"type": "string", "minLength": 1},
"url": {"type": "string", "minLength": 1}
},
"required": ["label", "url"],
"additionalProperties": false
}
},
{"type": "null"}
]
},
"disableL10n": {
"oneOf": [
{"type": "boolean"},
Expand Down
8 changes: 5 additions & 3 deletions deploy/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,12 @@ config:
proxyHeaders: null
# -- (bool/null) Disable built-in HTTP status code descriptions
disableBuiltInCodes: null
# -- (string/null) Add or override HTTP status codes. Format: `CODE=MESSAGE[\|DESCRIPTION]` (`CODE` supports wildcards like `4**`).
# Separate multiple entries with newlines
# -- ([]object/null) Add or override HTTP status codes. Each entry must have `code` and `message` (required), and
# optionally `description`. `code` supports wildcards like `4**`.
# @default -- *all built-in codes*
addCode: null
addCode: null # Array<{code: string, message: string, description?: string}>
# -- ([]object/null) Extra links to display on error pages. Each entry must have `label` and `url` (both required).
addLink: null # Array<{label: string, url: string}>

htmlTemplate:
# -- (string/null) Built-in HTML template name (**ignored when `custom` is set**).
Expand Down
21 changes: 21 additions & 0 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Options:
--template-name="…" Name of the built-in HTML template to use (app-down/cats/connection/ghost/hacker-terminal/l7/lost-in-space/noise/orient/shuffle/win98; ignored if a custom HTML template is set) (default: app-down) [$TEMPLATE_NAME, $HTML_TEMPLATE_NAME]
--rotation-mode="…" Mode for rotating built-in HTML templates (disabled/random-on-startup/random-on-each-request/random-hourly/random-daily; ignored if a custom HTML template is set) (default: disabled) [$ROTATION_MODE]
--homepage-url="…" Homepage URL to show as a link in error pages (e.g. https://app.example.com/home) (default: /) [$HOMEPAGE_URL]
--add-link="…" Add extra links to error pages (format: 'LABEL=URL[||LABEL=URL...]'; separate multiple entries with '||', a newline, or a tab) [$ADD_LINK]
--html-template="…" Custom HTML template for error page responses (template text/URL/file path) [$HTML_TEMPLATE, $TEMPLATE]
--json-template="…" Custom JSON template for error page responses (template text/URL/file path) [$JSON_TEMPLATE]
--xml-template="…" Custom XML template for error page responses (template text/URL/file path) [$XML_TEMPLATE]
Expand Down Expand Up @@ -109,6 +110,17 @@ ADD_CODE="418=I'm a teapot|Short and stout
499=Client Closed Request|The client closed the connection"
```

### Adding extra links

Add custom, labeled links (e.g. status page, contact, policy) to be displayed on every error page. Format: `LABEL=URL`.

```bash
# multiple links separated by || or newlines
error-pages --add-link "Status Page=https://status.example.com||Contact=https://example.com/contact"
```

URLs may contain `=` signs - only the first `=` in each entry is used as the separator.

## Templates builder

<!--GENERATED:BUILDER_CLI-->
Expand All @@ -130,6 +142,7 @@ Options:
--template="…" Custom template for error pages [$TEMPLATE]
--disable-l10n Disable localization of error pages (if the template supports localization) [$DISABLE_L10N]
--homepage-url="…" Homepage URL to show as a link in error pages (e.g. https://app.example.com/home) [$HOMEPAGE_URL]
--add-link="…" Add extra links to error pages (format: 'LABEL=URL[||LABEL=URL...]'; separate multiple entries with '||', a newline, or a tab) [$ADD_LINK]
--help, -h Show help
--version, -v Print the version
```
Expand Down Expand Up @@ -181,3 +194,11 @@ builder --out ./error-pages --index
├── 404.html
└── ...
```

### Adding extra links

The `--add-link` flag works the same way as in the HTTP server - see [Adding extra links](#adding-extra-links) above.

```bash
builder --add-link "Status Page=https://status.example.com||Contact=https://example.com/contact" --out ./error-pages
```
24 changes: 21 additions & 3 deletions docs/templating.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,30 @@ All templates receive a data object with the following fields:
| `.RequestID` | `string` | Unique request ID * |
| `.ForwardedFor` | `string` | Original client IP(s) from `X-Forwarded-For` * |
| `.Host` | `string` | Request `Host` header * |
| `.HomepageURL` | `string` | Homepage URL set via `--homepage-url` (empty if not configured) |
| `.Config.ShowRequestDetails` | `bool` | Whether `--show-details` is enabled |
| `.Config.L10nDisabled` | `bool` | Whether `--disable-l10n` is set |
| `.HomepageURL` | `string` | Homepage URL set via `--homepage-url` (empty if not configured) |
| `.Links` | `[]Link` | Extra links set via `--add-link` (empty slice if not configured) |
| `.Config.ShowRequestDetails` | `bool` | Whether `--show-details` is enabled |
| `.Config.L10nDisabled` | `bool` | Whether `--disable-l10n` is set |

> `*` - Requires `--show-details`

Each element of `.Links` has the following sub-fields:

| Sub-field | Type | Description |
|---------------|----------|-----------------------|
| `.Label` | `string` | Link text |
| `.URL` | `string` | Target URL |

Example usage in a custom template:

```html
{{ if .Links }}
<nav>
{{ range .Links }}<a href="{{ .URL }}">{{ .Label }}</a>{{ end }}
</nav>
{{ end }}
```

In addition to the fields above, templates also have access to a set of built-in functions (see below), which are
pipeline-friendly (needle before haystack): `{{ .Message | default "Unknown" | upper }}`.

Expand Down
Loading