From ef3c387f3961975fed597cbb2504ddef9e567124 Mon Sep 17 00:00:00 2001 From: Captain ALM Date: Sat, 16 Jul 2022 00:53:50 +0100 Subject: [PATCH] Switch over from test to go-info. Improve Makefile and add new compilation fields. --- Makefile | 7 +- cmd/wappcityuni/main.go | 12 ++- conf/serve.go | 1 + config.example.yml | 1 + pageHandler/go-info-page.go | 131 +++++++++++++++++++++++++++ pageHandler/page-handler.go | 31 ++++++- pageHandler/pages.go | 10 +- pageHandler/pages/TestPage.go | 39 -------- pageHandler/utils/buffered-writer.go | 10 ++ utils/info/conf-info.go | 6 ++ utils/info/product-info.go | 13 +++ 11 files changed, 210 insertions(+), 51 deletions(-) create mode 100644 pageHandler/go-info-page.go delete mode 100644 pageHandler/pages/TestPage.go create mode 100644 pageHandler/utils/buffered-writer.go create mode 100644 utils/info/conf-info.go create mode 100644 utils/info/product-info.go diff --git a/Makefile b/Makefile index 471ca81..5c16b1a 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ SHELL := /bin/bash -BIN := dist/wappcityuni -ENTRY_POINT := ./cmd/wappcityuni +PRODUCT_NAME := wappcityuni +BIN := dist/${PRODUCT_NAME} +ENTRY_POINT := ./cmd/${PRODUCT_NAME} HASH := $(shell git rev-parse --short HEAD) COMMIT_DATE := $(shell git show -s --format=%ci ${HASH}) BUILD_DATE := $(shell date '+%Y-%m-%d %H:%M:%S') VERSION := ${HASH} -LD_FLAGS := -s -w -X 'main.buildVersion=${VERSION}' -X 'main.buildDate=${BUILD_DATE}' +LD_FLAGS := -s -w -X 'main.buildVersion=${VERSION}' -X 'main.buildDate=${BUILD_DATE}' -X 'main.buildName=${PRODUCT_NAME}' COMP_BIN := go ifeq ($(OS),Windows_NT) diff --git a/cmd/wappcityuni/main.go b/cmd/wappcityuni/main.go index c29eeb2..bfa643e 100644 --- a/cmd/wappcityuni/main.go +++ b/cmd/wappcityuni/main.go @@ -5,6 +5,7 @@ import ( "github.com/joho/godotenv" "golang.captainalm.com/cityuni-webserver/conf" "golang.captainalm.com/cityuni-webserver/pageHandler" + "golang.captainalm.com/cityuni-webserver/utils/info" "gopkg.in/yaml.v3" "log" "net" @@ -20,13 +21,16 @@ import ( ) var ( - buildVersion = "develop" - buildDate = "" + buildName = "" + buildDescription = "City Uni Portfolio Web APP" + buildVersion = "develop" + buildDate = "" ) func main() { - log.Printf("[Main] Starting up City Uni Portfolio Web APP #%s (%s)\n", buildVersion, buildDate) + log.Printf("[Main] Starting up %s (%s) #%s (%s)\n", buildDescription, buildName, buildVersion, buildDate) y := time.Now() + info.SetupProductInfo(buildName, buildDescription, buildVersion, buildDate) //Hold main thread till safe shutdown exit: wg := &sync.WaitGroup{} @@ -78,6 +82,8 @@ func main() { //Server definitions: var webServer *http.Server var fcgiListen net.Listener + info.ListenSettings = configYml.Listen + info.ServeSettings = configYml.Serve switch strings.ToLower(configYml.Listen.WebMethod) { case "http": webServer = &http.Server{Handler: pageHandler.GetRouter(configYml)} diff --git a/conf/serve.go b/conf/serve.go index 96a4125..e68fb79 100644 --- a/conf/serve.go +++ b/conf/serve.go @@ -5,5 +5,6 @@ type ServeYaml struct { Domains []string `yaml:"domains"` RangeSupported bool `yaml:"rangeSupported"` FilterURLQueries bool `yaml:"filterURLQueries"` + EnableGoInfoPage bool `yaml:"enableGoInfoPage"` CacheSettings CacheSettingsYaml `yaml:"cacheSettings"` } diff --git a/config.example.yml b/config.example.yml index a8afee8..e49631e 100644 --- a/config.example.yml +++ b/config.example.yml @@ -5,6 +5,7 @@ listen: identify: true serve: rangeSupported: true + enableGoInfoPage: true cacheSettings: enableContentsCaching: true enableContentsCachePurge: true diff --git a/pageHandler/go-info-page.go b/pageHandler/go-info-page.go new file mode 100644 index 0000000..378d94d --- /dev/null +++ b/pageHandler/go-info-page.go @@ -0,0 +1,131 @@ +package pageHandler + +import ( + "golang.captainalm.com/cityuni-webserver/conf" + "golang.captainalm.com/cityuni-webserver/pageHandler/utils" + "golang.captainalm.com/cityuni-webserver/utils/info" + "html/template" + "net/url" + "os" + "path" + "runtime" + "sync" + "time" +) + +const templateName = "goinfo.go.html" + +func newGoInfoPage(handlerIn *PageHandler, dataStore string, cacheTemplates bool) *goInfoPage { + var ptm *sync.Mutex + if cacheTemplates { + ptm = &sync.Mutex{} + } + return &goInfoPage{ + Handler: handlerIn, + DataStore: dataStore, + CacheTemplate: cacheTemplates, + PageTemplateMutex: ptm, + } +} + +type goInfoPage struct { + Handler *PageHandler + DataStore string + CacheTemplate bool + PageTemplateMutex *sync.Mutex + PageTemplate *template.Template +} + +type goInfoTemplateMarshal struct { + FullOutput bool + RegisteredPages []string + CachedPages []string + ProductName string + ProductDescription string + BuildVersion string + BuildDate string + GoVersion string + GoRoutineNum int + GoCGoCallNum int64 + NumCPU int + GoRoot string + GoMaxProcs int + ListenSettings conf.ListenYaml + ServeSettings conf.ServeYaml +} + +func (gipg *goInfoPage) GetPath() string { + return "/goinfo.go" +} + +func (gipg *goInfoPage) GetSupportedURLParameters() []string { + return []string{"full"} +} + +func (gipg *goInfoPage) GetLastModified() time.Time { + return time.Now() +} + +func (gipg *goInfoPage) GetContents(urlParameters url.Values) (contentType string, contents []byte, canCache bool) { + theTemplate, err := gipg.getPageTemplate() + if err != nil { + return "text/plain", []byte("Cannot Get Info.\r\n" + err.Error()), false + } + theBuffer := &utils.BufferedWriter{} + err = theTemplate.ExecuteTemplate(theBuffer, templateName, &goInfoTemplateMarshal{ + FullOutput: urlParameters.Has("full"), + RegisteredPages: gipg.Handler.GetRegisteredPages(), + CachedPages: gipg.Handler.GetCachedPages(), + ProductName: info.BuildName, + ProductDescription: info.BuildDescription, + BuildVersion: info.BuildVersion, + BuildDate: info.BuildDate, + GoVersion: runtime.Version(), + GoRoutineNum: runtime.NumGoroutine(), + GoCGoCallNum: runtime.NumCgoCall(), + NumCPU: runtime.NumCPU(), + GoRoot: runtime.GOROOT(), + GoMaxProcs: runtime.GOMAXPROCS(0), + ListenSettings: info.ListenSettings, + ServeSettings: info.ServeSettings, + }) + if err != nil { + return "text/plain", []byte("Cannot Get Info.\r\n" + err.Error()), false + } + return "text/html", theBuffer.Data, false +} + +func (gipg *goInfoPage) PurgeTemplate() { + if gipg.CacheTemplate { + gipg.PageTemplateMutex.Lock() + gipg.PageTemplate = nil + gipg.PageTemplateMutex.Unlock() + } +} + +func (gipg *goInfoPage) getPageTemplate() (*template.Template, error) { + if gipg.CacheTemplate { + gipg.PageTemplateMutex.Lock() + defer gipg.PageTemplateMutex.Unlock() + } + if gipg.PageTemplate == nil { + thePath := templateName + if gipg.DataStore != "" { + thePath = path.Join(gipg.DataStore, thePath) + } + loadedData, err := os.ReadFile(thePath) + if err != nil { + return nil, err + } + tmpl, err := template.New(templateName).Parse(string(loadedData)) + if err != nil { + return nil, err + } + if gipg.CacheTemplate { + gipg.PageTemplate = tmpl + } + return tmpl, nil + } else { + return gipg.PageTemplate, nil + } +} diff --git a/pageHandler/page-handler.go b/pageHandler/page-handler.go index b43a28e..0faffd7 100644 --- a/pageHandler/page-handler.go +++ b/pageHandler/page-handler.go @@ -36,14 +36,19 @@ func NewPageHandler(config conf.ServeYaml) *PageHandler { thePCCMap = make(map[string]*CachedPage) theMutex = &sync.RWMutex{} } - return &PageHandler{ + toReturn := &PageHandler{ PageContentsCache: thePCCMap, - PageProviders: GetProviders(config.CacheSettings.EnableTemplateCaching, config.DataStorage), pageContentsCacheRWMutex: theMutex, RangeSupported: config.RangeSupported, FilterURLQueries: config.FilterURLQueries, CacheSettings: config.CacheSettings, } + if config.EnableGoInfoPage { + toReturn.PageProviders = GetProviders(config.CacheSettings.EnableTemplateCaching, config.DataStorage, toReturn) + } else { + toReturn.PageProviders = GetProviders(config.CacheSettings.EnableTemplateCaching, config.DataStorage, nil) + } + return toReturn } func (ph *PageHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { @@ -296,3 +301,25 @@ func (ph *PageHandler) getAllowedMethodsForPath(pathIn string) []string { } } } + +func (ph *PageHandler) GetRegisteredPages() []string { + pages := make([]string, len(ph.PageProviders)) + index := 0 + for s := range ph.PageProviders { + pages[index] = s + index++ + } + return pages +} + +func (ph *PageHandler) GetCachedPages() []string { + ph.pageContentsCacheRWMutex.Lock() + defer ph.pageContentsCacheRWMutex.Unlock() + pages := make([]string, len(ph.PageContentsCache)) + index := 0 + for s := range ph.PageContentsCache { + pages[index] = s + index++ + } + return pages +} diff --git a/pageHandler/pages.go b/pageHandler/pages.go index 38f7666..3b7197a 100644 --- a/pageHandler/pages.go +++ b/pageHandler/pages.go @@ -1,13 +1,15 @@ package pageHandler -import "golang.captainalm.com/cityuni-webserver/pageHandler/pages" - var providers map[string]PageProvider -func GetProviders(cacheTemplates bool, dataStorage string) map[string]PageProvider { +func GetProviders(cacheTemplates bool, dataStorage string, pageHandler *PageHandler) map[string]PageProvider { if providers == nil { providers = make(map[string]PageProvider) - providers["/test.go"] = pages.NewTestPage() //Test Page + if pageHandler != nil { + infoPage := newGoInfoPage(pageHandler, dataStorage, cacheTemplates) + providers[infoPage.GetPath()] = infoPage //Go Information Page + } + //Add the providers in the pages sub package } return providers diff --git a/pageHandler/pages/TestPage.go b/pageHandler/pages/TestPage.go deleted file mode 100644 index 62d8e73..0000000 --- a/pageHandler/pages/TestPage.go +++ /dev/null @@ -1,39 +0,0 @@ -package pages - -import ( - "net/url" - "time" -) - -var startTime = time.Now() - -func NewTestPage() *TestPage { - return &TestPage{} -} - -type TestPage struct { -} - -func (tp *TestPage) GetPath() string { - return "/test.go" -} - -func (tp *TestPage) GetSupportedURLParameters() []string { - return []string{"test"} -} - -func (tp *TestPage) GetLastModified() time.Time { - return startTime -} - -func (tp *TestPage) GetContents(urlParameters url.Values) (contentType string, contents []byte, canCache bool) { - if val, ok := urlParameters["test"]; ok { - if len(val) > 0 { - return "text/plain", ([]byte)("Testing!\r\n" + val[0]), len(val) == 1 - } - } - return "text/plain", ([]byte)("Testing!"), true -} - -func (tp *TestPage) PurgeTemplate() { -} diff --git a/pageHandler/utils/buffered-writer.go b/pageHandler/utils/buffered-writer.go new file mode 100644 index 0000000..4d31a7f --- /dev/null +++ b/pageHandler/utils/buffered-writer.go @@ -0,0 +1,10 @@ +package utils + +type BufferedWriter struct { + Data []byte +} + +func (c *BufferedWriter) Write(p []byte) (n int, err error) { + c.Data = append(c.Data, p...) + return len(p), nil +} diff --git a/utils/info/conf-info.go b/utils/info/conf-info.go new file mode 100644 index 0000000..9023b3b --- /dev/null +++ b/utils/info/conf-info.go @@ -0,0 +1,6 @@ +package info + +import "golang.captainalm.com/cityuni-webserver/conf" + +var ListenSettings conf.ListenYaml +var ServeSettings conf.ServeYaml diff --git a/utils/info/product-info.go b/utils/info/product-info.go new file mode 100644 index 0000000..fcf8ad4 --- /dev/null +++ b/utils/info/product-info.go @@ -0,0 +1,13 @@ +package info + +var BuildName string +var BuildDescription string +var BuildVersion string +var BuildDate string + +func SetupProductInfo(buildName string, buildDescription string, buildVersion string, buildDate string) { + BuildName = buildName + BuildDescription = buildDescription + BuildVersion = buildVersion + BuildDate = buildDate +}