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)) }