Skip to content

Commit ecee29e

Browse files
committed
Init repo
0 parents  commit ecee29e

File tree

9 files changed

+224
-0
lines changed

9 files changed

+224
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.idea/
2+
.DS_Store

Dockerfile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
FROM golang:1.16.5-alpine as builder
2+
3+
WORKDIR /src
4+
5+
COPY . .
6+
7+
RUN CGO_ENABLED=0 GOOS=linux go build -o nginx-errors .
8+
9+
FROM debian:stretch
10+
11+
RUN apt-get update && \
12+
apt install -y ca-certificates && \
13+
rm -rf /var/lib/apt/lists/*
14+
15+
16+
COPY --from=builder /src/nginx-errors /
17+
18+
COPY www /www
19+
20+
ENTRYPOINT ["/nginx-errors"]

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Nginx Errors
2+
3+
This is an additional ingress nginx's default backend with custom error page.

constant.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package main
2+
3+
const (
4+
FormatHeader = "X-Format"
5+
CodeHeader = "X-Code"
6+
ContentType = "Content-Type"
7+
OriginalURI = "X-Original-URI"
8+
RequestId = "X-Request-ID"
9+
DefaultFormat = "text/html"
10+
DefaultErrorTemplateName = "error.html"
11+
)

env.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
import "os"
4+
5+
// GetEnvAsStringOrFallback returns the env variable for the given key
6+
// and falls back to the given defaultValue if not set
7+
func GetEnvAsStringOrFallback(key, defaultValue string) string {
8+
if v := os.Getenv(key); v != "" {
9+
return v
10+
}
11+
return defaultValue
12+
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/vietanhduong/nginx-errors
2+
3+
go 1.16

hander.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"html/template"
6+
"log"
7+
"net/http"
8+
"strconv"
9+
)
10+
11+
type Response struct {
12+
ErrorCode int `json:"error_code"`
13+
RequestId string `json:"request_id"`
14+
OriginalURI string `json:"original_uri"`
15+
Message string `json:"message"`
16+
}
17+
18+
var ErrorMap = map[int]string{
19+
403: "Access Denied",
20+
404: "Not Found",
21+
413: "Request Too Large",
22+
502: "Bad Gateway",
23+
503: "Service Unavailable Error",
24+
}
25+
26+
func errorHandler(t *template.Template) func(http.ResponseWriter, *http.Request) {
27+
return func(w http.ResponseWriter, r *http.Request) {
28+
w.Header().Set(FormatHeader, r.Header.Get(FormatHeader))
29+
w.Header().Set(CodeHeader, r.Header.Get(CodeHeader))
30+
w.Header().Set(ContentType, r.Header.Get(ContentType))
31+
w.Header().Set(OriginalURI, r.Header.Get(OriginalURI))
32+
w.Header().Set(RequestId, r.Header.Get(RequestId))
33+
34+
format := r.Header.Get(FormatHeader)
35+
if format == "" {
36+
format = DefaultFormat
37+
}
38+
39+
w.Header().Set(ContentType, format)
40+
41+
errCode := r.Header.Get(CodeHeader)
42+
code, err := strconv.Atoi(errCode)
43+
if err != nil {
44+
code = 404
45+
}
46+
w.WriteHeader(code)
47+
48+
message, ok := ErrorMap[code]
49+
if !ok {
50+
message = "Unknown Error"
51+
}
52+
53+
resp := Response{
54+
ErrorCode: code,
55+
RequestId: r.Header.Get(RequestId),
56+
OriginalURI: r.Header.Get(OriginalURI),
57+
Message: message,
58+
}
59+
60+
if format == "application/json" {
61+
respContent, err := json.Marshal(&resp)
62+
if err != nil {
63+
log.Printf("Marshal json error: %v\n", err)
64+
return
65+
}
66+
if _, err = w.Write(respContent); err != nil {
67+
log.Printf("Write response failed with err %v\n", err)
68+
}
69+
return
70+
}
71+
72+
if err = t.ExecuteTemplate(w, DefaultErrorTemplateName, resp); err != nil {
73+
log.Printf("Execute template failed with error: %v\n", err)
74+
}
75+
}
76+
}

main.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"html/template"
6+
"net/http"
7+
)
8+
9+
func main() {
10+
//errFilesPath := GetEnvAsStringOrFallback("ERROR_FILES_PATH", "/www")
11+
12+
t := template.Must(template.ParseGlob("./www/*.html"))
13+
14+
http.HandleFunc("/", errorHandler(t))
15+
16+
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
17+
w.WriteHeader(http.StatusOK)
18+
})
19+
20+
if err := http.ListenAndServe(fmt.Sprintf(":8080"), nil); err != nil {
21+
panic(err)
22+
}
23+
}

www/error.html

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>{{.ErrorCode}} {{.Message}}</title>
6+
<style>
7+
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap');
8+
9+
* {
10+
line-height: 1.2;
11+
margin: 0;
12+
}
13+
14+
html {
15+
color: #888;
16+
display: flex;
17+
font-family: 'Roboto', sans-serif;
18+
height: 100%;
19+
width: 100%;
20+
}
21+
22+
body {
23+
width: 45em;
24+
max-width: 45em;
25+
margin: 0 auto;
26+
}
27+
28+
.container {
29+
margin: 50px 5px 5px 5px;
30+
}
31+
32+
33+
h1 {
34+
color: black;
35+
font-size: 6em;
36+
font-weight: 400;
37+
}
38+
39+
h2 {
40+
color: #c7c7c7;
41+
font-size: 3em;
42+
font-weight: 400;
43+
}
44+
45+
h3 {
46+
color: black;
47+
margin-top: 20px;
48+
font-family: 'Courier New', sans-serif;
49+
font-weight: 300;
50+
}
51+
52+
</style>
53+
</head>
54+
<body>
55+
<div class="container">
56+
<h1>
57+
Error {{ .ErrorCode }}
58+
</h1>
59+
<h2>
60+
{{ .Message }}
61+
</h2>
62+
{{- if .RequestId }}
63+
<h3>
64+
Request ID: {{- .RequestId }}
65+
</h3>
66+
{{- end }}
67+
{{- if .OriginalURI }}
68+
<h3>
69+
Request ID: {{- .OriginalURI }}
70+
</h3>
71+
{{- end }}
72+
</div>
73+
</body>
74+
</html>

0 commit comments

Comments
 (0)