diff --git a/Makefile b/Makefile index 243a23f..28b3e31 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ endif APP_NAME = goweb PACKAGES ?= ./... -MAIN_SOURCE = cmd/goweb/api.go +MAIN_SOURCE = ./cmd/goweb MAIN_RUNNER = go run $(MAIN_SOURCE) ifeq ($(DEBUG), true) MAIN_RUNNER = dlv debug $(MAIN_SOURCE) -- diff --git a/cmd/goweb/api.go b/cmd/goweb/api.go index 6a04a44..be8b876 100644 --- a/cmd/goweb/api.go +++ b/cmd/goweb/api.go @@ -1,98 +1,43 @@ package main import ( - "flag" "fmt" "net/http" - "os" - "strings" - "time" _ "net/http/pprof" - "github.com/ViBiOh/flags" - "github.com/ViBiOh/goweb/pkg/delay" - "github.com/ViBiOh/goweb/pkg/dump" - "github.com/ViBiOh/goweb/pkg/hello" "github.com/ViBiOh/httputils/v4/pkg/alcotest" "github.com/ViBiOh/httputils/v4/pkg/cors" - "github.com/ViBiOh/httputils/v4/pkg/health" "github.com/ViBiOh/httputils/v4/pkg/httputils" "github.com/ViBiOh/httputils/v4/pkg/logger" "github.com/ViBiOh/httputils/v4/pkg/owasp" - "github.com/ViBiOh/httputils/v4/pkg/prometheus" "github.com/ViBiOh/httputils/v4/pkg/recoverer" - "github.com/ViBiOh/httputils/v4/pkg/request" "github.com/ViBiOh/httputils/v4/pkg/server" - "github.com/ViBiOh/httputils/v4/pkg/tracer" -) - -const ( - helloPath = "/hello" - dumpPath = "/dump" - delayPath = "/delay" ) func main() { - fs := flag.NewFlagSet("api", flag.ExitOnError) - - appServerConfig := server.Flags(fs, "") - promServerConfig := server.Flags(fs, "prometheus", flags.NewOverride("Port", uint(9090)), flags.NewOverride("IdleTimeout", 10*time.Second), flags.NewOverride("ShutdownTimeout", 5*time.Second)) - healthConfig := health.Flags(fs, "") - - alcotestConfig := alcotest.Flags(fs, "") - loggerConfig := logger.Flags(fs, "logger") - tracerConfig := tracer.Flags(fs, "tracer") - prometheusConfig := prometheus.Flags(fs, "prometheus", flags.NewOverride("Gzip", false)) - owaspConfig := owasp.Flags(fs, "") - corsConfig := cors.Flags(fs, "cors") - - helloConfig := hello.Flags(fs, "") + config, err := newConfig() + if err != nil { + logger.Fatal(fmt.Errorf("config: %s", err)) + } - logger.Fatal(fs.Parse(os.Args[1:])) - - alcotest.DoAndExit(alcotestConfig) - logger.Global(logger.New(loggerConfig)) - defer logger.Close() - - tracerApp, err := tracer.New(tracerConfig) - logger.Fatal(err) - defer tracerApp.Close() - request.AddTracerToDefaultClient(tracerApp.GetProvider()) + alcotest.DoAndExit(config.alcotest) go func() { fmt.Println(http.ListenAndServe("localhost:9999", http.DefaultServeMux)) }() - appServer := server.New(appServerConfig) - promServer := server.New(promServerConfig) - prometheusApp := prometheus.New(prometheusConfig) - healthApp := health.New(healthConfig) - - helloHandler := http.StripPrefix(helloPath, hello.Handler(helloConfig)) - dumpHandler := http.StripPrefix(dumpPath, dump.Handler()) - delayHandler := http.StripPrefix(delayPath, delay.Handler()) - - appHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if strings.HasPrefix(r.URL.Path, helloPath) { - helloHandler.ServeHTTP(w, r) - return - } - if strings.HasPrefix(r.URL.Path, dumpPath) { - dumpHandler.ServeHTTP(w, r) - return - } - if strings.HasPrefix(r.URL.Path, delayPath) { - delayHandler.ServeHTTP(w, r) - return - } + client, err := newClient(config) + if err != nil { + logger.Fatal(fmt.Errorf("client: %s", err)) + } - w.WriteHeader(http.StatusTeapot) - }) + appServer := server.New(config.appServer) + promServer := server.New(config.promServer) - go promServer.Start("prometheus", healthApp.End(), prometheusApp.Handler()) - go appServer.Start("http", healthApp.End(), httputils.Handler(appHandler, healthApp, recoverer.Middleware, prometheusApp.Middleware, tracerApp.Middleware, owasp.New(owaspConfig).Middleware, cors.New(corsConfig).Middleware)) + go promServer.Start("prometheus", client.health.End(), client.prometheus.Handler()) + go appServer.Start("http", client.health.End(), httputils.Handler(newPort(config), client.health, recoverer.Middleware, client.prometheus.Middleware, client.tracer.Middleware, owasp.New(config.owasp).Middleware, cors.New(config.cors).Middleware)) - healthApp.WaitForTermination(appServer.Done()) + client.health.WaitForTermination(appServer.Done()) server.GracefulWait(appServer.Done(), promServer.Done()) } diff --git a/cmd/goweb/client.go b/cmd/goweb/client.go new file mode 100644 index 0000000..3ebcbf2 --- /dev/null +++ b/cmd/goweb/client.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + + "github.com/ViBiOh/httputils/v4/pkg/health" + "github.com/ViBiOh/httputils/v4/pkg/logger" + "github.com/ViBiOh/httputils/v4/pkg/prometheus" + "github.com/ViBiOh/httputils/v4/pkg/request" + "github.com/ViBiOh/httputils/v4/pkg/tracer" +) + +type client struct { + tracer tracer.App + logger logger.Logger + prometheus prometheus.App + health health.App +} + +func newClient(config configuration) (client, error) { + var output client + var err error + + output.logger = logger.New(config.logger) + logger.Global(output.logger) + + output.tracer, err = tracer.New(config.tracer) + if err != nil { + return output, fmt.Errorf("tracer: %w", err) + } + + request.AddTracerToDefaultClient(output.tracer.GetProvider()) + + output.prometheus = prometheus.New(config.prometheus) + output.health = health.New(config.health) + + return output, nil +} + +func (c client) Close() { + c.tracer.Close() + c.logger.Close() +} diff --git a/cmd/goweb/config.go b/cmd/goweb/config.go new file mode 100644 index 0000000..b1173fb --- /dev/null +++ b/cmd/goweb/config.go @@ -0,0 +1,49 @@ +package main + +import ( + "flag" + "os" + "time" + + "github.com/ViBiOh/flags" + "github.com/ViBiOh/goweb/pkg/hello" + "github.com/ViBiOh/httputils/v4/pkg/alcotest" + "github.com/ViBiOh/httputils/v4/pkg/cors" + "github.com/ViBiOh/httputils/v4/pkg/health" + "github.com/ViBiOh/httputils/v4/pkg/logger" + "github.com/ViBiOh/httputils/v4/pkg/owasp" + "github.com/ViBiOh/httputils/v4/pkg/prometheus" + "github.com/ViBiOh/httputils/v4/pkg/server" + "github.com/ViBiOh/httputils/v4/pkg/tracer" +) + +type configuration struct { + appServer server.Config + promServer server.Config + health health.Config + alcotest alcotest.Config + logger logger.Config + tracer tracer.Config + prometheus prometheus.Config + owasp owasp.Config + cors cors.Config + hello hello.Config +} + +func newConfig() (configuration, error) { + fs := flag.NewFlagSet("api", flag.ExitOnError) + + return configuration{ + appServer: server.Flags(fs, ""), + promServer: server.Flags(fs, "prometheus", flags.NewOverride("Port", uint(9090)), flags.NewOverride("IdleTimeout", 10*time.Second), flags.NewOverride("ShutdownTimeout", 5*time.Second)), + health: health.Flags(fs, ""), + alcotest: alcotest.Flags(fs, ""), + logger: logger.Flags(fs, "logger"), + tracer: tracer.Flags(fs, "tracer"), + prometheus: prometheus.Flags(fs, "prometheus", flags.NewOverride("Gzip", false)), + owasp: owasp.Flags(fs, ""), + cors: cors.Flags(fs, "cors"), + + hello: hello.Flags(fs, ""), + }, fs.Parse(os.Args[1:]) +} diff --git a/cmd/goweb/port.go b/cmd/goweb/port.go new file mode 100644 index 0000000..4fc4884 --- /dev/null +++ b/cmd/goweb/port.go @@ -0,0 +1,29 @@ +package main + +import ( + "net/http" + + "github.com/ViBiOh/goweb/pkg/delay" + "github.com/ViBiOh/goweb/pkg/dump" + "github.com/ViBiOh/goweb/pkg/hello" +) + +const ( + helloPath = "/hello/" + dumpPath = "/dump/" + delayPath = "/delay/" +) + +func newPort(config configuration) http.Handler { + mux := http.NewServeMux() + + mux.Handle(helloPath, http.StripPrefix(helloPath, hello.Handler(config.hello))) + mux.Handle(dumpPath, http.StripPrefix(dumpPath, dump.Handler())) + mux.Handle(delayPath, http.StripPrefix(delayPath, delay.Handler())) + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusTeapot) + }) + + return mux +}