From 1f8ae1bcb66f5ff9029612307b882dfe85aa810b Mon Sep 17 00:00:00 2001 From: Physcik Date: Thu, 25 Dec 2025 18:55:59 +0500 Subject: Structure pt 1 --- src/Render/Render.go | 41 +++++++++++++++++++++++++++++ src/Render/Templates.go | 17 ++++++++++++ src/Settings.json | 5 ++++ src/Settings/Settings.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ src/go.mod | 3 +++ src/main.go | 20 +++++++++++++++ 6 files changed, 153 insertions(+) create mode 100644 src/Render/Render.go create mode 100644 src/Render/Templates.go create mode 100644 src/Settings.json create mode 100644 src/Settings/Settings.go create mode 100644 src/go.mod create mode 100644 src/main.go (limited to 'src') diff --git a/src/Render/Render.go b/src/Render/Render.go new file mode 100644 index 0000000..85061d7 --- /dev/null +++ b/src/Render/Render.go @@ -0,0 +1,41 @@ +package render + +import ( + "fmt" + "log/slog" + "net/http" + "strings" + + settings "physick.ru/Settings" +) + +const indexTemplateName string = "index.html" + +func RegisterEndpoints() { + // http.Handle("static/", http.FileServer(http.FS(os.DirFS(settings.Current.StaticLocation)))) + http.HandleFunc("/", mux) +} + +func mux(w http.ResponseWriter, r *http.Request) { + slog.Info("Request", slog.String("URL", r.URL.String())) + if r.URL.String() == "/favicon.ico" { + http.ServeFile(w, r, fmt.Sprintf("%s/favicon.ico", settings.Current.StaticLocation)) + } + if strings.HasPrefix(r.URL.String(), "/static") { + var filePath = strings.Replace(r.URL.String(), "/static", settings.Current.StaticLocation, 1) + http.ServeFile(w, r, filePath) + return + } + render(w, r) +} + +func render(w http.ResponseWriter, r *http.Request) { + var indexTempl, readErr = getTemplateString(indexTemplateName) + if readErr != nil { + slog.Warn("Failed to load template", slog.Any("Error", readErr)) + w.WriteHeader(http.StatusInternalServerError) + return + } + slog.Info("Requested a template") + w.Write([]byte(indexTempl)) +} diff --git a/src/Render/Templates.go b/src/Render/Templates.go new file mode 100644 index 0000000..544a2ac --- /dev/null +++ b/src/Render/Templates.go @@ -0,0 +1,17 @@ +package render + +import ( + "fmt" + "os" + + settings "physick.ru/Settings" +) + +func getTemplateString(templName string) (string, error) { + var fullPath = fmt.Sprintf("%s/%s", settings.Current.TemplatesLocation, templName) + var file, fopenerr = os.ReadFile(fullPath) + if fopenerr != nil { + return "", fopenerr + } + return string(file), nil +} diff --git a/src/Settings.json b/src/Settings.json new file mode 100644 index 0000000..c614305 --- /dev/null +++ b/src/Settings.json @@ -0,0 +1,5 @@ +{ + "Port": ":7000", + "StaticLocation": "../static", + "TemplatesLocation": "../templates" +} diff --git a/src/Settings/Settings.go b/src/Settings/Settings.go new file mode 100644 index 0000000..58daed3 --- /dev/null +++ b/src/Settings/Settings.go @@ -0,0 +1,67 @@ +package settings + +import ( + "encoding/json" + "fmt" + "os" + "strings" +) + +type Settings struct { + Port string + StaticLocation string + TemplatesLocation string +} + +const settingsLocation = "Settings.json" + +var defaultSettings = Settings { + Port: ":6969", + StaticLocation: "../static", + TemplatesLocation: "../templates", +} + + +var Current Settings = Settings{} + +func ReadSettings() { + var file, fopenerr = os.ReadFile(settingsLocation) + if fopenerr != nil { + var success, inintBody = createSettingsFile() + if success { + file = inintBody + } else { + panic(fmt.Sprintf("Unable to load or create settings file. \nOriginal error: %v\n", fopenerr.Error())) + } + } + var data = Settings{} + json.Unmarshal(file, &data) + var validationErr = data.Validate() + if validationErr != nil { + panic(fmt.Sprintf("Failed to load settings file: %s", validationErr.Error())) + } + Current = data +} + +func createSettingsFile() (bool, []byte ) { + var file, err = os.Create(settingsLocation) + if err != nil { + return false, nil + } + defer file.Close() + var inititalData = defaultSettings + var body, jsonerr = json.MarshalIndent(inititalData, "", " ") + if jsonerr != nil { + return false, nil + } + fmt.Fprint(file, string(body)) + return true, body +} + +// Returns an error with the issue description if the settings are invalid +func (base *Settings) Validate() error { + if len(base.Port) == 0 || !strings.Contains(base.Port, ":") { + return fmt.Errorf("The port string is invalid") + } + return nil +} diff --git a/src/go.mod b/src/go.mod new file mode 100644 index 0000000..27c0362 --- /dev/null +++ b/src/go.mod @@ -0,0 +1,3 @@ +module physick.ru + +go 1.25.4 diff --git a/src/main.go b/src/main.go new file mode 100644 index 0000000..c950f14 --- /dev/null +++ b/src/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "log/slog" + "net/http" + + render "physick.ru/Render" + settings "physick.ru/Settings" +) + +func main() { + settings.ReadSettings() + + render.RegisterEndpoints() + + var httpErr = http.ListenAndServe(settings.Current.Port, nil) + if httpErr != nil { + slog.Error("Server error", slog.Any("Message", httpErr)) + } +} -- cgit v1.3