2024-01-12 00:11:53 +00:00
|
|
|
package router
|
|
|
|
|
2024-02-25 13:36:32 +00:00
|
|
|
import (
|
|
|
|
"net/http"
|
2024-03-21 20:53:48 +00:00
|
|
|
"sync"
|
2024-01-12 00:11:53 +00:00
|
|
|
|
2024-02-25 13:36:32 +00:00
|
|
|
"git.lumeweb.com/LumeWeb/portal/config"
|
|
|
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
|
|
|
"github.com/julienschmidt/httprouter"
|
|
|
|
)
|
|
|
|
|
|
|
|
type RoutableAPI interface {
|
|
|
|
Name() string
|
2024-03-17 12:51:23 +00:00
|
|
|
Domain() string
|
2024-03-17 12:53:56 +00:00
|
|
|
AuthTokenName() string
|
2024-02-25 13:36:32 +00:00
|
|
|
Can(w http.ResponseWriter, r *http.Request) bool
|
|
|
|
Handle(w http.ResponseWriter, r *http.Request)
|
|
|
|
Routes() (*httprouter.Router, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type APIRouter struct {
|
|
|
|
apis map[string]RoutableAPI
|
|
|
|
apiDomain map[string]string
|
|
|
|
apiHandlers map[string]http.Handler
|
|
|
|
logger *zap.Logger
|
|
|
|
config *config.Manager
|
2024-03-21 20:53:48 +00:00
|
|
|
mutex *sync.RWMutex
|
2024-02-25 13:36:32 +00:00
|
|
|
}
|
2024-01-12 00:11:53 +00:00
|
|
|
|
|
|
|
// Implement the ServeHTTP method on our new type
|
2024-02-25 13:36:32 +00:00
|
|
|
func (hs APIRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if handler := hs.getHandlerByDomain(r.Host); handler != nil {
|
2024-01-12 00:11:53 +00:00
|
|
|
handler.ServeHTTP(w, r)
|
2024-02-25 13:36:32 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, api := range hs.apis {
|
|
|
|
if api.Can(w, r) {
|
|
|
|
api.Handle(w, r)
|
|
|
|
return
|
|
|
|
}
|
2024-01-12 00:11:53 +00:00
|
|
|
}
|
2024-02-25 13:36:32 +00:00
|
|
|
|
|
|
|
http.NotFound(w, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *APIRouter) RegisterAPI(impl RoutableAPI) {
|
|
|
|
name := impl.Name()
|
|
|
|
hs.apis[name] = impl
|
|
|
|
hs.apiDomain[name+"."+hs.config.Config().Core.Domain] = name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *APIRouter) getHandlerByDomain(domain string) http.Handler {
|
|
|
|
if apiName := hs.apiDomain[domain]; apiName != "" {
|
|
|
|
return hs.getHandler(apiName)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *APIRouter) getHandler(protocol string) http.Handler {
|
2024-03-21 20:53:48 +00:00
|
|
|
hs.mutex.RLock()
|
|
|
|
defer hs.mutex.RUnlock()
|
2024-02-25 13:36:32 +00:00
|
|
|
if handler := hs.apiHandlers[protocol]; handler == nil {
|
|
|
|
if proto := hs.apis[protocol]; proto == nil {
|
|
|
|
hs.logger.Fatal("Protocol not found", zap.String("protocol", protocol))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
routes, err := hs.apis[protocol].Routes()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
hs.logger.Fatal("Error getting routes", zap.Error(err))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-03-21 20:53:48 +00:00
|
|
|
hs.mutex.Lock()
|
|
|
|
defer hs.mutex.Unlock()
|
2024-02-25 13:36:32 +00:00
|
|
|
hs.apiHandlers[protocol] = routes
|
|
|
|
}
|
|
|
|
|
|
|
|
return hs.apiHandlers[protocol]
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewAPIRouter() *APIRouter {
|
|
|
|
return &APIRouter{
|
|
|
|
apis: make(map[string]RoutableAPI),
|
|
|
|
apiHandlers: make(map[string]http.Handler),
|
2024-02-25 14:54:34 +00:00
|
|
|
apiDomain: make(map[string]string),
|
2024-03-21 20:53:48 +00:00
|
|
|
mutex: &sync.RWMutex{},
|
2024-02-25 13:36:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *APIRouter) SetLogger(logger *zap.Logger) {
|
|
|
|
hs.logger = logger
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *APIRouter) SetConfig(config *config.Manager) {
|
|
|
|
hs.config = config
|
2024-01-12 00:11:53 +00:00
|
|
|
}
|
2024-03-17 13:01:28 +00:00
|
|
|
|
|
|
|
func BuildSubdomain(api RoutableAPI, cfg *config.Manager) string {
|
|
|
|
return api.Name() + "." + cfg.Config().Core.Domain
|
|
|
|
}
|