From 4c063b74bac9ccf6b20303c9bd2987edb24f63f3 Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Wed, 31 Aug 2022 17:26:36 +0200 Subject: [PATCH] chore: commit save point --- Makefile.example | 72 ++++++++++ application/source/constants/context.go | 2 + application/source/server/cache.go | 44 ++++++ application/source/server/inject.go | 128 ++++++++++++++++++ application/source/server/routing.go | 15 +- application/source/watch/resources.go | 9 ++ application/source/websocket/connection.go | 42 +----- development/examples/e1/config.yaml | 4 + development/examples/e1/src/main.js | 5 +- development/examples/e1/web/hello.html | 5 +- development/examples/e1/web/scripts/bundle.js | 4 +- .../examples/e1/web/scripts/bundle.js.map | 4 +- 12 files changed, 287 insertions(+), 47 deletions(-) create mode 100644 Makefile.example create mode 100644 application/source/server/cache.go create mode 100644 application/source/server/inject.go diff --git a/Makefile.example b/Makefile.example new file mode 100644 index 0000000..c9d8453 --- /dev/null +++ b/Makefile.example @@ -0,0 +1,72 @@ +############################################################################################# +############################################################################################# +## +## PROJECT-DEFINITIONS +## +############################################################################################# +############################################################################################# + +COMPONENT_NAME := Monster + +############################################################################################# +############################################################################################# +## +## MORE GENERAL BLOCK WITH STANDARD DEFINITIONS +## +############################################################################################# +############################################################################################# + +# get Makefile directory name: http://stackoverflow.com/a/5982798/376773 +THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) +PROJECT_ROOT:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)/ +THIS_MAKEFILE:=$(PROJECT_ROOT)$(THIS_MAKEFILE_PATH) + + +-include $(PROJECT_ROOT)project.mk + + +## Define the location of Makefiles +MAKEFILE_IMPORT_PATH?=$(PROJECT_ROOT)makefiles/ +-include $(MAKEFILE_IMPORT_PATH)project.mk + +############################################################################################# +############################################################################################# +## +## INCLUSION OF VARIOUS STANDARD RULES +## +############################################################################################# +############################################################################################# + +include $(MAKEFILE_IMPORT_PATH)directories-standard.mk +#include $(MAKEFILE_IMPORT_PATH)jsdoc.mk +include $(MAKEFILE_IMPORT_PATH)output.mk +include $(MAKEFILE_IMPORT_PATH)placeholder.mk +#include $(MAKEFILE_IMPORT_PATH)s3.mk +#include $(MAKEFILE_IMPORT_PATH)license-agpl3.mk +#include $(MAKEFILE_IMPORT_PATH)jsdoc-json.mk +#include $(MAKEFILE_IMPORT_PATH)go.mk +include $(MAKEFILE_IMPORT_PATH)gitignore.mk +include $(MAKEFILE_IMPORT_PATH)color.mk +include $(MAKEFILE_IMPORT_PATH)version.mk +#include $(MAKEFILE_IMPORT_PATH)node.mk +include $(MAKEFILE_IMPORT_PATH)terminal.mk +#include $(MAKEFILE_IMPORT_PATH)target-go-fetch-licenses.mk +#include $(MAKEFILE_IMPORT_PATH)target-deploy-tool.mk +#include $(MAKEFILE_IMPORT_PATH)target-jsdoc-build.mk +#include $(MAKEFILE_IMPORT_PATH)target-jekyll.mk +#include $(MAKEFILE_IMPORT_PATH)target-minerva.mk +#include $(MAKEFILE_IMPORT_PATH)target-docman.mk +#include $(MAKEFILE_IMPORT_PATH)target-node-build.mk +#include $(MAKEFILE_IMPORT_PATH)target-caddy.mk +include $(MAKEFILE_IMPORT_PATH)target-update-makefiles.mk +include $(MAKEFILE_IMPORT_PATH)target-help.mk +#include $(MAKEFILE_IMPORT_PATH)target-go-build.mk +#include $(MAKEFILE_IMPORT_PATH)target-node-test.mk +#include $(MAKEFILE_IMPORT_PATH)target-npm-publish.mk +include $(MAKEFILE_IMPORT_PATH)target-git.mk +include $(MAKEFILE_IMPORT_PATH)target-init-standard.mk +include $(MAKEFILE_IMPORT_PATH)target-variable.mk +include $(MAKEFILE_IMPORT_PATH)terminal-check.mk + + +############################################################################################# diff --git a/application/source/constants/context.go b/application/source/constants/context.go index 78990c5..1e89c9b 100644 --- a/application/source/constants/context.go +++ b/application/source/constants/context.go @@ -10,3 +10,5 @@ const AppStyleDirectory = "styles" const AppScriptDirectory = "scripts" const StandardCacheControl = "no-cache, no-store, must-revalidate" + +const WebsocketPath = "/websocketPath" diff --git a/application/source/server/cache.go b/application/source/server/cache.go new file mode 100644 index 0000000..a61ba6f --- /dev/null +++ b/application/source/server/cache.go @@ -0,0 +1,44 @@ +package server + +import ( + "net/http" + "time" +) + +var epoch = time.Unix(0, 0).Format(time.RFC1123) + +var noCacheHeaders = map[string]string{ + "Expires": epoch, + "Cache-Control": "no-cache, private, max-age=0", + "Pragma": "no-cache", + "X-Accel-Expires": "0", +} + +var etagHeaders = []string{ + "ETag", + "If-Modified-Since", + "If-Match", + "If-None-Match", + "If-Range", + "If-Unmodified-Since", +} + +func NoCache(h http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + // Delete any ETag headers that may have been set + for _, v := range etagHeaders { + if r.Header.Get(v) != "" { + r.Header.Del(v) + } + } + + // Set our NoCache headers + for k, v := range noCacheHeaders { + w.Header().Set(k, v) + } + + h.ServeHTTP(w, r) + } + + return http.HandlerFunc(fn) +} diff --git a/application/source/server/inject.go b/application/source/server/inject.go new file mode 100644 index 0000000..dcedc6b --- /dev/null +++ b/application/source/server/inject.go @@ -0,0 +1,128 @@ +package server + +import ( + "gitlab.schukai.com/oss/utilities/conan/configuration" + "gitlab.schukai.com/oss/utilities/conan/constants" + "gitlab.schukai.com/oss/utilities/conan/logging" + "net/http" + "os" + "regexp" + "strings" +) + +func injectHandler(next http.Handler) http.Handler { + + fn := func(w http.ResponseWriter, r *http.Request) { + + if strings.HasSuffix(r.URL.Path, ".html") { + + path := configuration.GetServerWebPath() + "/" + r.URL.Path + p, err := os.ReadFile(path) + if err != nil { + logging.LogError("injectHandler error %s", err.Error()) + return + } + + p = injectScript(p) + + w.Header().Set("Content-Type", "text/html") + w.Write(p) + + return + + } + + next.ServeHTTP(w, r) + + } + + return http.HandlerFunc(fn) + +} + +var script string + +func init() { + + script = `<head> + <script type="module"> + + try { + let counter = 0; + let socket + let url = "" + if (document.location.protocol == 'https:') { + url = 'wss://' + } else { + url = 'ws://' + } + url += document.location.host + "{{ constants.WebsocketPath }}"; + + function connectWebsocket() { + + if (socket) { + socket.close() + } + + if (counter++ > 20) { + console.error("Failed 20 times to connect to websocket. Giving up.") + return + } + + + socket = new WebSocket(url) + + socket.onopen = function (e) { + console.log("[conan] Connection established"); + counter = 0 + }; + + socket.onmessage = function (event) { + console.log("[conan] Data received from server: " + event?.data); + + if (event?.data == "reload") { + console.log("[conan] Reloading page") + window.location.reload(); + } + }; + + socket.onclose = function (event) { + if (event.wasClean) { + console.log("[conan] Connection closed cleanly, code=" + event?.code + " reason=" + event?.reason + ""); + } else { + console.error("[conan] Connection died"); + setTimeout(connectWebsocket, 3000*counter) + } + }; + + socket.onerror = function (error) { + console.error("[conan] " + error?.message); + }; + + } + + document.addEventListener("DOMContentLoaded", () => { + connectWebsocket() + }) + + } catch (e) { + console.error(e) + } + + + </script>` + + script = strings.Replace(script, "{{ constants.WebsocketPath }}", constants.WebsocketPath, -1) + +} + +func injectScript(p []byte) []byte { + + s := string(p) + + reg := regexp.MustCompile(`<head>`) + s = reg.ReplaceAllString(s, script) + + return []byte(s) + +} diff --git a/application/source/server/routing.go b/application/source/server/routing.go index 6ba8265..f781697 100644 --- a/application/source/server/routing.go +++ b/application/source/server/routing.go @@ -2,11 +2,14 @@ package server import ( "crypto/tls" + "gitea.com/go-chi/session" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "gitlab.schukai.com/oss/utilities/conan/configuration" + "gitlab.schukai.com/oss/utilities/conan/constants" "gitlab.schukai.com/oss/utilities/conan/header" "gitlab.schukai.com/oss/utilities/conan/logging" + "gitlab.schukai.com/oss/utilities/conan/websocket" "net/http" ) @@ -25,12 +28,16 @@ func getRouter() *chi.Mux { router.Use(middleware.Compress(5)) router.Use(logging.LoggerMiddleware) router.Use(reloadMiddleware) + router.Use(NoCache) - router.Handle("/*", http.FileServer( - http.Dir(configuration.GetServerWebPath()+"/"))) + router.Use(session.Sessioner()) - return router + router.Handle(constants.WebsocketPath, websocket.GetWebsocketHandler()) -} + //fs := NoListFileSystem{http.Dir(configuration.GetServerWebPath() + "/")} + // router.Handle("*.html", injectHandler(http.FileServer(http.Dir(configuration.GetServerWebPath()+"/")))) + router.Handle("/*", injectHandler(http.FileServer(http.Dir(configuration.GetServerWebPath()+"/")))) + return router +} diff --git a/application/source/watch/resources.go b/application/source/watch/resources.go index 6647ce2..03538ce 100644 --- a/application/source/watch/resources.go +++ b/application/source/watch/resources.go @@ -7,6 +7,7 @@ import ( "gitlab.schukai.com/oss/utilities/conan/configuration" "gitlab.schukai.com/oss/utilities/conan/constants" "gitlab.schukai.com/oss/utilities/conan/logging" + "gitlab.schukai.com/oss/utilities/conan/websocket" "os" "path" "path/filepath" @@ -65,6 +66,12 @@ func executeWatchAction(watchPath string) { } } + if w.Command == "" { + logging.LogInfo("watching: no command defined for %s", watchPath) + websocket.SendReloadMessage() + continue + } + logging.LogDebug("watching: execute watch action: %s", w.Command) t, err := template.New("command").Parse(w.Command) @@ -109,6 +116,8 @@ func executeWatchAction(watchPath string) { r, err := result.String() logging.LogDebug("%s", r) + websocket.SendReloadMessage() + if err != nil { logging.LogError("watching: execute watch action error: %v", err.Error()) continue diff --git a/application/source/websocket/connection.go b/application/source/websocket/connection.go index 14c190b..01eb4dd 100644 --- a/application/source/websocket/connection.go +++ b/application/source/websocket/connection.go @@ -14,20 +14,6 @@ var ( connections = make(map[string]*websocket.Conn) ) -//func getCmd(input string) string { -// inputArr := strings.Split(input, " ") -// return inputArr[0] -//} -// -//func getMessage(input string) string { -// inputArr := strings.Split(input, " ") -// var result string -// for i := 1; i < len(inputArr); i++ { -// result += inputArr[i] -// } -// return result -//} - func SendMessageToAll(message []byte) { for _, conn := range connections { @@ -45,6 +31,10 @@ func closeConnection(session string) error { return nil } +func SendReloadMessage() { + SendMessageToAll([]byte("reload")) +} + func GetWebsocketHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -69,11 +59,6 @@ func GetWebsocketHandler() http.Handler { closeConnection(session) }() - //if sessionStore.Get("user") == nil { - // http.Error(w, "Forbidden", http.StatusForbidden) - // return - //} - // Continuosly read and write message for { mt, message, err := conn.ReadMessage() @@ -87,25 +72,6 @@ func GetWebsocketHandler() http.Handler { } fmt.Println(mt, string(message), "!!!!!!!!!!!!!!!!!!") - //input := string(message) - //cmd := getCmd(input) - //msg := getMessage(input) - //if cmd == "x" { - // todoList = append(todoList, msg) - //} else if cmd == "done" { - // updateTodoList(msg) - //} - //output := "Current Todos: \n" - //for _, todo := range todoList { - // output += "\n - " + todo + "\n" - //} - //output += "\n----------------------------------------" - //message = []byte(output) - //err = conn.WriteMessage(mt, message) - //if err != nil { - // log.Println("write failed:", err) - // break - //} } }) } diff --git a/development/examples/e1/config.yaml b/development/examples/e1/config.yaml index 84514f3..0b0f8b8 100644 --- a/development/examples/e1/config.yaml +++ b/development/examples/e1/config.yaml @@ -22,6 +22,10 @@ Server: Exclude: - ~$ - ^\. + - Path: web + Exclude: + - ~$ + - ^\. Flags: FollowSymlinks: true diff --git a/development/examples/e1/src/main.js b/development/examples/e1/src/main.js index a657bdc..8e3ac04 100644 --- a/development/examples/e1/src/main.js +++ b/development/examples/e1/src/main.js @@ -1 +1,4 @@ -console.log('Hello ME!?'); \ No newline at end of file +document.addEventListener("DOMContentLoaded", () => { + document.querySelector("#app").innerHTML = "Hello!!! World?!"; +}) +// Language: javascript \ No newline at end of file diff --git a/development/examples/e1/web/hello.html b/development/examples/e1/web/hello.html index 4e8540f..f82764d 100644 --- a/development/examples/e1/web/hello.html +++ b/development/examples/e1/web/hello.html @@ -6,5 +6,8 @@ <script src="scripts/bundle.js"></script> </head> <body> - <h1>Hello World</h1> + <h1>Hello ...ddd</h1> + +<div id="app"></div> + </body> diff --git a/development/examples/e1/web/scripts/bundle.js b/development/examples/e1/web/scripts/bundle.js index b5d19a8..4bd7bb6 100644 --- a/development/examples/e1/web/scripts/bundle.js +++ b/development/examples/e1/web/scripts/bundle.js @@ -1,5 +1,7 @@ (() => { // src/main.js - console.log("Hello ME!?"); + document.addEventListener("DOMContentLoaded", () => { + document.querySelector("#app").innerHTML = "Hello!!! World?!"; + }); })(); //# sourceMappingURL=bundle.js.map diff --git a/development/examples/e1/web/scripts/bundle.js.map b/development/examples/e1/web/scripts/bundle.js.map index e98b515..11dffab 100644 --- a/development/examples/e1/web/scripts/bundle.js.map +++ b/development/examples/e1/web/scripts/bundle.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../src/main.js"], - "sourcesContent": ["console.log('Hello ME!?');"], - "mappings": ";;AAAA,UAAQ,IAAI,YAAY;", + "sourcesContent": ["document.addEventListener(\"DOMContentLoaded\", () => {\n document.querySelector(\"#app\").innerHTML = \"Hello!!! World?!\";\n})\n// Language: javascript "], + "mappings": ";;AAAA,WAAS,iBAAiB,oBAAoB,MAAM;AAChD,aAAS,cAAc,MAAM,EAAE,YAAY;AAAA,EAC/C,CAAC;", "names": [] } -- GitLab