mirror of
https://github.com/tarampampam/error-pages.git
synced 2024-08-30 18:22:40 +00:00
wip: 🔕 temporary commit
This commit is contained in:
parent
b7228c3933
commit
14815b4c73
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
# Docs: <https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/customizing-dependency-updates>
|
# yaml-language-server: $schema=https://json.schemastore.org/dependabot-2.0.json
|
||||||
|
# docs: https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/customizing-dependency-updates
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
|
13
.github/release.yml
vendored
Normal file
13
.github/release.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# yaml-language-server: $schema=https://json.schemastore.org/github-release-config.json
|
||||||
|
# docs: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
categories:
|
||||||
|
- title: 🛠 Fixes
|
||||||
|
labels: [type:fix, type:bug]
|
||||||
|
- title: 🚀 Features
|
||||||
|
labels: [type:feature, type:feature_request]
|
||||||
|
- title: 📦 Dependency updates
|
||||||
|
labels: [dependencies]
|
||||||
|
- title: Other Changes
|
||||||
|
labels: ['*']
|
10
.github/workflows/dependabot.yml
vendored
10
.github/workflows/dependabot.yml
vendored
@ -1,4 +1,7 @@
|
|||||||
name: dependabot
|
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||||
|
# docs: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
|
||||||
|
name: 🤖 Dependabot
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request: {}
|
pull_request: {}
|
||||||
@ -9,6 +12,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
dependabot: # https://tinyurl.com/e69djmen
|
dependabot: # https://tinyurl.com/e69djmen
|
||||||
|
name: Enable auto-merge for Dependabot PRs
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.actor == 'dependabot[bot]' }}
|
if: ${{ github.actor == 'dependabot[bot]' }}
|
||||||
steps:
|
steps:
|
||||||
@ -16,10 +20,8 @@ jobs:
|
|||||||
id: metadata
|
id: metadata
|
||||||
with: {github-token: "${{ secrets.GITHUB_TOKEN }}"}
|
with: {github-token: "${{ secrets.GITHUB_TOKEN }}"}
|
||||||
|
|
||||||
- name: Enable auto-merge for Dependabot PRs
|
- if: ${{ contains(fromJSON('["version-update:semver-minor", "version-update:semver-patch"]'), steps.metadata.outputs.update-type) }}
|
||||||
if: ${{ contains(fromJSON('["version-update:semver-minor", "version-update:semver-patch"]'), steps.metadata.outputs.update-type) }}
|
|
||||||
run: gh pr merge --auto --merge "$PR_URL"
|
run: gh pr merge --auto --merge "$PR_URL"
|
||||||
continue-on-error: true
|
|
||||||
env:
|
env:
|
||||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
7
.github/workflows/documentation.yml
vendored
7
.github/workflows/documentation.yml
vendored
@ -1,4 +1,7 @@
|
|||||||
name: documentation
|
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||||
|
# docs: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
|
||||||
|
name: 📚 Documentation
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -12,7 +15,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: peter-evans/dockerhub-description@v4 # Action page: <https://github.com/peter-evans/dockerhub-description>
|
- uses: peter-evans/dockerhub-description@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_LOGIN }}
|
username: ${{ secrets.DOCKER_LOGIN }}
|
||||||
password: ${{ secrets.DOCKER_USER_PASSWORD }}
|
password: ${{ secrets.DOCKER_USER_PASSWORD }}
|
||||||
|
217
.github/workflows/release.yml
vendored
217
.github/workflows/release.yml
vendored
@ -1,113 +1,122 @@
|
|||||||
name: release
|
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||||
|
# docs: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
|
||||||
|
name: 🚀 Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release: # Docs: <https://git.io/JeBz1#release-event-release>
|
release: # Docs: <https://git.io/JeBz1#release-event-release>
|
||||||
types: [published]
|
types: [published]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
purge-cdn-cache:
|
wip:
|
||||||
name: Purge jsDelivr CDN cache
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: gacts/purge-jsdelivr-cache@v1 # Action page: <https://github.com/gacts/purge-jsdelivr-cache>
|
- run: echo WIP
|
||||||
with:
|
|
||||||
url: |
|
|
||||||
https://cdn.jsdelivr.net/gh/tarampampam/error-pages@2/l10n/l10n.js
|
|
||||||
https://cdn.jsdelivr.net/gh/tarampampam/error-pages@2/l10n/l10n.min.js
|
|
||||||
https://cdn.jsdelivr.net/gh/tarampampam/error-pages@latest/l10n/l10n.js
|
|
||||||
https://cdn.jsdelivr.net/gh/tarampampam/error-pages@latest/l10n/l10n.min.js
|
|
||||||
|
|
||||||
build:
|
#jobs:
|
||||||
name: Build for ${{ matrix.os }} (${{ matrix.arch }})
|
# purge-cdn-cache:
|
||||||
runs-on: ubuntu-latest
|
# name: Purge jsDelivr CDN cache
|
||||||
strategy:
|
# runs-on: ubuntu-latest
|
||||||
fail-fast: false
|
# steps:
|
||||||
matrix:
|
# - uses: gacts/purge-jsdelivr-cache@v1 # Action page: <https://github.com/gacts/purge-jsdelivr-cache>
|
||||||
os: [linux, darwin] # linux, freebsd, darwin, windows
|
# with:
|
||||||
arch: [amd64] # amd64, 386
|
# url: |
|
||||||
steps:
|
# https://cdn.jsdelivr.net/gh/tarampampam/error-pages@2/l10n/l10n.js
|
||||||
- uses: actions/checkout@v4
|
# https://cdn.jsdelivr.net/gh/tarampampam/error-pages@2/l10n/l10n.min.js
|
||||||
|
# https://cdn.jsdelivr.net/gh/tarampampam/error-pages@latest/l10n/l10n.js
|
||||||
- uses: gacts/setup-go-with-cache@v1
|
# https://cdn.jsdelivr.net/gh/tarampampam/error-pages@latest/l10n/l10n.min.js
|
||||||
with: {go-version-file: go.mod}
|
#
|
||||||
|
# build:
|
||||||
- {uses: gacts/github-slug@v1, id: slug}
|
# name: Build for ${{ matrix.os }} (${{ matrix.arch }})
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
- name: Generate builder values
|
# strategy:
|
||||||
id: values
|
# fail-fast: false
|
||||||
run: echo "binary-name=error-pages-${{ matrix.os }}-${{ matrix.arch }}" >> $GITHUB_OUTPUT
|
# matrix:
|
||||||
|
# os: [linux, darwin] # linux, freebsd, darwin, windows
|
||||||
- name: Build application
|
# arch: [amd64] # amd64, 386
|
||||||
env:
|
# steps:
|
||||||
GOOS: ${{ matrix.os }}
|
# - uses: actions/checkout@v4
|
||||||
GOARCH: ${{ matrix.arch }}
|
#
|
||||||
CGO_ENABLED: 0
|
# - uses: gacts/setup-go-with-cache@v1
|
||||||
LDFLAGS: -s -w -X gh.tarampamp.am/error-pages/internal/version.version=${{ steps.slug.outputs.version }}
|
# with: {go-version-file: go.mod}
|
||||||
run: go build -trimpath -ldflags "$LDFLAGS" -o "./${{ steps.values.outputs.binary-name }}" ./cmd/error-pages/
|
#
|
||||||
|
# - {uses: gacts/github-slug@v1, id: slug}
|
||||||
- name: Upload binary file to release
|
#
|
||||||
uses: svenstaro/upload-release-action@v2
|
# - name: Generate builder values
|
||||||
with:
|
# id: values
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
# run: echo "binary-name=error-pages-${{ matrix.os }}-${{ matrix.arch }}" >> $GITHUB_OUTPUT
|
||||||
file: ${{ steps.values.outputs.binary-name }}
|
#
|
||||||
asset_name: ${{ steps.values.outputs.binary-name }}
|
# - name: Build application
|
||||||
tag: ${{ github.ref }}
|
# env:
|
||||||
|
# GOOS: ${{ matrix.os }}
|
||||||
docker-image:
|
# GOARCH: ${{ matrix.arch }}
|
||||||
name: Build docker image
|
# CGO_ENABLED: 0
|
||||||
runs-on: ubuntu-latest
|
# LDFLAGS: -s -w -X gh.tarampamp.am/error-pages/internal/version.version=${{ steps.slug.outputs.version }}
|
||||||
steps:
|
# run: go build -trimpath -ldflags "$LDFLAGS" -o "./${{ steps.values.outputs.binary-name }}" ./cmd/error-pages/
|
||||||
- uses: actions/checkout@v4
|
#
|
||||||
|
# - name: Upload binary file to release
|
||||||
- {uses: gacts/github-slug@v1, id: slug}
|
# uses: svenstaro/upload-release-action@v2
|
||||||
|
# with:
|
||||||
- uses: docker/setup-qemu-action@v3 # Action page: <https://github.com/docker/setup-qemu-action>
|
# repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# file: ${{ steps.values.outputs.binary-name }}
|
||||||
- uses: docker/setup-buildx-action@v3 # Action page: <https://github.com/docker/setup-buildx-action>
|
# asset_name: ${{ steps.values.outputs.binary-name }}
|
||||||
|
# tag: ${{ github.ref }}
|
||||||
- uses: docker/login-action@v3 # Action page: <https://github.com/docker/login-action>
|
#
|
||||||
with:
|
# docker-image:
|
||||||
username: ${{ secrets.DOCKER_LOGIN }}
|
# name: Build docker image
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
# runs-on: ubuntu-latest
|
||||||
|
# steps:
|
||||||
- uses: docker/login-action@v3 # Action page: <https://github.com/docker/login-action>
|
# - uses: actions/checkout@v4
|
||||||
with:
|
#
|
||||||
registry: ghcr.io
|
# - {uses: gacts/github-slug@v1, id: slug}
|
||||||
username: ${{ github.actor }}
|
#
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
# - uses: docker/setup-qemu-action@v3 # Action page: <https://github.com/docker/setup-qemu-action>
|
||||||
|
#
|
||||||
- uses: docker/build-push-action@v5 # Action page: <https://github.com/docker/build-push-action>
|
# - uses: docker/setup-buildx-action@v3 # Action page: <https://github.com/docker/setup-buildx-action>
|
||||||
with:
|
#
|
||||||
context: .
|
# - uses: docker/login-action@v3 # Action page: <https://github.com/docker/login-action>
|
||||||
file: Dockerfile
|
# with:
|
||||||
push: true
|
# username: ${{ secrets.DOCKER_LOGIN }}
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm64/v8
|
# password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
build-args: "APP_VERSION=${{ steps.slug.outputs.version }}"
|
#
|
||||||
tags: |
|
# - uses: docker/login-action@v3 # Action page: <https://github.com/docker/login-action>
|
||||||
tarampampam/error-pages:${{ steps.slug.outputs.version }}
|
# with:
|
||||||
tarampampam/error-pages:${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}
|
# registry: ghcr.io
|
||||||
tarampampam/error-pages:${{ steps.slug.outputs.version-major }}
|
# username: ${{ github.actor }}
|
||||||
tarampampam/error-pages:latest
|
# password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:${{ steps.slug.outputs.version }}
|
#
|
||||||
ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}
|
# - uses: docker/build-push-action@v5 # Action page: <https://github.com/docker/build-push-action>
|
||||||
ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:${{ steps.slug.outputs.version-major }}
|
# with:
|
||||||
ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:latest
|
# context: .
|
||||||
|
# file: Dockerfile
|
||||||
demo:
|
# push: true
|
||||||
name: Update the demonstration
|
# platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm64/v8
|
||||||
runs-on: ubuntu-latest
|
# build-args: "APP_VERSION=${{ steps.slug.outputs.version }}"
|
||||||
needs: [docker-image]
|
# tags: |
|
||||||
steps:
|
# tarampampam/error-pages:${{ steps.slug.outputs.version }}
|
||||||
- {uses: gacts/github-slug@v1, id: slug}
|
# tarampampam/error-pages:${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}
|
||||||
|
# tarampampam/error-pages:${{ steps.slug.outputs.version-major }}
|
||||||
- name: Take rendered templates from the built docker image
|
# tarampampam/error-pages:latest
|
||||||
run: |
|
# ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:${{ steps.slug.outputs.version }}
|
||||||
docker create --name img ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:${{ steps.slug.outputs.version }}
|
# ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}
|
||||||
docker cp img:/opt/html ./out
|
# ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:${{ steps.slug.outputs.version-major }}
|
||||||
docker rm -f img
|
# ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:latest
|
||||||
|
#
|
||||||
- name: Deploy to GitHub Pages
|
# demo:
|
||||||
uses: peaceiris/actions-gh-pages@v4
|
# name: Update the demonstration
|
||||||
with:
|
# runs-on: ubuntu-latest
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
# needs: [docker-image]
|
||||||
publish_dir: ./out
|
# steps:
|
||||||
|
# - {uses: gacts/github-slug@v1, id: slug}
|
||||||
|
#
|
||||||
|
# - name: Take rendered templates from the built docker image
|
||||||
|
# run: |
|
||||||
|
# docker create --name img ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}:${{ steps.slug.outputs.version }}
|
||||||
|
# docker cp img:/opt/html ./out
|
||||||
|
# docker rm -f img
|
||||||
|
#
|
||||||
|
# - name: Deploy to GitHub Pages
|
||||||
|
# uses: peaceiris/actions-gh-pages@v4
|
||||||
|
# with:
|
||||||
|
# github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# publish_dir: ./out
|
||||||
|
366
.github/workflows/tests.yml
vendored
366
.github/workflows/tests.yml
vendored
@ -1,4 +1,7 @@
|
|||||||
name: tests
|
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||||
|
# docs: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
|
||||||
|
name: 🧪 Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -12,224 +15,177 @@ concurrency:
|
|||||||
group: ${{ github.ref }}
|
group: ${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs: # Docs: <https://git.io/JvxXE>
|
jobs:
|
||||||
gitleaks:
|
gitleaks:
|
||||||
name: Gitleaks
|
name: Check for GitLeaks
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- {uses: actions/checkout@v4, with: {fetch-depth: 0}}
|
||||||
with: {fetch-depth: 0}
|
- uses: gacts/gitleaks@v1
|
||||||
|
|
||||||
- name: Check for GitLeaks
|
|
||||||
uses: gacts/gitleaks@v1 # Action page: <https://github.com/gacts/gitleaks>
|
|
||||||
|
|
||||||
golangci-lint:
|
golangci-lint:
|
||||||
name: Golang-CI (lint)
|
name: Run golangci-lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- {uses: actions/setup-go@v5, with: {go-version-file: go.mod}}
|
||||||
- uses: gacts/setup-go-with-cache@v1
|
|
||||||
with: {go-version-file: go.mod}
|
|
||||||
|
|
||||||
- uses: golangci/golangci-lint-action@v6
|
- uses: golangci/golangci-lint-action@v6
|
||||||
with: {skip-pkg-cache: true, skip-build-cache: true}
|
|
||||||
|
|
||||||
validate-config-file:
|
|
||||||
name: Validate config file
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- {uses: actions/setup-node@v4, with: {node-version: 16}}
|
|
||||||
|
|
||||||
- name: Install linter
|
|
||||||
run: npm install -g ajv-cli # Package page: <https://www.npmjs.com/package/ajv-cli>
|
|
||||||
|
|
||||||
- name: Run linter
|
|
||||||
run: ajv validate --all-errors --verbose -s ./schemas/config/1.0.schema.json -d ./error-pages.y*ml
|
|
||||||
|
|
||||||
lint-l10n:
|
|
||||||
name: Lint l10n file(s)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- {uses: actions/setup-node@v4, with: {node-version: 16}}
|
|
||||||
|
|
||||||
- name: Install eslint
|
|
||||||
run: npm install -g eslint@v8 # Package page: <https://www.npmjs.com/package/eslint>
|
|
||||||
|
|
||||||
- name: Run linter
|
|
||||||
working-directory: l10n
|
|
||||||
run: eslint ./*.js
|
|
||||||
|
|
||||||
go-test:
|
go-test:
|
||||||
name: Unit tests
|
name: Unit tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: {fetch-depth: 2} # Fixes codecov error 'Issue detecting commit SHA'
|
- {uses: actions/setup-go@v5, with: {go-version-file: go.mod}}
|
||||||
|
- run: go test -race ./...
|
||||||
|
|
||||||
- uses: gacts/setup-go-with-cache@v1
|
# build:
|
||||||
with: {go-version-file: go.mod}
|
# name: Build for ${{ matrix.os }} (${{ matrix.arch }})
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# strategy:
|
||||||
|
# fail-fast: false
|
||||||
|
# matrix:
|
||||||
|
# os: [linux, darwin] # linux, freebsd, darwin, windows
|
||||||
|
# arch: [amd64] # amd64, 386
|
||||||
|
# needs: [golangci-lint, go-test, validate-config-file]
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v4
|
||||||
|
#
|
||||||
|
# - uses: gacts/setup-go-with-cache@v1
|
||||||
|
# with: {go-version-file: go.mod}
|
||||||
|
#
|
||||||
|
# - {uses: gacts/github-slug@v1, id: slug}
|
||||||
|
#
|
||||||
|
# - name: Build application
|
||||||
|
# env:
|
||||||
|
# GOOS: ${{ matrix.os }}
|
||||||
|
# GOARCH: ${{ matrix.arch }}
|
||||||
|
# CGO_ENABLED: 0
|
||||||
|
# LDFLAGS: -s -w -X gh.tarampamp.am/error-pages/internal/version.version=${{ steps.slug.outputs.branch-name-slug }}@${{ steps.slug.outputs.commit-hash-short }}
|
||||||
|
# run: go build -trimpath -ldflags "$LDFLAGS" -o ./error-pages ./cmd/error-pages/
|
||||||
|
#
|
||||||
|
# - name: Try to execute
|
||||||
|
# if: matrix.os == 'linux'
|
||||||
|
# run: ./error-pages --version && ./error-pages -h
|
||||||
|
#
|
||||||
|
# - uses: actions/upload-artifact@v4
|
||||||
|
# with:
|
||||||
|
# name: error-pages-${{ matrix.os }}-${{ matrix.arch }}
|
||||||
|
# path: error-pages
|
||||||
|
# if-no-files-found: error
|
||||||
|
# retention-days: 1
|
||||||
|
|
||||||
- name: Run Unit tests
|
# generate:
|
||||||
run: go test -race -covermode=atomic -coverprofile /tmp/coverage.txt ./...
|
# name: Run templates generator
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
- uses: codecov/codecov-action@v4 # https://github.com/codecov/codecov-action
|
# needs: [build]
|
||||||
continue-on-error: true
|
# steps:
|
||||||
with:
|
# - uses: actions/checkout@v4
|
||||||
file: /tmp/coverage.txt
|
#
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
# - uses: actions/download-artifact@v4
|
||||||
|
# with:
|
||||||
build:
|
# name: error-pages-linux-amd64
|
||||||
name: Build for ${{ matrix.os }} (${{ matrix.arch }})
|
# path: .artifact
|
||||||
runs-on: ubuntu-latest
|
#
|
||||||
strategy:
|
# - name: Prepare binary file to run
|
||||||
fail-fast: false
|
# working-directory: .artifact
|
||||||
matrix:
|
# run: mv ./error-pages ./../error-pages && chmod +x ./../error-pages
|
||||||
os: [linux, darwin] # linux, freebsd, darwin, windows
|
#
|
||||||
arch: [amd64] # amd64, 386
|
# - name: Run generator
|
||||||
needs: [golangci-lint, go-test, validate-config-file]
|
# run: ./error-pages --verbose build --index ./out
|
||||||
steps:
|
#
|
||||||
- uses: actions/checkout@v4
|
# - name: Test files creation
|
||||||
|
# run: |
|
||||||
- uses: gacts/setup-go-with-cache@v1
|
# test -f ./out/index.html
|
||||||
with: {go-version-file: go.mod}
|
# test -f ./out/ghost/404.html
|
||||||
|
# test -f ./out/l7-dark/404.html
|
||||||
- {uses: gacts/github-slug@v1, id: slug}
|
# test -f ./out/l7-light/404.html
|
||||||
|
# test -f ./out/shuffle/404.html
|
||||||
- name: Build application
|
# test -f ./out/noise/404.html
|
||||||
env:
|
# test -f ./out/hacker-terminal/404.html
|
||||||
GOOS: ${{ matrix.os }}
|
# test -f ./out/cats/404.html
|
||||||
GOARCH: ${{ matrix.arch }}
|
# test -f ./out/lost-in-space/404.html
|
||||||
CGO_ENABLED: 0
|
# test -f ./out/app-down/404.html
|
||||||
LDFLAGS: -s -w -X gh.tarampamp.am/error-pages/internal/version.version=${{ steps.slug.outputs.branch-name-slug }}@${{ steps.slug.outputs.commit-hash-short }}
|
# test -f ./out/connection/404.html
|
||||||
run: go build -trimpath -ldflags "$LDFLAGS" -o ./error-pages ./cmd/error-pages/
|
# test -f ./out/matrix/404.html
|
||||||
|
# test -f ./out/orient/404.html
|
||||||
- name: Try to execute
|
#
|
||||||
if: matrix.os == 'linux'
|
# docker-image:
|
||||||
run: ./error-pages --version && ./error-pages -h
|
# name: Build docker image
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
- uses: actions/upload-artifact@v4
|
# needs: [golangci-lint, go-test, validate-config-file]
|
||||||
with:
|
# steps:
|
||||||
name: error-pages-${{ matrix.os }}-${{ matrix.arch }}
|
# - uses: actions/checkout@v4
|
||||||
path: error-pages
|
#
|
||||||
if-no-files-found: error
|
# - {uses: gacts/github-slug@v1, id: slug}
|
||||||
retention-days: 1
|
#
|
||||||
|
# - uses: docker/build-push-action@v5 # Action page: <https://github.com/docker/build-push-action>
|
||||||
generate:
|
# with:
|
||||||
name: Run templates generator
|
# context: .
|
||||||
runs-on: ubuntu-latest
|
# file: Dockerfile
|
||||||
needs: [build]
|
# push: false
|
||||||
steps:
|
# build-args: "APP_VERSION=${{ steps.slug.outputs.branch-name-slug }}@${{ steps.slug.outputs.commit-hash-short }}"
|
||||||
- uses: actions/checkout@v4
|
# tags: app:ci
|
||||||
|
#
|
||||||
- uses: actions/download-artifact@v4
|
# - run: docker save app:ci > ./docker-image.tar
|
||||||
with:
|
#
|
||||||
name: error-pages-linux-amd64
|
# - uses: actions/upload-artifact@v4
|
||||||
path: .artifact
|
# with:
|
||||||
|
# name: docker-image
|
||||||
- name: Prepare binary file to run
|
# path: ./docker-image.tar
|
||||||
working-directory: .artifact
|
# retention-days: 1
|
||||||
run: mv ./error-pages ./../error-pages && chmod +x ./../error-pages
|
#
|
||||||
|
# scan-docker-image:
|
||||||
- name: Run generator
|
# name: Scan the docker image
|
||||||
run: ./error-pages --verbose build --index ./out
|
# runs-on: ubuntu-latest
|
||||||
|
# needs: [docker-image]
|
||||||
- name: Test files creation
|
# steps:
|
||||||
run: |
|
# - uses: actions/checkout@v4 # is needed for `upload-sarif` action
|
||||||
test -f ./out/index.html
|
#
|
||||||
test -f ./out/ghost/404.html
|
# - uses: actions/download-artifact@v4
|
||||||
test -f ./out/l7-dark/404.html
|
# with:
|
||||||
test -f ./out/l7-light/404.html
|
# name: docker-image
|
||||||
test -f ./out/shuffle/404.html
|
# path: .artifact
|
||||||
test -f ./out/noise/404.html
|
#
|
||||||
test -f ./out/hacker-terminal/404.html
|
# - uses: aquasecurity/trivy-action@0.21.0 # action page: <https://github.com/aquasecurity/trivy-action>
|
||||||
test -f ./out/cats/404.html
|
# with:
|
||||||
test -f ./out/lost-in-space/404.html
|
# input: .artifact/docker-image.tar
|
||||||
test -f ./out/app-down/404.html
|
# format: sarif
|
||||||
test -f ./out/connection/404.html
|
# severity: MEDIUM,HIGH,CRITICAL
|
||||||
test -f ./out/matrix/404.html
|
# exit-code: 1
|
||||||
test -f ./out/orient/404.html
|
# output: trivy-results.sarif
|
||||||
|
#
|
||||||
docker-image:
|
# - uses: github/codeql-action/upload-sarif@v3
|
||||||
name: Build docker image
|
# if: always()
|
||||||
runs-on: ubuntu-latest
|
# continue-on-error: true
|
||||||
needs: [golangci-lint, go-test, validate-config-file]
|
# with: {sarif_file: trivy-results.sarif}
|
||||||
steps:
|
#
|
||||||
- uses: actions/checkout@v4
|
# poke-docker-image:
|
||||||
|
# name: Run the docker image
|
||||||
- {uses: gacts/github-slug@v1, id: slug}
|
# runs-on: ubuntu-latest
|
||||||
|
# needs: [docker-image]
|
||||||
- uses: docker/build-push-action@v5 # Action page: <https://github.com/docker/build-push-action>
|
# timeout-minutes: 2
|
||||||
with:
|
# steps:
|
||||||
context: .
|
# - uses: actions/checkout@v4
|
||||||
file: Dockerfile
|
#
|
||||||
push: false
|
# - uses: actions/download-artifact@v4
|
||||||
build-args: "APP_VERSION=${{ steps.slug.outputs.branch-name-slug }}@${{ steps.slug.outputs.commit-hash-short }}"
|
# with:
|
||||||
tags: app:ci
|
# name: docker-image
|
||||||
|
# path: .artifact
|
||||||
- run: docker save app:ci > ./docker-image.tar
|
#
|
||||||
|
# - working-directory: .artifact
|
||||||
- uses: actions/upload-artifact@v4
|
# run: docker load < docker-image.tar
|
||||||
with:
|
#
|
||||||
name: docker-image
|
# - uses: gacts/install-hurl@v1
|
||||||
path: ./docker-image.tar
|
#
|
||||||
retention-days: 1
|
# - name: Run container with the app
|
||||||
|
# run: docker run --rm -d -p "8080:8080/tcp" -e "SHOW_DETAILS=true" -e "PROXY_HTTP_HEADERS=X-Foo,Bar,Baz_blah" --name app app:ci
|
||||||
scan-docker-image:
|
#
|
||||||
name: Scan the docker image
|
# - name: Wait for container "healthy" state
|
||||||
runs-on: ubuntu-latest
|
# run: until [[ "`docker inspect -f {{.State.Health.Status}} app`" == "healthy" ]]; do echo "wait 1 sec.."; sleep 1; done
|
||||||
needs: [docker-image]
|
#
|
||||||
steps:
|
# - run: hurl --color --test --fail-at-end --variable host=127.0.0.1 --variable port=8080 ./test/hurl/*.hurl
|
||||||
- uses: actions/checkout@v4 # is needed for `upload-sarif` action
|
#
|
||||||
|
# - name: Stop the container
|
||||||
- uses: actions/download-artifact@v4
|
# if: always()
|
||||||
with:
|
# run: docker kill app
|
||||||
name: docker-image
|
|
||||||
path: .artifact
|
|
||||||
|
|
||||||
- uses: aquasecurity/trivy-action@0.21.0 # action page: <https://github.com/aquasecurity/trivy-action>
|
|
||||||
with:
|
|
||||||
input: .artifact/docker-image.tar
|
|
||||||
format: sarif
|
|
||||||
severity: MEDIUM,HIGH,CRITICAL
|
|
||||||
exit-code: 1
|
|
||||||
output: trivy-results.sarif
|
|
||||||
|
|
||||||
- uses: github/codeql-action/upload-sarif@v3
|
|
||||||
if: always()
|
|
||||||
continue-on-error: true
|
|
||||||
with: {sarif_file: trivy-results.sarif}
|
|
||||||
|
|
||||||
poke-docker-image:
|
|
||||||
name: Run the docker image
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [docker-image]
|
|
||||||
timeout-minutes: 2
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: docker-image
|
|
||||||
path: .artifact
|
|
||||||
|
|
||||||
- working-directory: .artifact
|
|
||||||
run: docker load < docker-image.tar
|
|
||||||
|
|
||||||
- uses: gacts/install-hurl@v1
|
|
||||||
|
|
||||||
- name: Run container with the app
|
|
||||||
run: docker run --rm -d -p "8080:8080/tcp" -e "SHOW_DETAILS=true" -e "PROXY_HTTP_HEADERS=X-Foo,Bar,Baz_blah" --name app app:ci
|
|
||||||
|
|
||||||
- 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: hurl --color --test --fail-at-end --variable host=127.0.0.1 --variable port=8080 ./test/hurl/*.hurl
|
|
||||||
|
|
||||||
- name: Stop the container
|
|
||||||
if: always()
|
|
||||||
run: docker kill app
|
|
||||||
|
@ -110,10 +110,6 @@ issues:
|
|||||||
- tmp
|
- tmp
|
||||||
- temp
|
- temp
|
||||||
- testdata
|
- testdata
|
||||||
- cmd-old # TODO: remove
|
|
||||||
- internal-old # TODO: remove
|
|
||||||
- templates-old # TODO: remove
|
|
||||||
- test-old # TODO: remove
|
|
||||||
exclude-rules:
|
exclude-rules:
|
||||||
- {path: flags\.go, linters: [gochecknoglobals, lll, mnd, dupl]}
|
- {path: flags\.go, linters: [gochecknoglobals, lll, mnd, dupl]}
|
||||||
- {path: env\.go, linters: [lll, gosec]}
|
- {path: env\.go, linters: [lll, gosec]}
|
||||||
|
@ -7,8 +7,6 @@ FROM docker.io/library/golang:1.22-bookworm AS develop
|
|||||||
ENV GOPATH="/var/tmp/go"
|
ENV GOPATH="/var/tmp/go"
|
||||||
|
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& GOBIN=/bin go install gotest.tools/gotestsum@latest \
|
|
||||||
&& go clean -cache -modcache \
|
|
||||||
# renovate: source=github-releases name=golangci/golangci-lint
|
# renovate: source=github-releases name=golangci/golangci-lint
|
||||||
&& GOLANGCI_LINT_VERSION="1.59.1" \
|
&& GOLANGCI_LINT_VERSION="1.59.1" \
|
||||||
&& wget -O- -nv "https://cdn.jsdelivr.net/gh/golangci/golangci-lint@v${GOLANGCI_LINT_VERSION}/install.sh" \
|
&& wget -O- -nv "https://cdn.jsdelivr.net/gh/golangci/golangci-lint@v${GOLANGCI_LINT_VERSION}/install.sh" \
|
||||||
|
40
README.md
40
README.md
@ -10,10 +10,10 @@ $ error-pages [GLOBAL FLAGS] [COMMAND] [COMMAND FLAGS] [ARGUMENTS...]
|
|||||||
|
|
||||||
Global flags:
|
Global flags:
|
||||||
|
|
||||||
| Name | Description | Default value | Environment variables |
|
| Name | Description | Default value | Environment variables |
|
||||||
|--------------------|---------------------------------------------|:-------------:|:---------------------:|
|
|--------------------|---------------------------------------|:-------------:|:---------------------:|
|
||||||
| `--log-level="…"` | logging level (debug/info/warn/error/fatal) | `info` | `LOG_LEVEL` |
|
| `--log-level="…"` | logging level (debug/info/warn/error) | `info` | `LOG_LEVEL` |
|
||||||
| `--log-format="…"` | logging format (console/json) | `console` | `LOG_FORMAT` |
|
| `--log-format="…"` | logging format (console/json) | `console` | `LOG_FORMAT` |
|
||||||
|
|
||||||
### `serve` command (aliases: `s`, `server`, `http`)
|
### `serve` command (aliases: `s`, `server`, `http`)
|
||||||
|
|
||||||
@ -27,21 +27,23 @@ $ error-pages [GLOBAL FLAGS] serve [COMMAND FLAGS] [ARGUMENTS...]
|
|||||||
|
|
||||||
The following flags are supported:
|
The following flags are supported:
|
||||||
|
|
||||||
| Name | Description | Default value | Environment variables |
|
| Name | Description | Default value | Environment variables |
|
||||||
|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------:|:-------------------------:|
|
|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------:|:---------------------------:|
|
||||||
| `--listen="…"` (`-l`) | IP (v4 or v6) address to listen on | `0.0.0.0` | `LISTEN_ADDR` |
|
| `--listen="…"` (`-l`) | IP (v4 or v6) address to listen on | `0.0.0.0` | `LISTEN_ADDR` |
|
||||||
| `--port="…"` (`-p`) | TCP port number | `8080` | `LISTEN_PORT` |
|
| `--port="…"` (`-p`) | TCP port number | `8080` | `LISTEN_PORT` |
|
||||||
| `--add-template="…"` | to add a new template, provide the path to the file using this flag (the filename without the extension will be used as the template name) | `[]` | *none* |
|
| `--add-template="…"` | to add a new template, provide the path to the file using this flag (the filename without the extension will be used as the template name) | `[]` | *none* |
|
||||||
| `--add-http-code="…"` | to add a new HTTP status code, provide the code and its message/description using this flag (the format should be '%code%=%message%/%description%'; the code may contain a wildcard '*' to cover multiple codes at once, for example, '4**' will cover all 4xx codes, unless a more specific code was described previously) | `map[]` | *none* |
|
| `--disable-template="…"` | disable the specified template by its name | `[]` | *none* |
|
||||||
| `--json-format="…"` | override the default error page response in JSON format (Go templates are supported) | | `RESPONSE_JSON_FORMAT` |
|
| `--add-http-code="…"` | to add a new HTTP status code, provide the code and its message/description using this flag (the format should be '%code%=%message%/%description%'; the code may contain a wildcard '*' to cover multiple codes at once, for example, '4**' will cover all 4xx codes, unless a more specific code was described previously) | `map[]` | *none* |
|
||||||
| `--xml-format="…"` | override the default error page response in XML format (Go templates are supported) | | `RESPONSE_XML_FORMAT` |
|
| `--json-format="…"` | override the default error page response in JSON format (Go templates are supported) | | `RESPONSE_JSON_FORMAT` |
|
||||||
| `--template-name="…"` (`-t`) | name of the template to use for rendering error pages | `template-1` | `TEMPLATE_NAME` |
|
| `--xml-format="…"` | override the default error page response in XML format (Go templates are supported) | | `RESPONSE_XML_FORMAT` |
|
||||||
| `--disable-l10n` | disable localization of error pages (if the template supports localization) | `false` | `DISABLE_L10N` |
|
| `--plaintext-format="…"` | override the default error page response in plain text format (Go templates are supported) | | `RESPONSE_PLAINTEXT_FORMAT` |
|
||||||
| `--default-error-page="…"` | the code of the default (index page, when a code is not specified) error page to render | `404` | `DEFAULT_ERROR_PAGE` |
|
| `--template-name="…"` (`-t`) | name of the template to use for rendering error pages | `app-down` | `TEMPLATE_NAME` |
|
||||||
| `--send-same-http-code` | the HTTP response should have the same status code as the requested error page (by default, every response with an error page will have a status code of 200) | `false` | `SEND_SAME_HTTP_CODE` |
|
| `--disable-l10n` | disable localization of error pages (if the template supports localization) | `false` | `DISABLE_L10N` |
|
||||||
| `--show-details` | show request details in the error page response (if supported by the template) | `false` | `SHOW_DETAILS` |
|
| `--default-error-page="…"` | the code of the default (index page, when a code is not specified) error page to render | `404` | `DEFAULT_ERROR_PAGE` |
|
||||||
| `--proxy-headers="…"` | listed here HTTP headers will be proxied from the original request to the error page response (comma-separated list) | `X-Request-Id,X-Trace-Id,X-Amzn-Trace-Id` | `PROXY_HTTP_HEADERS` |
|
| `--send-same-http-code` | the HTTP response should have the same status code as the requested error page (by default, every response with an error page will have a status code of 200) | `false` | `SEND_SAME_HTTP_CODE` |
|
||||||
| `--rotation-mode="…"` | templates automatic rotation mode (disabled/random-on-startup/random-on-each-request/random-daily/random-hourly) | `disabled` | `TEMPLATES_ROTATION_MODE` |
|
| `--show-details` | show request details in the error page response (if supported by the template) | `false` | `SHOW_DETAILS` |
|
||||||
|
| `--proxy-headers="…"` | listed here HTTP headers will be proxied from the original request to the error page response (comma-separated list) | `X-Request-Id,X-Trace-Id,X-Amzn-Trace-Id` | `PROXY_HTTP_HEADERS` |
|
||||||
|
| `--rotation-mode="…"` | templates automatic rotation mode (disabled/random-on-startup/random-on-each-request/random-hourly/random-daily) | `disabled` | `TEMPLATES_ROTATION_MODE` |
|
||||||
|
|
||||||
### `healthcheck` command (aliases: `chk`, `health`, `check`)
|
### `healthcheck` command (aliases: `chk`, `health`, `check`)
|
||||||
|
|
||||||
|
140
error-pages.yml
140
error-pages.yml
@ -1,140 +0,0 @@
|
|||||||
templates:
|
|
||||||
# - name: {string} Template name (optional, if path is defined)
|
|
||||||
# path: {string} Path to the template file
|
|
||||||
# content: {string} Template content, if path is not defined
|
|
||||||
- path: ./templates/ghost.html
|
|
||||||
name: ghost # name is optional, if path is defined
|
|
||||||
content: ${GHOST_TEMPLATE_CONTENT}
|
|
||||||
- path: ./templates/l7-light.html
|
|
||||||
- path: ./templates/l7-dark.html
|
|
||||||
- path: ./templates/shuffle.html
|
|
||||||
- path: ./templates/noise.html
|
|
||||||
- path: ./templates/hacker-terminal.html
|
|
||||||
- path: ./templates/cats.html
|
|
||||||
- path: ./templates/lost-in-space.html
|
|
||||||
- path: ./templates/app-down.html
|
|
||||||
- path: ./templates/connection.html
|
|
||||||
- path: ./templates/matrix.html
|
|
||||||
- path: ./templates/orient.html
|
|
||||||
|
|
||||||
formats:
|
|
||||||
json:
|
|
||||||
content: |
|
|
||||||
{
|
|
||||||
"error": true,
|
|
||||||
"code": {{ code | json }},
|
|
||||||
"message": {{ message | json }},
|
|
||||||
"description": {{ description | json }}{{ if show_details }},
|
|
||||||
"details": {
|
|
||||||
"host": {{ host | json }},
|
|
||||||
"original_uri": {{ original_uri | json }},
|
|
||||||
"forwarded_for": {{ forwarded_for | json }},
|
|
||||||
"namespace": {{ namespace | json }},
|
|
||||||
"ingress_name": {{ ingress_name | json }},
|
|
||||||
"service_name": {{ service_name | json }},
|
|
||||||
"service_port": {{ service_port | json }},
|
|
||||||
"request_id": {{ request_id | json }},
|
|
||||||
"timestamp": {{ now.Unix }}
|
|
||||||
}{{ end }}
|
|
||||||
}
|
|
||||||
|
|
||||||
xml:
|
|
||||||
content: |
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<error>
|
|
||||||
<code>{{ code }}</code>
|
|
||||||
<message>{{ message }}</message>
|
|
||||||
<description>{{ description }}</description>{{ if show_details }}
|
|
||||||
<details>
|
|
||||||
<host>{{ host }}</host>
|
|
||||||
<originalURI>{{ original_uri }}</originalURI>
|
|
||||||
<forwardedFor>{{ forwarded_for }}</forwardedFor>
|
|
||||||
<namespace>{{ namespace }}</namespace>
|
|
||||||
<ingressName>{{ ingress_name }}</ingressName>
|
|
||||||
<serviceName>{{ service_name }}</serviceName>
|
|
||||||
<servicePort>{{ service_port }}</servicePort>
|
|
||||||
<requestID>{{ request_id }}</requestID>
|
|
||||||
<timestamp>{{ now.Unix }}</timestamp>
|
|
||||||
</details>{{ end }}
|
|
||||||
</error>
|
|
||||||
|
|
||||||
pages:
|
|
||||||
400:
|
|
||||||
message: Bad Request
|
|
||||||
description: The server did not understand the request
|
|
||||||
|
|
||||||
401:
|
|
||||||
message: Unauthorized
|
|
||||||
description: The requested page needs a username and a password
|
|
||||||
|
|
||||||
403:
|
|
||||||
message: Forbidden
|
|
||||||
description: Access is forbidden to the requested page
|
|
||||||
|
|
||||||
404:
|
|
||||||
message: Not Found
|
|
||||||
description: The server can not find the requested page
|
|
||||||
|
|
||||||
405:
|
|
||||||
message: Method Not Allowed
|
|
||||||
description: The method specified in the request is not allowed
|
|
||||||
|
|
||||||
407:
|
|
||||||
message: Proxy Authentication Required
|
|
||||||
description: You must authenticate with a proxy server before this request can be served
|
|
||||||
|
|
||||||
408:
|
|
||||||
message: Request Timeout
|
|
||||||
description: The request took longer than the server was prepared to wait
|
|
||||||
|
|
||||||
409:
|
|
||||||
message: Conflict
|
|
||||||
description: The request could not be completed because of a conflict
|
|
||||||
|
|
||||||
410:
|
|
||||||
message: Gone
|
|
||||||
description: The requested page is no longer available
|
|
||||||
|
|
||||||
411:
|
|
||||||
message: Length Required
|
|
||||||
description: The "Content-Length" is not defined. The server will not accept the request without it
|
|
||||||
|
|
||||||
412:
|
|
||||||
message: Precondition Failed
|
|
||||||
description: The pre condition given in the request evaluated to false by the server
|
|
||||||
|
|
||||||
413:
|
|
||||||
message: Payload Too Large
|
|
||||||
description: The server will not accept the request, because the request entity is too large
|
|
||||||
|
|
||||||
416:
|
|
||||||
message: Requested Range Not Satisfiable
|
|
||||||
description: The requested byte range is not available and is out of bounds
|
|
||||||
|
|
||||||
418:
|
|
||||||
message: I'm a teapot
|
|
||||||
description: Attempt to brew coffee with a teapot is not supported
|
|
||||||
|
|
||||||
429:
|
|
||||||
message: Too Many Requests
|
|
||||||
description: Too many requests in a given amount of time
|
|
||||||
|
|
||||||
500:
|
|
||||||
message: Internal Server Error
|
|
||||||
description: The server met an unexpected condition
|
|
||||||
|
|
||||||
502:
|
|
||||||
message: Bad Gateway
|
|
||||||
description: The server received an invalid response from the upstream server
|
|
||||||
|
|
||||||
503:
|
|
||||||
message: Service Unavailable
|
|
||||||
description: The server is temporarily overloading or down
|
|
||||||
|
|
||||||
504:
|
|
||||||
message: Gateway Timeout
|
|
||||||
description: The gateway has timed out
|
|
||||||
|
|
||||||
505:
|
|
||||||
message: HTTP Version Not Supported
|
|
||||||
description: The server does not support the "http protocol" version
|
|
29
go.mod
29
go.mod
@ -3,41 +3,20 @@ module gh.tarampamp.am/error-pages
|
|||||||
go 1.22
|
go 1.22
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/a8m/envsubst v1.4.2
|
|
||||||
github.com/fasthttp/router v1.5.1
|
|
||||||
github.com/fatih/color v1.17.0
|
|
||||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d
|
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/prometheus/client_golang v1.19.1
|
|
||||||
github.com/prometheus/client_model v0.6.1
|
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha5
|
github.com/urfave/cli-docs/v3 v3.0.0-alpha5
|
||||||
github.com/urfave/cli/v2 v2.27.2
|
|
||||||
github.com/urfave/cli/v3 v3.0.0-alpha9
|
github.com/urfave/cli/v3 v3.0.0-alpha9
|
||||||
github.com/valyala/fasthttp v1.54.0
|
|
||||||
go.uber.org/automaxprocs v1.5.3
|
go.uber.org/automaxprocs v1.5.3
|
||||||
go.uber.org/goleak v1.3.0
|
|
||||||
go.uber.org/zap v1.27.0
|
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/klauspost/compress v1.17.7 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/common v0.50.0 // indirect
|
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||||
github.com/prometheus/procfs v0.13.0 // indirect
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
golang.org/x/sys v0.18.0 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
google.golang.org/protobuf v1.33.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
63
go.sum
63
go.sum
@ -1,82 +1,35 @@
|
|||||||
github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg=
|
|
||||||
github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY=
|
|
||||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
|
||||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fasthttp/router v1.5.1 h1:uViy8UYYhm5npJSKEZ4b/ozM//NGzVCfJbh6VJ0VKr8=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/fasthttp/router v1.5.1/go.mod h1:WrmsLo3mrerZP2VEXRV1E8nL8ymJFYCDTr4HmnB8+Zs=
|
|
||||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
|
||||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d h1:cVtBfNW5XTHiKQe7jDaDBSh/EVM4XLPutLAGboIXuM0=
|
|
||||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
|
|
||||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
|
||||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
|
||||||
github.com/prometheus/common v0.50.0 h1:YSZE6aa9+luNa2da6/Tik0q0A5AbR+U003TItK57CPQ=
|
|
||||||
github.com/prometheus/common v0.50.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ=
|
|
||||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
|
||||||
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3CiimCAbxFrhB3j7h0/OvpYGVQa8=
|
|
||||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
|
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha5 h1:H1oWnR2/GN0dNm2PVylws+GxSOD6YOwW/jI5l78YfPk=
|
github.com/urfave/cli-docs/v3 v3.0.0-alpha5 h1:H1oWnR2/GN0dNm2PVylws+GxSOD6YOwW/jI5l78YfPk=
|
||||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha5/go.mod h1:AIqom6Q60U4tiqHp41i7+/AB2XHgi1WvQ7jOFlccmZ4=
|
github.com/urfave/cli-docs/v3 v3.0.0-alpha5/go.mod h1:AIqom6Q60U4tiqHp41i7+/AB2XHgi1WvQ7jOFlccmZ4=
|
||||||
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
|
|
||||||
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
|
|
||||||
github.com/urfave/cli/v3 v3.0.0-alpha9 h1:P0RMy5fQm1AslQS+XCmy9UknDXctOmG/q/FZkUFnJSo=
|
github.com/urfave/cli/v3 v3.0.0-alpha9 h1:P0RMy5fQm1AslQS+XCmy9UknDXctOmG/q/FZkUFnJSo=
|
||||||
github.com/urfave/cli/v3 v3.0.0-alpha9/go.mod h1:0kK/RUFHyh+yIKSfWxwheGndfnrvYSmYFVeKCh03ZUc=
|
github.com/urfave/cli/v3 v3.0.0-alpha9/go.mod h1:0kK/RUFHyh+yIKSfWxwheGndfnrvYSmYFVeKCh03ZUc=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
|
||||||
github.com/valyala/fasthttp v1.54.0 h1:cCL+ZZR3z3HPLMVfEYVUMtJqVaui0+gu7Lx63unHwS0=
|
|
||||||
github.com/valyala/fasthttp v1.54.0/go.mod h1:6dt4/8olwq9QARP/TDuPmWyWcl4byhpvTJ4AAtcz+QM=
|
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
|
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
|
||||||
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
|
||||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
|
||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
|
||||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
@ -3,6 +3,8 @@ package appmeta
|
|||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestVersion(t *testing.T) {
|
func TestVersion(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
for give, want := range map[string]string{
|
for give, want := range map[string]string{
|
||||||
// without changes
|
// without changes
|
||||||
"vvv": "vvv",
|
"vvv": "vvv",
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kami-zh/go-capturer"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"gh.tarampamp.am/error-pages/internal/cli"
|
"gh.tarampamp.am/error-pages/internal/cli"
|
||||||
@ -15,11 +14,5 @@ func TestNewApp(t *testing.T) {
|
|||||||
|
|
||||||
app := cli.NewApp("appName")
|
app := cli.NewApp("appName")
|
||||||
|
|
||||||
assert.NotEmpty(t, app.Flags)
|
assert.NoError(t, app.Run(context.Background(), []string{""}))
|
||||||
|
|
||||||
output := capturer.CaptureStdout(func() {
|
|
||||||
assert.NoError(t, app.Run(context.Background(), []string{""}))
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.NotEmpty(t, output)
|
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit
|
|||||||
logger.Uint64("failed", failed.Load()),
|
logger.Uint64("failed", failed.Load()),
|
||||||
logger.Duration("duration", time.Since(startedAt)),
|
logger.Duration("duration", time.Since(startedAt)),
|
||||||
logger.Float64("RPS", float64(success.Load()+failed.Load())/time.Since(startedAt).Seconds()),
|
logger.Float64("RPS", float64(success.Load()+failed.Load())/time.Since(startedAt).Seconds()),
|
||||||
logger.Float64("errors rate", float64(failed.Load())/float64(success.Load()+failed.Load())*100),
|
logger.Float64("errors rate", float64(failed.Load())/float64(success.Load()+failed.Load())*100), //nolint:mnd
|
||||||
)
|
)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit
|
|||||||
|
|
||||||
var req, rErr = makeRequest(perfCtx, uint16(c.Uint(portFlag.Name)))
|
var req, rErr = makeRequest(perfCtx, uint16(c.Uint(portFlag.Name)))
|
||||||
if rErr != nil {
|
if rErr != nil {
|
||||||
log.Error("failed to create a new request", logger.Error(rErr))
|
log.Error("Failed to create a new request", logger.Error(rErr))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -110,11 +110,11 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit
|
|||||||
var resp, respErr = httpClient.Do(req)
|
var resp, respErr = httpClient.Do(req)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
if _, err := io.Copy(io.Discard, resp.Body); err != nil && !errIsDone(err) {
|
if _, err := io.Copy(io.Discard, resp.Body); err != nil && !errIsDone(err) {
|
||||||
log.Error("failed to read response body", logger.Error(err))
|
log.Error("Failed to read response body", logger.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := resp.Body.Close(); err != nil && !errIsDone(err) {
|
if err := resp.Body.Close(); err != nil && !errIsDone(err) {
|
||||||
log.Error("failed to close response body", logger.Error(err))
|
log.Error("Failed to close response body", logger.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Error("request failed", logger.Error(respErr))
|
log.Error("Request failed", logger.Error(respErr))
|
||||||
failed.Add(1)
|
failed.Add(1)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
@ -110,7 +110,7 @@ func NewCommand(log *logger.Logger) *cli.Command { //nolint:funlen,gocognit,gocy
|
|||||||
OnlyOnce: true,
|
OnlyOnce: true,
|
||||||
}
|
}
|
||||||
proxyHeadersListFlag = cli.StringFlag{
|
proxyHeadersListFlag = cli.StringFlag{
|
||||||
Name: "proxy-headers", // TODO: add support for the "*" wildcard
|
Name: "proxy-headers",
|
||||||
Usage: "listed here HTTP headers will be proxied from the original request to the error page response " +
|
Usage: "listed here HTTP headers will be proxied from the original request to the error page response " +
|
||||||
"(comma-separated list)",
|
"(comma-separated list)",
|
||||||
Value: strings.Join(cfg.ProxyHeaders, ","),
|
Value: strings.Join(cfg.ProxyHeaders, ","),
|
||||||
|
101
internal/cli/serve/command_test.go
Normal file
101
internal/cli/serve/command_test.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package serve_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"gh.tarampamp.am/error-pages/internal/cli/serve"
|
||||||
|
"gh.tarampamp.am/error-pages/internal/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCommand_Run(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var (
|
||||||
|
port = getFreeTcpPort(t)
|
||||||
|
cmd = serve.NewCommand(logger.NewNop())
|
||||||
|
)
|
||||||
|
|
||||||
|
var ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var ch = make(chan error, 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(ch)
|
||||||
|
|
||||||
|
ch <- cmd.Run(ctx, []string{
|
||||||
|
"serve",
|
||||||
|
"--port", strconv.Itoa(int(port)),
|
||||||
|
"--add-template", "./testdata/foo-template.html",
|
||||||
|
"--disable-template", "ghost",
|
||||||
|
"--disable-template", "<unknown>",
|
||||||
|
"--add-http-code", "200=Code/Description",
|
||||||
|
"--json-format", "json format",
|
||||||
|
"--xml-format", "xml format",
|
||||||
|
"--plaintext-format", "plaintext format",
|
||||||
|
"--template-name", "foo-template",
|
||||||
|
"--disable-l10n",
|
||||||
|
"--default-error-page", "503",
|
||||||
|
"--send-same-http-code",
|
||||||
|
"--show-details",
|
||||||
|
"--proxy-headers", "X-Forwarded-For,X-Forwarded-Proto",
|
||||||
|
"--rotation-mode", "random-on-each-request",
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
|
||||||
|
var connected bool
|
||||||
|
|
||||||
|
for {
|
||||||
|
conn, err := net.DialTimeout("tcp", fmt.Sprintf("127.0.0.1:%d", port), time.Second)
|
||||||
|
if err == nil {
|
||||||
|
connected = true
|
||||||
|
|
||||||
|
require.NoError(t, conn.Close())
|
||||||
|
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
t.Fatal("timeout")
|
||||||
|
case chErr := <-ch:
|
||||||
|
require.NoError(t, chErr)
|
||||||
|
case <-time.After(10 * time.Millisecond):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require.True(t, connected, "server is not running")
|
||||||
|
}
|
||||||
|
|
||||||
|
// getFreeTcpPort is a helper function to get a free TCP port number.
|
||||||
|
func getFreeTcpPort(t *testing.T) uint16 {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
l, lErr := net.Listen("tcp", "127.0.0.1:0")
|
||||||
|
require.NoError(t, lErr)
|
||||||
|
|
||||||
|
port := l.Addr().(*net.TCPAddr).Port
|
||||||
|
require.NoError(t, l.Close())
|
||||||
|
|
||||||
|
// make sure port is closed
|
||||||
|
for {
|
||||||
|
conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port))
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(t, conn.Close())
|
||||||
|
<-time.After(5 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint16(port)
|
||||||
|
}
|
10
internal/cli/serve/testdata/foo-template.html
vendored
Normal file
10
internal/cli/serve/testdata/foo-template.html
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
226
internal/http/handlers/error_page/handler_test.go
Normal file
226
internal/http/handlers/error_page/handler_test.go
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
package error_page_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"gh.tarampamp.am/error-pages/internal/config"
|
||||||
|
"gh.tarampamp.am/error-pages/internal/http/handlers/error_page"
|
||||||
|
"gh.tarampamp.am/error-pages/internal/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHandler(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
for name, tt := range map[string]struct {
|
||||||
|
giveConfig func() *config.Config
|
||||||
|
giveUrl string
|
||||||
|
giveHeaders map[string]string
|
||||||
|
|
||||||
|
wantStatusCode int
|
||||||
|
wantHeaders map[string]string
|
||||||
|
wantBodyIncludes []string
|
||||||
|
}{
|
||||||
|
"common, plain text": {
|
||||||
|
giveConfig: func() *config.Config { cfg := config.New(); return &cfg },
|
||||||
|
giveUrl: "/",
|
||||||
|
giveHeaders: map[string]string{"Content-Type": "text/plain"},
|
||||||
|
|
||||||
|
wantStatusCode: http.StatusOK,
|
||||||
|
wantHeaders: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
|
||||||
|
wantBodyIncludes: []string{"Error 404", "Not Found"},
|
||||||
|
},
|
||||||
|
"common, html": {
|
||||||
|
giveConfig: func() *config.Config {
|
||||||
|
cfg := config.New()
|
||||||
|
|
||||||
|
cfg.TemplateName = "ghost"
|
||||||
|
|
||||||
|
return &cfg
|
||||||
|
},
|
||||||
|
giveUrl: "/",
|
||||||
|
giveHeaders: map[string]string{"X-Format": "text/html", "X-Code": "407"},
|
||||||
|
|
||||||
|
wantStatusCode: http.StatusOK,
|
||||||
|
wantHeaders: map[string]string{"Content-Type": "text/html; charset=utf-8"},
|
||||||
|
wantBodyIncludes: []string{
|
||||||
|
"<!DOCTYPE html>",
|
||||||
|
"<title>407: Proxy Authentication Required",
|
||||||
|
"Proxy Authentication Required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"common, json": {
|
||||||
|
giveConfig: func() *config.Config {
|
||||||
|
cfg := config.New()
|
||||||
|
|
||||||
|
cfg.RespondWithSameHTTPCode = true
|
||||||
|
|
||||||
|
return &cfg
|
||||||
|
},
|
||||||
|
giveUrl: "/503.html",
|
||||||
|
giveHeaders: map[string]string{"Accept": "application/json", "X-FooBar": "baz"},
|
||||||
|
|
||||||
|
wantStatusCode: http.StatusServiceUnavailable,
|
||||||
|
wantHeaders: map[string]string{
|
||||||
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
|
"X-FooBar": "", // is not in the list of proxy headers
|
||||||
|
},
|
||||||
|
wantBodyIncludes: []string{"503", "Service Unavailable"},
|
||||||
|
},
|
||||||
|
"common, xml": {
|
||||||
|
giveConfig: func() *config.Config {
|
||||||
|
cfg := config.New()
|
||||||
|
|
||||||
|
cfg.ProxyHeaders = append(cfg.ProxyHeaders, "X-FooBar")
|
||||||
|
|
||||||
|
return &cfg
|
||||||
|
},
|
||||||
|
giveUrl: "/500",
|
||||||
|
giveHeaders: map[string]string{"Accept": "application/xml", "X-FooBar": "baz"},
|
||||||
|
|
||||||
|
wantStatusCode: http.StatusOK,
|
||||||
|
wantHeaders: map[string]string{
|
||||||
|
"Content-Type": "application/xml; charset=utf-8",
|
||||||
|
"X-FooBar": "baz",
|
||||||
|
},
|
||||||
|
wantBodyIncludes: []string{"500", "Internal Server Error"},
|
||||||
|
},
|
||||||
|
"show details": {
|
||||||
|
giveConfig: func() *config.Config {
|
||||||
|
cfg := config.New()
|
||||||
|
|
||||||
|
cfg.ShowDetails = true
|
||||||
|
|
||||||
|
return &cfg
|
||||||
|
},
|
||||||
|
giveUrl: "/503",
|
||||||
|
giveHeaders: map[string]string{
|
||||||
|
"Accept": "application/json",
|
||||||
|
"X-Original-URI": "/foo/bar",
|
||||||
|
"X-Namespace": "some-Namespace",
|
||||||
|
"X-Ingress-Name": "ingress-name",
|
||||||
|
"X-Service-Name": "service-name",
|
||||||
|
"X-Service-Port": "666",
|
||||||
|
"X-Request-ID": "req-id-777",
|
||||||
|
"X-Forwarded-For": "123.123.123.123:12312",
|
||||||
|
"Host": "example.com",
|
||||||
|
},
|
||||||
|
|
||||||
|
wantStatusCode: http.StatusOK,
|
||||||
|
wantHeaders: map[string]string{"Content-Type": "application/json; charset=utf-8"},
|
||||||
|
wantBodyIncludes: []string{
|
||||||
|
"503",
|
||||||
|
"Service Unavailable",
|
||||||
|
"details",
|
||||||
|
"/foo/bar",
|
||||||
|
"some-Namespace",
|
||||||
|
"ingress-name",
|
||||||
|
"service-name",
|
||||||
|
"666",
|
||||||
|
"req-id-777",
|
||||||
|
"123.123.123.123:12312",
|
||||||
|
"example.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"fallback to StatusText if code is not found": {
|
||||||
|
giveConfig: func() *config.Config {
|
||||||
|
cfg := config.New()
|
||||||
|
|
||||||
|
cfg.Codes = config.Codes{}
|
||||||
|
|
||||||
|
return &cfg
|
||||||
|
},
|
||||||
|
giveUrl: "/100",
|
||||||
|
giveHeaders: map[string]string{"Accept": "application/json"},
|
||||||
|
|
||||||
|
wantStatusCode: http.StatusOK,
|
||||||
|
wantHeaders: map[string]string{"Content-Type": "application/json; charset=utf-8"},
|
||||||
|
wantBodyIncludes: []string{"100", "Continue"},
|
||||||
|
},
|
||||||
|
"unknown code": {
|
||||||
|
giveConfig: func() *config.Config {
|
||||||
|
cfg := config.New()
|
||||||
|
|
||||||
|
cfg.Codes = config.Codes{}
|
||||||
|
|
||||||
|
return &cfg
|
||||||
|
},
|
||||||
|
giveUrl: "/1",
|
||||||
|
giveHeaders: map[string]string{"Accept": "application/json"},
|
||||||
|
|
||||||
|
wantStatusCode: http.StatusOK,
|
||||||
|
wantHeaders: map[string]string{"Content-Type": "application/json; charset=utf-8"},
|
||||||
|
wantBodyIncludes: []string{"1", "Unknown Status Code"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var (
|
||||||
|
req = httptest.NewRequest(http.MethodGet, tt.giveUrl, http.NoBody)
|
||||||
|
handler = error_page.New(tt.giveConfig(), logger.NewNop())
|
||||||
|
rr = httptest.NewRecorder()
|
||||||
|
)
|
||||||
|
|
||||||
|
for k, v := range tt.giveHeaders {
|
||||||
|
req.Header.Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
assert.Equal(t, rr.Code, tt.wantStatusCode)
|
||||||
|
|
||||||
|
for hName, hWant := range tt.wantHeaders {
|
||||||
|
for hGot := range rr.Header() {
|
||||||
|
if hGot == hName {
|
||||||
|
assert.Contains(t, hWant, rr.Header().Get(hGot))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, wantBodyInclude := range tt.wantBodyIncludes {
|
||||||
|
assert.Contains(t, rr.Body.String(), wantBodyInclude)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRotationModeOnEachRequest(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var cfg = config.New()
|
||||||
|
|
||||||
|
cfg.RotationMode = config.RotationModeRandomOnEachRequest
|
||||||
|
cfg.Templates = map[string]string{
|
||||||
|
"foo": "foo",
|
||||||
|
"bar": "bar",
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
lastResponseBody string
|
||||||
|
changedTimes int
|
||||||
|
|
||||||
|
handler = error_page.New(&cfg, logger.NewNop())
|
||||||
|
)
|
||||||
|
|
||||||
|
for range 300 {
|
||||||
|
var (
|
||||||
|
req = httptest.NewRequest(http.MethodGet, "/", http.NoBody)
|
||||||
|
rr = httptest.NewRecorder()
|
||||||
|
)
|
||||||
|
|
||||||
|
req.Header.Set("Accept", "text/html")
|
||||||
|
|
||||||
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
if lastResponseBody != rr.Body.String() {
|
||||||
|
changedTimes++
|
||||||
|
lastResponseBody = rr.Body.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, changedTimes > 30, "the template should be changed at least 30 times")
|
||||||
|
}
|
44
internal/http/middleware/logreq/middleware_test.go
Normal file
44
internal/http/middleware/logreq/middleware_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package logreq_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"gh.tarampamp.am/error-pages/internal/http/middleware/logreq"
|
||||||
|
"gh.tarampamp.am/error-pages/internal/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var (
|
||||||
|
buf bytes.Buffer
|
||||||
|
log, _ = logger.New(logger.DebugLevel, logger.JSONFormat, &buf)
|
||||||
|
|
||||||
|
mw = logreq.New(log, nil)
|
||||||
|
rr = httptest.NewRecorder()
|
||||||
|
req = httptest.NewRequest(http.MethodPut, "/foo/bar", http.NoBody)
|
||||||
|
)
|
||||||
|
|
||||||
|
req.Header.Set("User-Agent", "test")
|
||||||
|
req.Header.Set("Referer", "https://example.com")
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
mw(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
})).ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
var logRecord = buf.String()
|
||||||
|
|
||||||
|
assert.Contains(t, logRecord, `"level":"info"`)
|
||||||
|
assert.Contains(t, logRecord, `"msg":"HTTP request processed"`)
|
||||||
|
assert.Contains(t, logRecord, `"useragent":"test"`)
|
||||||
|
assert.Contains(t, logRecord, `"method":"PUT"`)
|
||||||
|
assert.Contains(t, logRecord, `"url":"/foo/bar"`)
|
||||||
|
assert.Contains(t, logRecord, `"referer":"https://example.com"`)
|
||||||
|
assert.Contains(t, logRecord, `application/json`)
|
||||||
|
}
|
3116
profile001.svg
3116
profile001.svg
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 169 KiB |
@ -1,108 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"title": "Error-Pages config file schema",
|
|
||||||
"description": "Error-Pages config file schema.",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"templates": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "Templates list",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Template properties",
|
|
||||||
"properties": {
|
|
||||||
"path": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path to the template file",
|
|
||||||
"examples": [
|
|
||||||
"./templates/ghost.html",
|
|
||||||
"/opt/tpl/ghost.htm"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Template name (optional, if path is defined)",
|
|
||||||
"examples": [
|
|
||||||
"ghost"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"content": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Template content, if path is not defined",
|
|
||||||
"examples": [
|
|
||||||
"<html><body>{{ code }}: {{ message }}</body></html>"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"formats": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Responses, based on requested content-type format",
|
|
||||||
"properties": {
|
|
||||||
"json": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "JSON format",
|
|
||||||
"properties": {
|
|
||||||
"content": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "JSON response body (template tags are allowed here)",
|
|
||||||
"examples": [
|
|
||||||
"{\"error\": true, \"code\": {{ code | json }}, \"message\": {{ message | json }}}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"xml": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "XML format",
|
|
||||||
"properties": {
|
|
||||||
"content": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "XML response body (template tags are allowed here)",
|
|
||||||
"examples": [
|
|
||||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?><error><code>{{ code }}</code><message>{{ message }}</message></error>"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"pages": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Error pages (codes)",
|
|
||||||
"patternProperties": {
|
|
||||||
"^[a-zA-Z0-9_-]+$": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Error page (code)",
|
|
||||||
"properties": {
|
|
||||||
"message": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Error page message (title)",
|
|
||||||
"examples": [
|
|
||||||
"Bad Request"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Error page description",
|
|
||||||
"examples": [
|
|
||||||
"The server did not understand the request"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"templates"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
# Config file schemas
|
|
||||||
|
|
||||||
These schemas describe Error Pages configuration file and used by:
|
|
||||||
|
|
||||||
- <https://github.com/SchemaStore/schemastore>
|
|
||||||
|
|
||||||
Schemas naming agreement: `<version_major>.<version_minor>.schema.json`.
|
|
||||||
|
|
||||||
## Contributing guide
|
|
||||||
|
|
||||||
If you want to modify the existing schema - your changes **MUST** be backward compatible. If your changes break backward compatibility - you **MUST** create a new schema file with a fresh version and "register" it in a [schemas catalog][schemas_catalog].
|
|
||||||
|
|
||||||
[schemas_catalog]:https://github.com/SchemaStore/schemastore/blob/master/src/api/json/catalog.json
|
|
@ -1,15 +0,0 @@
|
|||||||
# Schemas
|
|
||||||
|
|
||||||
This directory contains public schemas for the most important parts of application.
|
|
||||||
|
|
||||||
**Do not rename or remove this directory or any file or directory inside.**
|
|
||||||
|
|
||||||
- You can validate existing config file using the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ docker run --rm -v "$(pwd):/src" -w "/src" node:16-alpine sh -c \
|
|
||||||
"npm install -g ajv-cli && \
|
|
||||||
ajv validate --all-errors --verbose \
|
|
||||||
-s ./schemas/config/1.0.schema.json \
|
|
||||||
-d ./error-pages.y*ml"
|
|
||||||
```
|
|
Loading…
Reference in New Issue
Block a user