A very naive, simple and not so robust HTTP API responder implementation.
This commit is contained in:
parent
f5d898b025
commit
afad4f5d7f
@ -44,6 +44,8 @@ func main() {
|
||||
app := application.NewApplication(mainCtx, appName, appConfig)
|
||||
app.Start()
|
||||
|
||||
httpSrv.RegisterHandlerForApplication(appName, app.GetHandler())
|
||||
|
||||
apps = append(apps, app)
|
||||
}
|
||||
|
||||
|
13
internal/application/api_responder.go
Normal file
13
internal/application/api_responder.go
Normal file
@ -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)
|
||||
}
|
@ -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")
|
||||
|
@ -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)))
|
||||
}
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user