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
|
package main
import (
"encoding/json"
"fmt"
"html/template"
"log"
"net/http"
"regexp"
"os"
"slices"
)
type Config struct {
Port string
Allowed []string
HomeHtml string
MainTemplate string
ErrorTemplate string
}
var config Config
func GetFiles(w http.ResponseWriter, r *http.Request) {
log.Println("Request for:", r.URL.String())
url := fmt.Sprintf("static%s", r.URL.String())
htmlRegex, err := regexp.Compile("^static/.*\\.html$")
if err != nil {
ErrorPage(w, "Internal Server Error", 500)
return
}
if url == "static/" {
url = config.HomeHtml
}
if slices.Contains(config.Allowed, url) {
if htmlRegex.MatchString(url) {
t := template.Must(template.ParseFiles(config.MainTemplate))
html, err := os.ReadFile(url)
if err != nil {
ErrorPage(w, "Internal Server Error", 500)
return
}
t.Execute(w, template.HTML(html))
} else {
http.ServeFile(w, r, url)
}
} else {
ErrorPage(w, "Page Not Found.", 404)
}
}
func ErrorPage(w http.ResponseWriter, message string, code int) {
log.Println(code, message)
t := template.Must(template.ParseFiles(config.ErrorTemplate))
t.Execute(w, struct {
Code int
Message string
}{
Code: code,
Message: message,
})
}
func Usage() {
fmt.Fprintf(os.Stderr, "%s [--port port]\n", os.Args[0])
}
func ParseConfigFile(path string) error {
configJson, err := os.ReadFile("config.json")
if err != nil {
return err
}
err = json.Unmarshal(configJson, &config)
return err
}
func LogConfiguration() {
log.Println("Port:", config.Port)
log.Println("Allowed:")
for i, a := range config.Allowed {
log.Printf("%d: %s\n", i, a)
}
log.Println("HomeHtml:", config.HomeHtml)
log.Println("MainTemplate:", config.MainTemplate)
log.Println("ErrorTemplate:", config.ErrorTemplate)
}
func main() {
portFlagSet := false
port := ":8000"
for i := 1; i < len(os.Args); i++ {
switch os.Args[i] {
case "--port":
if i+1 >= len(os.Args) {
Usage()
} else {
portFlagSet = true
port = ":" + os.Args[i+1]
i++
}
default:
log.Println("Unknown option: ", os.Args[i])
Usage()
}
}
err := ParseConfigFile("config.json")
if err != nil {
panic(err)
}
if !portFlagSet {
port = ":" + config.Port
} else {
config.Port = port
}
LogConfiguration()
http.HandleFunc("/", GetFiles)
log.Fatal(http.ListenAndServe(port, nil))
}
|