diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 25b7e9a..a217b3c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -196,12 +196,12 @@ jobs: # Docs: run: docker load < docker-image.tar - name: Run container with the app - run: docker run --rm -d -p "8080:8080/tcp" --name app app:ci + run: docker run --rm -d -p "8080:8080/tcp" -e "DEFAULT_HTTP_CODE=401" --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: curl --fail http://127.0.0.1:8080/ + - run: test $(curl --write-out %{http_code} --silent --output /dev/null http://127.0.0.1:8080/) -eq 401 - 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 diff --git a/.golangci.yml b/.golangci.yml index fce316e..faea502 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,6 +5,8 @@ run: skip-dirs: - .github - .git + - tmp + - temp modules-download-mode: readonly allow-parallel-runners: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 8523505..34bcf70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,16 @@ The format is based on [Keep a Changelog][keepachangelog] and this project adher ## UNRELEASED +### Added + +- Flag `--default-http-code` for the `serve` subcommand (`404` is used by default instead of `200`, environment name `DEFAULT_HTTP_CODE`) [#41] + ### Changed - Go updated from `1.17.1` up to `1.17.5` +[#41]:https://github.com/tarampampam/error-pages/issues/41 + ## v2.2.0 ### Added diff --git a/Dockerfile b/Dockerfile index 74c6bbf..ca10380 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,7 +65,8 @@ WORKDIR /opt ENV LISTEN_PORT="8080" \ TEMPLATE_NAME="ghost" \ - DEFAULT_ERROR_PAGE="404" + DEFAULT_ERROR_PAGE="404" \ + DEFAULT_HTTP_CODE="404" # Docs: HEALTHCHECK --interval=7s --timeout=2s CMD [ \ diff --git a/internal/cli/serve/command.go b/internal/cli/serve/command.go index a757f67..6bc481b 100644 --- a/internal/cli/serve/command.go +++ b/internal/cli/serve/command.go @@ -144,7 +144,7 @@ func run(parentCtx context.Context, log *zap.Logger, f flags, cfg *config.Config server := appHttp.NewServer(log) // register server routes, middlewares, etc. - server.Register(&errorPages, picker, f.defaultErrorPage) + server.Register(&errorPages, picker, f.defaultErrorPage, f.defaultHTTPCode) startedAt, startingErrCh := time.Now(), make(chan error, 1) // channel for server starting error @@ -156,6 +156,7 @@ func run(parentCtx context.Context, log *zap.Logger, f flags, cfg *config.Config zap.String("addr", f.listen.ip), zap.Uint16("port", f.listen.port), zap.String("default error page", f.defaultErrorPage), + zap.Uint16("default HTTP response code", f.defaultHTTPCode), ) if err := server.Start(f.listen.ip, f.listen.port); err != nil { diff --git a/internal/cli/serve/flags.go b/internal/cli/serve/flags.go index 7117ea9..1c368bf 100644 --- a/internal/cli/serve/flags.go +++ b/internal/cli/serve/flags.go @@ -19,6 +19,7 @@ type flags struct { name string } defaultErrorPage string + defaultHTTPCode uint16 } const ( @@ -26,6 +27,7 @@ const ( portFlagName = "port" templateNameFlagName = "template-name" defaultErrorPageFlagName = "default-error-page" + defaultHTTPCodeFlagName = "default-http-code" ) const ( @@ -61,9 +63,15 @@ func (f *flags) init(flagSet *pflag.FlagSet) { "404", fmt.Sprintf("default error page [$%s]", env.DefaultErrorPage), ) + flagSet.Uint16VarP( + &f.defaultHTTPCode, + defaultHTTPCodeFlagName, "", + 404, //nolint:gomnd + fmt.Sprintf("default HTTP response code [$%s]", env.DefaultHTTPCode), + ) } -func (f *flags) overrideUsingEnv(flagSet *pflag.FlagSet) (lastErr error) { +func (f *flags) overrideUsingEnv(flagSet *pflag.FlagSet) (lastErr error) { //nolint:gocognit flagSet.VisitAll(func(flag *pflag.Flag) { // flag was NOT defined using CLI (flags should have maximal priority) if !flag.Changed { //nolint:nestif @@ -91,6 +99,15 @@ func (f *flags) overrideUsingEnv(flagSet *pflag.FlagSet) (lastErr error) { if envVar, exists := env.DefaultErrorPage.Lookup(); exists { f.defaultErrorPage = strings.TrimSpace(envVar) } + + case defaultHTTPCodeFlagName: + if envVar, exists := env.DefaultHTTPCode.Lookup(); exists { + if code, err := strconv.ParseUint(envVar, 10, 16); err == nil { //nolint:gomnd + f.defaultHTTPCode = uint16(code) + } else { + lastErr = fmt.Errorf("wrong default HTTP response code environment variable [%s] value", envVar) + } + } } } }) @@ -103,5 +120,9 @@ func (f *flags) validate() error { return fmt.Errorf("wrong IP address [%s] for listening", f.listen.ip) } + if f.defaultHTTPCode > 599 { //nolint:gomnd + return fmt.Errorf("wrong default HTTP response code [%d]", f.defaultHTTPCode) + } + return nil } diff --git a/internal/env/env.go b/internal/env/env.go index 6c638f5..1088e27 100644 --- a/internal/env/env.go +++ b/internal/env/env.go @@ -11,6 +11,7 @@ const ( TemplateName envVariable = "TEMPLATE_NAME" // template name ConfigFilePath envVariable = "CONFIG_FILE" // path to the config file DefaultErrorPage envVariable = "DEFAULT_ERROR_PAGE" // default error page (code) + DefaultHTTPCode envVariable = "DEFAULT_HTTP_CODE" // default HTTP response code ) // String returns environment variable name in the string representation. diff --git a/internal/env/env_test.go b/internal/env/env_test.go index e249f99..018896c 100644 --- a/internal/env/env_test.go +++ b/internal/env/env_test.go @@ -13,6 +13,7 @@ func TestConstants(t *testing.T) { assert.Equal(t, "TEMPLATE_NAME", string(TemplateName)) assert.Equal(t, "CONFIG_FILE", string(ConfigFilePath)) assert.Equal(t, "DEFAULT_ERROR_PAGE", string(DefaultErrorPage)) + assert.Equal(t, "DEFAULT_HTTP_CODE", string(DefaultHTTPCode)) } func TestEnvVariable_Lookup(t *testing.T) { @@ -24,6 +25,7 @@ func TestEnvVariable_Lookup(t *testing.T) { {giveEnv: TemplateName}, {giveEnv: ConfigFilePath}, {giveEnv: DefaultErrorPage}, + {giveEnv: DefaultHTTPCode}, } for _, tt := range cases { diff --git a/internal/http/handlers/index/handler.go b/internal/http/handlers/index/handler.go index fceff42..652f627 100644 --- a/internal/http/handlers/index/handler.go +++ b/internal/http/handlers/index/handler.go @@ -17,13 +17,18 @@ type ( ) // NewHandler creates handler for the index page serving. -func NewHandler(e errorsPager, p templatePicker, defaultPageCode string) fasthttp.RequestHandler { +func NewHandler( + e errorsPager, + p templatePicker, + defaultPageCode string, + defaultHTTPCode uint16, +) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { content, err := e.GetPage(p.Pick(), defaultPageCode) if err == nil { ctx.SetContentType("text/html; charset=utf-8") - ctx.SetStatusCode(fasthttp.StatusOK) + ctx.SetStatusCode(int(defaultHTTPCode)) _, _ = ctx.Write(content) return diff --git a/internal/http/server.go b/internal/http/server.go index 5b1da05..791599f 100644 --- a/internal/http/server.go +++ b/internal/http/server.go @@ -66,8 +66,13 @@ type ( // Register server routes, middlewares, etc. // Router docs: -func (s *Server) Register(errorsPager errorsPager, templatePicker templatePicker, defaultPageCode string) { - s.router.GET("/", indexHandler.NewHandler(errorsPager, templatePicker, defaultPageCode)) +func (s *Server) Register( + errorsPager errorsPager, + templatePicker templatePicker, + defaultPageCode string, + defaultHTTPCode uint16, +) { + s.router.GET("/", indexHandler.NewHandler(errorsPager, templatePicker, defaultPageCode, defaultHTTPCode)) s.router.GET("/version", versionHandler.NewHandler(version.Version())) s.router.ANY("/health/live", healthzHandler.NewHandler(checkers.NewLiveChecker())) s.router.GET("/{code}.html", errorpageHandler.NewHandler(errorsPager, templatePicker))