From e7dd1e7a56921aa006c674230e365bcc7a56e856 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 29 Mar 2020 15:04:12 +0200 Subject: [PATCH] migrate handler from api to aicra; check for service when setting handler --- api/handler.go | 34 ---------------------------------- errors.go | 15 +++++++++++++++ handler.go | 32 ++++++++++++++++++++++++++++++++ server.go | 31 ++++++++++++++++++++++--------- 4 files changed, 69 insertions(+), 43 deletions(-) delete mode 100644 api/handler.go create mode 100644 errors.go create mode 100644 handler.go diff --git a/api/handler.go b/api/handler.go deleted file mode 100644 index c6e5cc9..0000000 --- a/api/handler.go +++ /dev/null @@ -1,34 +0,0 @@ -package api - -import ( - "strings" -) - -// HandlerFn defines the handler signature -type HandlerFn func(req Request, res *Response) Error - -// Handler is an API handler ready to be bound -type Handler struct { - path string - method string - Fn HandlerFn -} - -// NewHandler builds a handler from its http method and path -func NewHandler(method, path string, fn HandlerFn) (*Handler, error) { - return &Handler{ - path: path, - method: strings.ToUpper(method), - Fn: fn, - }, nil -} - -// GetMethod returns the handler's HTTP method -func (h *Handler) GetMethod() string { - return h.method -} - -// GetPath returns the handler's path -func (h *Handler) GetPath() string { - return h.path -} diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..252f8ee --- /dev/null +++ b/errors.go @@ -0,0 +1,15 @@ +package aicra + +// cerr allows you to create constant "const" error with type boxing. +type cerr string + +// Error implements the error builtin interface. +func (err cerr) Error() string { + return string(err) +} + +// ErrNoServiceForHandler - no service matching this handler +const ErrNoServiceForHandler = cerr("no service found for this handler") + +// ErrNoHandlerForService - no handler matching this service +const ErrNoHandlerForService = cerr("no handler found for this service") diff --git a/handler.go b/handler.go new file mode 100644 index 0000000..8af4f34 --- /dev/null +++ b/handler.go @@ -0,0 +1,32 @@ +package aicra + +import ( + "fmt" + "strings" + + "git.xdrm.io/go/aicra/dynamic" + "git.xdrm.io/go/aicra/internal/config" +) + +type handler struct { + Method string + Path string + dynHandler *dynamic.Handler +} + +// createHandler builds a handler from its http method and path +// also it checks whether the function signature is valid +func createHandler(method, path string, service config.Service, fn dynamic.HandlerFn) (*handler, error) { + method = strings.ToUpper(method) + + dynHandler, err := dynamic.Build(fn, service) + if err != nil { + return nil, fmt.Errorf("%s '%s' handler: %w", method, path, err) + } + + return &handler{ + Path: path, + Method: method, + dynHandler: dynHandler, + }, nil +} diff --git a/server.go b/server.go index a8bd3d0..54e53b4 100644 --- a/server.go +++ b/server.go @@ -5,15 +5,15 @@ import ( "io" "os" - "git.xdrm.io/go/aicra/api" "git.xdrm.io/go/aicra/datatype" + "git.xdrm.io/go/aicra/dynamic" "git.xdrm.io/go/aicra/internal/config" ) // Server represents an AICRA instance featuring: type checkers, services type Server struct { config *config.Server - handlers []*api.Handler + handlers []*handler } // New creates a framework instance from a configuration file @@ -26,7 +26,7 @@ func New(configPath string, dtypes ...datatype.T) (*Server, error) { // 1. init instance var i = &Server{ config: nil, - handlers: make([]*api.Handler, 0), + handlers: make([]*handler, 0), } // 2. open config file @@ -46,13 +46,26 @@ func New(configPath string, dtypes ...datatype.T) (*Server, error) { } -// HandleFunc sets a new handler for an HTTP method to a path -func (s *Server) Handle(httpMethod, path string, fn api.HandlerFn) { - handler, err := api.NewHandler(httpMethod, path, fn) +// Handle sets a new handler for an HTTP method to a path +func (s *Server) Handle(method, path string, fn dynamic.HandlerFn) error { + // find associated service + var found *config.Service = nil + for _, service := range s.config.Services { + if method == service.Method && path == service.Pattern { + found = service + break + } + } + if found == nil { + return fmt.Errorf("%s '%s': %w", method, path, ErrNoServiceForHandler) + } + + handler, err := createHandler(method, path, *found, fn) if err != nil { - panic(err) + return err } s.handlers = append(s.handlers, handler) + return nil } // ToHTTPServer converts the server to a http server @@ -62,13 +75,13 @@ func (s Server) ToHTTPServer() (*httpServer, error) { for _, service := range s.config.Services { found := false for _, handler := range s.handlers { - if handler.GetMethod() == service.Method && handler.GetPath() == service.Pattern { + if handler.Method == service.Method && handler.Path == service.Pattern { found = true break } } if !found { - return nil, fmt.Errorf("missing handler for %s '%s'", service.Method, service.Pattern) + return nil, fmt.Errorf("%s '%s': %w", service.Method, service.Pattern, ErrNoHandlerForService) } }