From 44e7e634eb7c92b2187ca90975c67fa464183e19 Mon Sep 17 00:00:00 2001 From: ernest micklei Date: Thu, 25 Sep 2025 12:49:54 +0200 Subject: [PATCH 01/11] initial --- service.go | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/service.go b/service.go index 07b0852..7fe0011 100644 --- a/service.go +++ b/service.go @@ -44,6 +44,7 @@ func (s *service) init() { type service struct { explorer *explorer indexTemplate *template.Template + httpServer *http.Server } // NewService creates a new to explore one or more values (structures). @@ -53,6 +54,36 @@ func NewService(labelValuePairs ...any) Service { return s } +// Break will listen and serve on the given http port and path. +// it accepts 0 or 1 Options to override defaults. +// The explorer page will have a button "Resume" that stops the server +// and unblocks the go-routine that started it. +func (s *service) Break(opts ...Options) { + if len(opts) > 0 { + s.explorer.options = &opts[0] + } + port := s.explorer.options.httpPort() + serveMux := s.explorer.options.serveMux() + rootPath := s.explorer.options.rootPath() + serveMux.Handle(rootPath, s) + server := &http.Server{ + Addr: fmt.Sprintf(":%d", port), + Handler: serveMux, + } + s.httpServer = server + if err := server.ListenAndServe(); err != nil { + slog.Error("[structexplorer] failed to start service", "err", err) + } +} + +func (s *service) resume() { + if s.httpServer == nil { + return + } + s.httpServer.Close() + s.httpServer = nil +} + // Start will listen and serve on the given http port and path. // it accepts 0 or 1 Options to override defaults. func (s *service) Start(opts ...Options) { @@ -64,7 +95,7 @@ func (s *service) Start(opts ...Options) { rootPath := s.explorer.options.rootPath() slog.Info(fmt.Sprintf("starting go struct explorer at http://localhost:%d%s on %v", port, rootPath, s.explorer.rootKeys())) serveMux.Handle(rootPath, s) - if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil { + if err := http.ListenAndServe(fmt.Sprintf(":%d", port), serveMux); err != nil { slog.Error("[structexplorer] failed to start service", "err", err) } } @@ -204,6 +235,10 @@ func (s *service) serveInstructions(w http.ResponseWriter, r *http.Request) { case "clear": s.explorer.removeNonRootObjects() return + case "resume": + s.resume() + return + default: slog.Warn("[structexplorer] invalid direction", "action", cmd.Action) http.Error(w, "invalid action", http.StatusBadRequest) From 8162b3ae92c020f03e5ecee89ac9a06e06305218 Mon Sep 17 00:00:00 2001 From: ernest micklei Date: Thu, 25 Sep 2025 14:44:41 +0200 Subject: [PATCH 02/11] add example break --- examples/break/main_test.go | 18 ++++++++++++++++++ index_tmpl.html | 3 +++ open.go | 21 +++++++++++++++++++++ script.js | 14 ++++++++++++-- service.go | 12 ++++++++---- 5 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 examples/break/main_test.go create mode 100644 open.go diff --git a/examples/break/main_test.go b/examples/break/main_test.go new file mode 100644 index 0000000..4665051 --- /dev/null +++ b/examples/break/main_test.go @@ -0,0 +1,18 @@ +package main + +import ( + "log" + "testing" + + "github.com/emicklei/structexplorer" +) + +func TestWithBreak(t *testing.T) { + target := struct{ Field string }{Field: "hello"} + + log.Println("before opening the explorer to see state") + + structexplorer.NewService("debugging", target).Break() + + log.Println("after opening the explorer to see state") +} diff --git a/index_tmpl.html b/index_tmpl.html index 0503364..c5f85af 100644 --- a/index_tmpl.html +++ b/index_tmpl.html @@ -121,6 +121,9 @@ 🔄 +