diff --git a/cmd/metricatord/main.go b/cmd/metricatord/main.go index d75e4ac..5770e10 100644 --- a/cmd/metricatord/main.go +++ b/cmd/metricatord/main.go @@ -44,6 +44,8 @@ func main() { app := application.NewApplication(mainCtx, appName, appConfig) app.Start() + httpSrv.RegisterHandlerForApplication(appName, app.GetHandler()) + apps = append(apps, app) } diff --git a/internal/application/api_responder.go b/internal/application/api_responder.go new file mode 100644 index 0000000..9aa76ae --- /dev/null +++ b/internal/application/api_responder.go @@ -0,0 +1,13 @@ +package application + +import ( + "context" + + "go.dev.pztrn.name/metricator/internal/common" +) + +func (a *Application) respond(ctx context.Context) string { + metricName := ctx.Value(common.ContextKeyMetric).(string) + + return a.storage.Get(metricName) +} diff --git a/internal/application/application.go b/internal/application/application.go index dad17b2..4c1dbbd 100644 --- a/internal/application/application.go +++ b/internal/application/application.go @@ -6,6 +6,7 @@ import ( "net/http" "sync" + "go.dev.pztrn.name/metricator/internal/common" "go.dev.pztrn.name/metricator/internal/storage" "go.dev.pztrn.name/metricator/internal/storage/memory" ) @@ -46,6 +47,11 @@ func (a *Application) GetDoneChan() chan struct{} { return a.doneChan } +// GetHandler returns HTTP requests handling function. +func (a *Application) GetHandler() common.HTTPHandlerFunc { + return a.respond +} + // Initializes internal things like storage, HTTP client, etc. func (a *Application) initialize() { a.storage, a.storageDone = memory.NewStorage(a.ctx, a.name+" storage") diff --git a/internal/httpserver/handler.go b/internal/httpserver/handler.go index 4501f49..dd30a55 100644 --- a/internal/httpserver/handler.go +++ b/internal/httpserver/handler.go @@ -1,20 +1,53 @@ package httpserver import ( + "context" "net/http" + "strings" "go.dev.pztrn.name/metricator/internal/common" ) // HTTP requests handler. type handler struct { - handler common.HTTPHandlerFunc + handlers map[string]common.HTTPHandlerFunc } // Registers request's handler. -func (h *handler) register(hndl common.HTTPHandlerFunc) { - h.handler = hndl +func (h *handler) register(name string, hndl common.HTTPHandlerFunc) { + h.handlers[name] = hndl } // ServeHTTP handles every HTTP request. -func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {} +func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if !strings.HasPrefix(r.URL.Path, "/api") { + w.WriteHeader(http.StatusBadRequest) + _, _ = w.Write([]byte("400 Bad Request - invalid path")) + + return + } + + // Request validation. + pathSplitted := strings.Split(r.URL.Path, "/") + if len(pathSplitted) < 3 { + w.WriteHeader(http.StatusBadRequest) + _, _ = w.Write([]byte("400 Bad Request - invalid path")) + } + + handler, found := h.handlers[pathSplitted[2]] + if !found { + w.WriteHeader(http.StatusBadRequest) + _, _ = w.Write([]byte("400 Bad Request - invalid application name")) + + return + } + + requestContext := r.Context() + + // Compose metric name. + metricName := strings.Join(pathSplitted[3:], "/") + ctx := context.WithValue(requestContext, common.ContextKeyMetric, metricName) + + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(handler(ctx))) +} diff --git a/internal/httpserver/httpserver.go b/internal/httpserver/httpserver.go index 40260c0..d7fc7aa 100644 --- a/internal/httpserver/httpserver.go +++ b/internal/httpserver/httpserver.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "go.dev.pztrn.name/metricator/internal/common" "go.dev.pztrn.name/metricator/internal/configuration" ) @@ -39,7 +40,9 @@ func (h *HTTPServer) getRequestContext(_ net.Listener) context.Context { // Initializes handler and HTTP server structure. func (h *HTTPServer) initialize() { - h.handler = &handler{} + h.handler = &handler{ + handlers: make(map[string]common.HTTPHandlerFunc), + } // We do not need to specify all possible parameters for HTTP server, so: // nolint:exhaustivestruct h.server = &http.Server{ @@ -53,6 +56,11 @@ func (h *HTTPServer) initialize() { } } +// RegisterHandlerForApplication registers HTTP handler for application. +func (h *HTTPServer) RegisterHandlerForApplication(name string, handler common.HTTPHandlerFunc) { + h.handler.register(name, handler) +} + // Start starts HTTP server in another goroutine and one more goroutine which // is listening to main context's Cancel() call to stop HTTP server. func (h *HTTPServer) Start() {