diff --git a/Dockerfile b/Dockerfile index 27199d3..5efcc84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,4 +26,4 @@ COPY --from=build /go/src/github.com/raspbernetes/custom-error-pages . USER nonroot:nonroot -ENTRYPOINT ["/custom-error-pages"] +ENTRYPOINT ["/custom-error-pages"] \ No newline at end of file diff --git a/main.go b/main.go index 28ab861..5fea4b6 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,19 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package main import ( @@ -10,7 +26,7 @@ import ( "strconv" "strings" "time" - + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) @@ -45,31 +61,51 @@ const ( // ErrFilesPathVar is the name of the environment variable indicating // the location on disk of files served by the handler. ErrFilesPathVar = "ERROR_FILES_PATH" + + // DefaultFormatVar is the name of the environment variable indicating + // the default error MIME type that should be returned if either the + // client does not specify an Accept header, or the Accept header provided + // cannot be mapped to a file extension. + DefaultFormatVar = "DEFAULT_RESPONSE_FORMAT" ) +func init() { + prometheus.MustRegister(requestCount) + prometheus.MustRegister(requestDuration) +} + func main() { - errFilesPath := "./pages" + errFilesPath := "/www" if os.Getenv(ErrFilesPathVar) != "" { errFilesPath = os.Getenv(ErrFilesPathVar) } - http.HandleFunc("/", errorHandler(errFilesPath)) + defaultFormat := "text/html" + if os.Getenv(DefaultFormatVar) != "" { + defaultFormat = os.Getenv(DefaultFormatVar) + } + + http.HandleFunc("/", errorHandler(errFilesPath, defaultFormat)) http.Handle("/metrics", promhttp.Handler()) http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) - w.Write([]byte("OK")) - fmt.Fprint(w) }) http.ListenAndServe(fmt.Sprintf(":8080"), nil) } -func errorHandler(path string) func(http.ResponseWriter, *http.Request) { +func errorHandler(path, defaultFormat string) func(http.ResponseWriter, *http.Request) { + defaultExts, err := mime.ExtensionsByType(defaultFormat) + if err != nil || len(defaultExts) == 0 { + panic("couldn't get file extension for default format") + } + defaultExt := defaultExts[0] + return func(w http.ResponseWriter, r *http.Request) { start := time.Now() - ext := "html" + ext := defaultExt if os.Getenv("DEBUG") != "" { w.Header().Set(FormatHeader, r.Header.Get(FormatHeader)) @@ -85,14 +121,14 @@ func errorHandler(path string) func(http.ResponseWriter, *http.Request) { format := r.Header.Get(FormatHeader) if format == "" { - format = "text/html" + format = defaultFormat log.Printf("format not specified. Using %v", format) } cext, err := mime.ExtensionsByType(format) if err != nil { log.Printf("unexpected error reading media type extension: %v. Using %v", err, ext) - format = "text/html" + format = defaultFormat } else if len(cext) == 0 { log.Printf("couldn't get media type extension. Using %v", ext) } else { @@ -111,6 +147,10 @@ func errorHandler(path string) func(http.ResponseWriter, *http.Request) { if !strings.HasPrefix(ext, ".") { ext = "." + ext } + // special case for compatibility + if ext == ".htm" { + ext = ".html" + } file := fmt.Sprintf("%v/%v%v", path, code, ext) f, err := os.Open(file) if err != nil { diff --git a/metrics.go b/metrics.go index 53bb240..1ca3b2a 100644 --- a/metrics.go +++ b/metrics.go @@ -1,3 +1,19 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + // Collect and display prometheus metrics package main diff --git a/pages/401.html b/www/401.html similarity index 100% rename from pages/401.html rename to www/401.html diff --git a/www/401.json b/www/401.json new file mode 100644 index 0000000..b881e36 --- /dev/null +++ b/www/401.json @@ -0,0 +1 @@ +{ "message": "You do not have permission to perform this request" } diff --git a/pages/403.html b/www/403.html similarity index 100% rename from pages/403.html rename to www/403.html diff --git a/pages/404.html b/www/404.html similarity index 100% rename from pages/404.html rename to www/404.html diff --git a/www/404.json b/www/404.json new file mode 100644 index 0000000..36f3e75 --- /dev/null +++ b/www/404.json @@ -0,0 +1 @@ +{ "message": "The page you're looking for could not be found" } \ No newline at end of file diff --git a/pages/500.html b/www/500.html similarity index 100% rename from pages/500.html rename to www/500.html diff --git a/www/500.json b/www/500.json new file mode 100644 index 0000000..9c07701 --- /dev/null +++ b/www/500.json @@ -0,0 +1 @@ +{ "message": "An internal server error has been occured" } \ No newline at end of file diff --git a/pages/503.html b/www/503.html similarity index 100% rename from pages/503.html rename to www/503.html diff --git a/www/503.json b/www/503.json new file mode 100644 index 0000000..ac00eff --- /dev/null +++ b/www/503.json @@ -0,0 +1 @@ +{ "message": "The server is temporarily unavailable due maintenance" } \ No newline at end of file