11package main
22
33import (
4- "fmt "
4+ "html/template "
55 "net/http"
66 "os"
77 "time"
@@ -11,87 +11,157 @@ import (
1111
1212type server struct {
1313 config * appConfig
14+ mux * http.ServeMux
15+ tmpl * template.Template
1416}
1517
18+ // TemplateData holds all the data needed for the HTML template
19+ type TemplateData struct {
20+ ApplicationName string
21+ ApplicationVersion string
22+ ApplicationMessage string
23+ Color string
24+ Alive bool
25+ Ready bool
26+ RootDelaySeconds int
27+ StartUpDelaySeconds int
28+ TearDownDelaySeconds int
29+ LogToFileOnly bool
30+ ProcessID int
31+ UserID int
32+ Hostname string
33+ CatImageURL string
34+ }
35+
36+ const htmlTemplate = `<!DOCTYPE html>
37+ <html>
38+ <head>
39+ <title>{{.ApplicationName}} {{.ApplicationVersion}}</title>
40+ </head>
41+ <body style='background-color:{{.Color}};'>
42+ <h1>{{.ApplicationName}}</h1>
43+
44+ <h2>Configuration</h2>
45+ Application Version: {{.ApplicationVersion}}<br>
46+ Application Message: {{.ApplicationMessage}}<br>
47+ Application Liveness: {{.Alive}}<br>
48+ Application Readiness: {{.Ready}}<br>
49+ Delay seconds of root endpoint ('/'): {{.RootDelaySeconds}}<br>
50+ Seconds the application needs to start up: {{.StartUpDelaySeconds}}<br>
51+ Seconds the application needs to shut down gracefully: {{.TearDownDelaySeconds}}<br>
52+ Only log to file: {{.LogToFileOnly}}<br>
53+
54+ <h2>Tech Details</h2>
55+ Process Id of the application: {{.ProcessID}}<br>
56+ User Id the application is using: {{.UserID}}<br>
57+ Hostname: {{.Hostname}}<br>
58+
59+ {{if .CatImageURL}}
60+ <h2>The cute cat</h2>
61+ <img src='{{.CatImageURL}}' width='500px'></img>
62+ {{end}}
63+ </body>
64+ </html>`
65+
1666func newServer (appConfig * appConfig ) * server {
67+ // Parse the HTML template
68+ tmpl , err := template .New ("index" ).Parse (htmlTemplate )
69+ if err != nil {
70+ log .Fatalf ("Failed to parse template: %v" , err )
71+ }
72+
73+ // Create a new ServeMux
74+ mux := http .NewServeMux ()
1775
1876 server := & server {
1977 config : appConfig ,
78+ mux : mux ,
79+ tmpl : tmpl ,
2080 }
2181
22- http .HandleFunc ("/" , server .handleRoot )
23- http .HandleFunc ("/favicon.ico" , func (w http.ResponseWriter , r * http.Request ) {
24- http .NotFound (w , r )
25- })
26- http .HandleFunc ("/liveness" , server .handleLiveness )
27- http .HandleFunc ("/readiness" , server .handleReadiness )
82+ // Register handlers with the mux
83+ mux .HandleFunc ("/" , server .handleRoot )
84+ mux .HandleFunc ("/favicon.ico" , server .handleFavicon )
85+ mux .HandleFunc ("/liveness" , server .handleLiveness )
86+ mux .HandleFunc ("/readiness" , server .handleReadiness )
2887
2988 return server
3089}
3190
3291func (s * server ) run () {
33- err := http .ListenAndServe (":8080" , nil )
92+ err := http .ListenAndServe (":8080" , s . mux )
3493 if err != nil {
3594 log .Errorf ("Error on starting the server: '%s'" , err )
3695 }
3796}
3897
3998func (s * server ) handleRoot (w http.ResponseWriter , r * http.Request ) {
4099 log .Info ("Request to root endpoint ('/')" )
100+
41101 if ! s .config .rootEnabled {
42102 w .WriteHeader (http .StatusServiceUnavailable )
43103 log .Info ("Root endpoint ('/') responded with Status Code 503 Service Unavailable due to root endpoint is disabled" )
44- } else {
104+ return
105+ }
106+
107+ // Handle delay if configured
45108 if s .config .rootDelaySeconds > 0 {
46109 for i := 0 ; i < s .config .rootDelaySeconds ; i ++ {
47110 log .Infof ("Delayed Response for %d of %d seconds" , i + 1 , s .config .rootDelaySeconds )
48111 time .Sleep (1 * time .Second )
49112 }
50113 log .Info ("Finished delaying Response" )
51114 }
52- w .Header ().Set ("Content-Type" , "text/html" )
53- fmt .Fprint (w , "<!DOCTYPE html><htlml>" )
54- fmt .Fprintf (w , "<head><title>%s %s</title></head>" , s .config .applicationName , s .config .applicationVersion )
55- fmt .Fprintf (w , "<body style='background-color:%s;'>" , s .config .color )
56- fmt .Fprintf (w , "<h1>%s</h1>" , s .config .applicationName )
57- fmt .Fprint (w , "<h2>Configuration</h2>" )
58- fmt .Fprintf (w , "Application Version: %s<br>" , s .config .applicationVersion )
59- fmt .Fprintf (w , "Application Message: %s<br>" , s .config .applicationMessage )
60- fmt .Fprintf (w , "Application Liveness: %t<br>" , s .config .alive )
61- fmt .Fprintf (w , "Application Readiness: %t<br>" , s .config .ready )
62- fmt .Fprintf (w , "Delay seconds of root endpoint ('/'): %d<br>" , s .config .rootDelaySeconds )
63- fmt .Fprintf (w , "Seconds the application needs to start up: %d<br>" , s .config .startUpDelaySeconds )
64- fmt .Fprintf (w , "Seconds the application needs to shut down gracefuly: %d<br>" , s .config .tearDownDelaySeconds )
65- fmt .Fprintf (w , "Only log to file: %v<br>" , s .config .logToFileOnly )
66-
67- fmt .Fprint (w , "<h2>Tech Details</h2>" )
68- fmt .Fprintf (w , "Process Id of the application: %d<br>" , os .Getpid ())
69- fmt .Fprintf (w , "User Id the application is using: %d<br>" , os .Getuid ())
70- hostName , _ := os .Hostname ()
71- fmt .Fprintf (w , "Hostname: %s<br>" , hostName )
72-
73- if s .config .catImageUrl != "" {
74- fmt .Fprint (w , "<h2>The cute cat</h2>" )
75- fmt .Fprintf (w , "<img src='%s' width='500px'></img>" , s .config .catImageUrl )
115+
116+ // Get hostname
117+ hostname , _ := os .Hostname ()
118+
119+ // Prepare template data
120+ data := TemplateData {
121+ ApplicationName : s .config .applicationName ,
122+ ApplicationVersion : s .config .applicationVersion ,
123+ ApplicationMessage : s .config .applicationMessage ,
124+ Color : s .config .color ,
125+ Alive : s .config .alive ,
126+ Ready : s .config .ready ,
127+ RootDelaySeconds : s .config .rootDelaySeconds ,
128+ StartUpDelaySeconds : s .config .startUpDelaySeconds ,
129+ TearDownDelaySeconds : s .config .tearDownDelaySeconds ,
130+ LogToFileOnly : s .config .logToFileOnly ,
131+ ProcessID : os .Getpid (),
132+ UserID : os .Getuid (),
133+ Hostname : hostname ,
134+ CatImageURL : s .config .catImageUrl ,
76135 }
77136
78- fmt .Fprint (w , "</body></htlml>" )
137+ // Set content type and execute template
138+ w .Header ().Set ("Content-Type" , "text/html" )
139+ if err := s .tmpl .Execute (w , data ); err != nil {
140+ log .Errorf ("Error executing template: %v" , err )
141+ http .Error (w , "Internal Server Error" , http .StatusInternalServerError )
142+ return
143+ }
79144}
145+
146+ func (s * server ) handleFavicon (w http.ResponseWriter , r * http.Request ) {
147+ http .NotFound (w , r )
80148}
81149
82150func (s * server ) handleLiveness (w http.ResponseWriter , r * http.Request ) {
83151 log .Info ("Request to liveness endpoint ('/liveness')" )
152+
84153 if s .config .alive {
85154 w .WriteHeader (http .StatusOK )
86155 log .Info ("Liveness endpoint ('/liveness') responded with Status Code 200 OK" )
87156 } else {
88157 w .WriteHeader (http .StatusInternalServerError )
89- log .Info ("Liveness endpoint ('/liveness') responded with Status Code 503 Service Unavailable " )
158+ log .Info ("Liveness endpoint ('/liveness') responded with Status Code 500 Internal Server Error " )
90159 }
91160}
92161
93162func (s * server ) handleReadiness (w http.ResponseWriter , r * http.Request ) {
94163 log .Info ("Request to readiness endpoint ('/readiness')" )
164+
95165 if s .config .ready {
96166 w .WriteHeader (http .StatusOK )
97167 log .Info ("Readiness endpoint ('/readiness') responded with Status Code 200 OK" )
0 commit comments