-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
148 lines (125 loc) · 4.37 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// HTTP Server for phasik.tv
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"gopkg.in/yaml.v2"
)
// Startup message returned to the console when the server starts
const startupMessage = `` +
` ___________________` + "\n" +
` / ________ -[]--. \` + "\n" +
" / ,-' `-. \\ \\" + "\n" +
` / ( o ) _) \` + "\n" +
" / `-._________,-'_ /_/-.\\" + "\n" +
` / __ _ Phasik " " " \` + "\n" +
` /_____________________________\` + "\n" +
` "-=-------------------------=-"` + "\n" +
` phasik.tv started!`
// httpMinimalResponse is a struct to hold the minimal amount of data
// required to send a JSON response
type httpMinimalResponse struct {
Status string `json:"status"`
StatusCode int `json:"statusCode"`
Data []byte `json:"data"`
}
// serveFiles is a helper function to serve static files from the ./static
// directory. Allows for special case handling.
// TODO: Use this or delete it
func serveFiles(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.URL.Path)
p := "." + r.URL.Path
if p == "./" {
p = "./static/index.html"
}
http.ServeFile(w, r, p)
}
// response2JSON is a helper function to convert HTTP status codes to JSON
// JSON output is written to the provided io.PipeWriter
func response2JSON(status uint16, in_r *io.PipeReader, out_w *io.PipeWriter) {
response := httpMinimalResponse{
Status: http.StatusText(int(status)),
StatusCode: int(status),
Data: []byte(""),
}
json_enc := json.NewEncoder(out_w)
err := json.NewDecoder(in_r).Decode(&(&response).Data)
if err != nil && err != io.EOF {
fmt.Printf("response2JSON error: %+v\n", err)
json_enc.Encode(httpMinimalResponse{
Status: http.StatusText(http.StatusInternalServerError),
StatusCode: int(http.StatusInternalServerError),
Data: []byte(err.Error()),
})
}
json_enc.Encode(&response)
out_w.Close()
// fmt.Printf("response2JSON: %+v\n", response) // TODO: Debug logging
}
// handleJSON200Response is a helper function to handle JSON responses with a 200 OK code
func handleJSON200Response(w http.ResponseWriter, r *http.Request) {
handleJSONResponse(http.StatusOK, w, r)
}
// handleJSONResponse is a helper function to generate a JSON response from a
// provided HTTP status code.
// The response is written to the provided http.ResponseWriter
// and the request Method & URL.path are gathered and logged from the provided
// *http.Request
func handleJSONResponse(status uint16, w http.ResponseWriter, r *http.Request) {
json_pipe_r, json_pipe_w := io.Pipe()
data_pipe_r, data_pipe_w := io.Pipe()
data_pipe_w.Close()
go response2JSON(http.StatusOK, data_pipe_r, json_pipe_w)
fmt.Printf("%s %s -> ", r.Method, r.URL.Path) // Always log request first in case it causes error
json_resp, err := io.ReadAll(json_pipe_r)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s", json_resp) // if success: first thing logged after "-> "
// TODO: Use this, return it, or delete it
// var resp httpMinimalResponse
// json.Unmarshal(json_resp, &resp)
// TODO: Implement DEBUG logging
// TODO: Maybe implement JSON logging for K8s + ELK
// fmt.Printf("resp (unmarshalled): %+v\n", resp)
// logger.Printf("json_resp: %s", json_resp)
// send JSON response
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, string(json_resp))
}
// main is the entrypoint for the phasik.tv server
func main() {
// logger := log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime) // TODO: Evaluate stdlib log vs logrus vs zerolog ?
fs := http.FileServer(http.Dir("/srv/www"))
http.Handle("/", fs)
http.HandleFunc("/livez", handleJSON200Response)
http.HandleFunc("/readyz", handleJSON200Response)
port := os.Getenv("PORT")
if port == "" {
port = "80"
}
config_file := os.Getenv("CONFIG_FILE")
if config_file == "" {
config_file = "config.yml"
}
yaml_config, cfg_err := os.ReadFile(config_file)
if cfg_err != nil {
panic(cfg_err)
}
var config map[string]interface{}
yaml.Unmarshal(yaml_config, &config)
fmt.Printf("Config: %+v\n", config)
for _, line := range strings.Split(startupMessage, "\n") {
fmt.Println(line)
}
fmt.Printf("Server listening at :%s 🚀\n", port)
err := http.ListenAndServe(fmt.Sprintf(":%s", port), nil)
if err != nil {
panic(err)
}
}