Skip to content

Commit

Permalink
Allow to set default error page (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
tarampampam authored Oct 6, 2021
1 parent 6b17d3e commit bb17027
Show file tree
Hide file tree
Showing 26 changed files with 719 additions and 560 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,11 @@ jobs: # Docs: <https://git.io/JvxXE>
- name: Wait for container "healthy" state
run: until [[ "`docker inspect -f {{.State.Health.Status}} app`" == "healthy" ]]; do echo "wait 1 sec.."; sleep 1; done

- run: curl --fail http://127.0.0.1:8080/
- run: curl --fail http://127.0.0.1:8080/500.html
- run: curl --fail http://127.0.0.1:8080/400.html
- run: curl --fail http://127.0.0.1:8080/health/live
- run: test $(curl --write-out %{http_code} --silent --output /dev/null http://127.0.0.1:8080/) -eq 404
- run: test $(curl --write-out %{http_code} --silent --output /dev/null http://127.0.0.1:8080/foobar) -eq 404

- name: Stop the container
if: always()
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this package will be documented in this file.

The format is based on [Keep a Changelog][keepachangelog] and this project adheres to [Semantic Versioning][semver].

## UNRELEASED

### Added

- `referer` field in access log records
- Flag `--default-error-page` for the `serve` subcommand (`404` is used by default, environment name `DEFAULT_ERROR_PAGE`)

### Changed

- The source code has been refactored
- The index page (`/`) now returns the error page with a code, declared using `--default-error-page` flag (HTTP code 200, when a page code exists)

## v2.0.0

### Changed
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ USER appuser:appuser
WORKDIR /opt

ENV LISTEN_PORT="8080" \
TEMPLATE_NAME="ghost"
TEMPLATE_NAME="ghost" \
DEFAULT_ERROR_PAGE="404"

# Docs: <https://docs.docker.com/engine/reference/builder/#healthcheck>
HEALTHCHECK --interval=7s --timeout=2s CMD [ \
Expand Down
70 changes: 50 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ Also, this project can be used for the [**Traefik** error pages customization](h

Download the latest binary file for your os/arch from the [releases page][link_releases] or use our docker image:

[![image stats](https://dockeri.co/image/tarampampam/error-pages)][link_docker_hub]

Registry | Image
-------------------------------------- | -----
[Docker Hub][link_docker_hub] | `tarampampam/error-pages`
Expand All @@ -56,13 +54,25 @@ $ docker run --rm -it \
</p>
</details>

## Templates

Name | Preview
:---------------: | :-----:
`ghost` | [![ghost](https://hsto.org/webt/oj/cl/4k/ojcl4ko_cvusy5xuki6efffzsyo.gif)](https://tarampampam.github.io/error-pages/ghost/404.html)
`l7-light` | [![l7-light](https://hsto.org/webt/xc/iq/vt/xciqvty-aoj-rchfarsjhutpjny.png)](https://tarampampam.github.io/error-pages/l7-light/404.html)
`l7-dark` | [![l7-dark](https://hsto.org/webt/s1/ih/yr/s1ihyrqs_y-sgraoimfhk6ypney.png)](https://tarampampam.github.io/error-pages/l7-dark/404.html)
`shuffle` | [![shuffle](https://hsto.org/webt/7w/rk/3m/7wrk3mrzz3y8qfqwovmuvacu-bs.gif)](https://tarampampam.github.io/error-pages/shuffle/404.html)
`noise` | [![noise](https://hsto.org/webt/42/oq/8y/42oq8yok_i-arrafjt6hds_7ahy.gif)](https://tarampampam.github.io/error-pages/noise/404.html)
`hacker-terminal` | [![hacker-terminal](https://hsto.org/webt/5s/l0/p1/5sl0p1_ud_nalzjzsj5slz6dfda.gif)](https://tarampampam.github.io/error-pages/hacker-terminal/404.html)

> Note: `noise` template highly uses the CPU, be careful
## Usage

All of the examples below will use a docker image with the application, but you can also use a binary. By the way, our docker image uses the **unleveled user** by default and **distroless**.

### HTTP server
<details>
<summary><strong>HTTP server</strong></summary>

As mentioned above - our application can be run as an HTTP server. It only needs to specify the path to the configuration file (it does not need statically generated error pages). The server uses [FastHTTP][fasthttp] and stores all necessary data in memory - so it does not use the file system and very fast. Oh yes, the image with the app also contains a configured **healthcheck** and **logs in JSON** format :)

Expand All @@ -86,8 +96,10 @@ To see the help run the following command:
```bash
$ docker run --rm tarampampam/error-pages serve --help
```
</details>

### Generator
<details>
<summary><strong>Generator</strong></summary>

Create a config file (`error-pages.yml`) with the following content:

Expand Down Expand Up @@ -158,13 +170,15 @@ To see the usage help run the following command:
```bash
$ docker run --rm tarampampam/error-pages build --help
```
</details>

### Static error pages
<details>
<summary><strong>Static error pages</strong></summary>

You may want to use the generated error pages somewhere else, and you can simply extract them from the docker image to your local directory for this purpose:

```bash
$ docker create --name error-pages tarampampam/error-pages:2.0.0-rc2
$ docker create --name error-pages tarampampam/error-pages
$ docker cp error-pages:/opt/html ./out
$ docker rm -f error-pages
$ ls ./out
Expand All @@ -187,7 +201,35 @@ $ tree
...
```

### Custom error pages for your image with [nginx][link_nginx]
Or inside another docker image:

```dockerfile
FROM alpine:latest
COPY --from=tarampampam/error-pages /opt/html /error-pages
RUN ls -l /error-pages
```

```bash
$ docker build --rm .
...
Step 3/3 : RUN ls -l /error-pages
---> Running in 30095dc344a9
total 12
drwxr-xr-x 2 root root 326 Sep 29 15:44 ghost
drwxr-xr-x 2 root root 326 Sep 29 15:44 hacker-terminal
-rw-r--r-- 1 root root 11241 Sep 29 15:44 index.html
drwxr-xr-x 2 root root 326 Sep 29 15:44 l7-dark
drwxr-xr-x 2 root root 326 Sep 29 15:44 l7-light
drwxr-xr-x 2 root root 326 Sep 29 15:44 noise
drwxr-xr-x 2 root root 326 Sep 29 15:44 shuffle
```
</details>

<details>
<summary><strong>Custom error pages for your image with nginx</strong></summary>

You can build your own docker image with `nginx` and our error pages:

Expand Down Expand Up @@ -234,19 +276,7 @@ $ docker build --tag your-nginx:local -f ./Dockerfile .
```

> More info about `error_page` directive can be [found here](http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page).
## Templates

Name | Preview
:---------------: | :-----:
`ghost` | [![ghost](https://hsto.org/webt/oj/cl/4k/ojcl4ko_cvusy5xuki6efffzsyo.gif)](https://tarampampam.github.io/error-pages/ghost/404.html)
`l7-light` | [![l7-light](https://hsto.org/webt/xc/iq/vt/xciqvty-aoj-rchfarsjhutpjny.png)](https://tarampampam.github.io/error-pages/l7-light/404.html)
`l7-dark` | [![l7-dark](https://hsto.org/webt/s1/ih/yr/s1ihyrqs_y-sgraoimfhk6ypney.png)](https://tarampampam.github.io/error-pages/l7-dark/404.html)
`shuffle` | [![shuffle](https://hsto.org/webt/7w/rk/3m/7wrk3mrzz3y8qfqwovmuvacu-bs.gif)](https://tarampampam.github.io/error-pages/shuffle/404.html)
`noise` | [![noise](https://hsto.org/webt/42/oq/8y/42oq8yok_i-arrafjt6hds_7ahy.gif)](https://tarampampam.github.io/error-pages/noise/404.html)
`hacker-terminal` | [![hacker-terminal](https://hsto.org/webt/5s/l0/p1/5sl0p1_ud_nalzjzsj5slz6dfda.gif)](https://tarampampam.github.io/error-pages/hacker-terminal/404.html)

> Note: `noise` template highly uses the CPU, be careful
</details>
## Custom error pages for [Traefik][link_traefik]

Expand Down
4 changes: 2 additions & 2 deletions internal/breaker/os_signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"syscall"
)

// OSSignals allows to subscribe for system signals.
// OSSignals allows subscribing for system signals.
type OSSignals struct {
ctx context.Context
ch chan os.Signal
Expand All @@ -22,7 +22,7 @@ func NewOSSignals(ctx context.Context) OSSignals {
}
}

// Subscribe for some of system signals (call Stop for stopping).
// Subscribe for some system signals (call Stop for stopping).
func (oss *OSSignals) Subscribe(onSignal func(os.Signal), signals ...os.Signal) {
if len(signals) == 0 {
signals = []os.Signal{os.Interrupt, syscall.SIGINT, syscall.SIGTERM} // default signals
Expand Down
45 changes: 23 additions & 22 deletions internal/cli/build/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type historyItem struct {
}

// NewCommand creates `build` command.
func NewCommand(log *zap.Logger, configFile *string) *cobra.Command { //nolint:funlen,gocognit
func NewCommand(log *zap.Logger, configFile *string) *cobra.Command { //nolint:funlen,gocognit,gocyclo
var (
generateIndex bool
cfg *config.Config
Expand Down Expand Up @@ -52,33 +52,34 @@ func NewCommand(log *zap.Logger, configFile *string) *cobra.Command { //nolint:f
return errors.New("wrong arguments count")
}

log.Info("loading templates")
errorPages := tpl.NewErrorPages()

templates, err := cfg.LoadTemplates()
if err != nil {
log.Info("loading templates")
if templates, err := cfg.LoadTemplates(); err == nil {
if len(templates) > 0 {
for templateName, content := range templates {
errorPages.AddTemplate(templateName, content)
}

for code, desc := range cfg.Pages {
errorPages.AddPage(code, desc.Message, desc.Description)
}
} else {
return errors.New("no loaded templates")
}
} else {
return err
} else if len(templates) == 0 {
return errors.New("no loaded templates")
}

log.Debug("the output directory preparing", zap.String("Path", args[0]))

if err = createDirectory(args[0]); err != nil {
if err := createDirectory(args[0]); err != nil {
return errors.Wrap(err, "cannot prepare output directory")
}

codes := make(map[string]tpl.Annotator)

for code, desc := range cfg.Pages {
codes[code] = tpl.Annotator{Message: desc.Message, Description: desc.Description}
}

history := make(map[string][]historyItem, len(templates))
history, startedAt := make(map[string][]historyItem), time.Now()

log.Info("saving the error pages")
startedAt := time.Now()

if err = tpl.NewErrors(templates, codes).VisitAll(func(template, code string, content []byte) error {
if err := errorPages.IteratePages(func(template, code string, content []byte) error {
if e := createDirectory(path.Join(args[0], template)); e != nil {
return e
}
Expand All @@ -90,18 +91,18 @@ func NewCommand(log *zap.Logger, configFile *string) *cobra.Command { //nolint:f
}

if _, ok := history[template]; !ok {
history[template] = make([]historyItem, 0, len(codes))
history[template] = make([]historyItem, 0, len(cfg.Pages))
}

history[template] = append(history[template], historyItem{
Code: code,
Message: codes[code].Message,
Message: cfg.Pages[code].Message,
Path: path.Join(template, fileName),
})

return nil
}); err != nil {
return nil
return err
}

log.Debug("saved", zap.Duration("duration", time.Since(startedAt)))
Expand All @@ -110,7 +111,7 @@ func NewCommand(log *zap.Logger, configFile *string) *cobra.Command { //nolint:f
log.Info("index file generation")
startedAt = time.Now()

if err = writeIndexFile(path.Join(args[0], "index.html"), history); err != nil {
if err := writeIndexFile(path.Join(args[0], "index.html"), history); err != nil {
return err
}

Expand Down
Loading

0 comments on commit bb17027

Please sign in to comment.