2018-07-07 16:10:42 +00:00
|
|
|
package aicra
|
2018-05-21 10:02:24 +00:00
|
|
|
|
|
|
|
import (
|
2020-03-21 15:53:19 +00:00
|
|
|
"fmt"
|
2020-04-04 09:46:37 +00:00
|
|
|
"io"
|
2020-04-04 08:39:02 +00:00
|
|
|
"net/http"
|
2019-04-30 22:02:28 +00:00
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
"git.xdrm.io/go/aicra/datatype"
|
2020-04-04 08:36:52 +00:00
|
|
|
"git.xdrm.io/go/aicra/dynfunc"
|
2018-10-01 15:43:18 +00:00
|
|
|
"git.xdrm.io/go/aicra/internal/config"
|
2018-05-21 10:02:24 +00:00
|
|
|
)
|
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
// Builder for an aicra server
|
|
|
|
type Builder struct {
|
|
|
|
conf *config.Server
|
2020-04-04 08:36:52 +00:00
|
|
|
handlers []*apiHandler
|
|
|
|
}
|
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
// represents an server handler
|
2020-04-04 08:36:52 +00:00
|
|
|
type apiHandler struct {
|
2020-04-04 09:46:37 +00:00
|
|
|
Method string
|
|
|
|
Path string
|
|
|
|
dyn *dynfunc.Handler
|
2018-07-10 23:36:42 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
// AddType adds an available datatype to the api definition
|
|
|
|
func (b *Builder) AddType(t datatype.T) {
|
|
|
|
if b.conf == nil {
|
|
|
|
b.conf = &config.Server{}
|
2018-07-10 23:51:10 +00:00
|
|
|
}
|
2020-04-04 09:46:37 +00:00
|
|
|
if b.conf.Services != nil {
|
|
|
|
panic(ErrLateType)
|
2018-07-06 08:49:52 +00:00
|
|
|
}
|
2020-04-04 09:46:37 +00:00
|
|
|
b.conf.Types = append(b.conf.Types, t)
|
|
|
|
}
|
2018-07-06 08:49:52 +00:00
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
// Setup the builder with its api definition
|
|
|
|
// panics if already setup
|
|
|
|
func (b *Builder) Setup(r io.Reader) error {
|
|
|
|
if b.conf == nil {
|
|
|
|
b.conf = &config.Server{}
|
2018-10-01 17:27:38 +00:00
|
|
|
}
|
2020-04-04 09:46:37 +00:00
|
|
|
if b.conf.Services != nil {
|
|
|
|
panic(ErrAlreadySetup)
|
|
|
|
}
|
|
|
|
return b.conf.Parse(r)
|
2018-07-07 17:21:00 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
// Bind a dynamic handler to a REST service
|
|
|
|
func (b *Builder) Bind(method, path string, fn interface{}) error {
|
|
|
|
if b.conf.Services == nil {
|
|
|
|
return ErrNotSetup
|
|
|
|
}
|
|
|
|
|
2020-03-29 13:04:12 +00:00
|
|
|
// find associated service
|
2020-04-04 08:36:52 +00:00
|
|
|
var service *config.Service
|
2020-04-04 09:46:37 +00:00
|
|
|
for _, s := range b.conf.Services {
|
2020-04-04 08:36:52 +00:00
|
|
|
if method == s.Method && path == s.Pattern {
|
|
|
|
service = s
|
2020-03-29 13:04:12 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-04-04 08:36:52 +00:00
|
|
|
|
|
|
|
if service == nil {
|
|
|
|
return fmt.Errorf("%s '%s': %w", method, path, ErrUnknownService)
|
2020-03-29 13:04:12 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
dyn, err := dynfunc.Build(fn, *service)
|
2020-03-28 13:57:28 +00:00
|
|
|
if err != nil {
|
2020-04-04 08:36:52 +00:00
|
|
|
return fmt.Errorf("%s '%s' handler: %w", method, path, err)
|
2020-03-28 13:57:28 +00:00
|
|
|
}
|
2020-04-04 08:36:52 +00:00
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
b.handlers = append(b.handlers, &apiHandler{
|
|
|
|
Path: path,
|
|
|
|
Method: method,
|
|
|
|
dyn: dyn,
|
2020-04-04 08:36:52 +00:00
|
|
|
})
|
|
|
|
|
2020-03-29 13:04:12 +00:00
|
|
|
return nil
|
2018-07-06 08:49:52 +00:00
|
|
|
}
|
2019-09-26 17:03:37 +00:00
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
// Build a fully-featured HTTP server
|
|
|
|
func (b Builder) Build() (http.Handler, error) {
|
|
|
|
|
|
|
|
for _, service := range b.conf.Services {
|
2020-04-04 08:39:02 +00:00
|
|
|
var hasAssociatedHandler bool
|
2020-04-04 09:46:37 +00:00
|
|
|
for _, handler := range b.handlers {
|
2020-03-29 13:04:12 +00:00
|
|
|
if handler.Method == service.Method && handler.Path == service.Pattern {
|
2020-04-04 08:39:02 +00:00
|
|
|
hasAssociatedHandler = true
|
2020-03-21 15:53:19 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-04-04 08:39:02 +00:00
|
|
|
if !hasAssociatedHandler {
|
|
|
|
return nil, fmt.Errorf("%s '%s': %w", service.Method, service.Pattern, ErrMissingHandler)
|
2020-03-21 15:53:19 +00:00
|
|
|
}
|
2019-09-26 17:03:37 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 09:46:37 +00:00
|
|
|
return httpHandler(b), nil
|
2019-09-26 17:03:37 +00:00
|
|
|
}
|