Skip to content

Commit

Permalink
Update router
Browse files Browse the repository at this point in the history
  • Loading branch information
remicaumette committed Sep 4, 2023
1 parent 9c522d4 commit e187bd9
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 33 deletions.
19 changes: 9 additions & 10 deletions xfoundation/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ type (
Register(app *App) error
}

Scopeable[T any] interface {
Scope() (T, error)
}

App struct {
Container
Env string
Logger *zap.Logger
Providers []Provider
startHooks []func(ctx context.Context) error
stopHooks []func(ctx context.Context) error
values map[reflect.Type]reflect.Value
}

Container struct {
values map[reflect.Type]reflect.Value
}
)

Expand Down Expand Up @@ -58,7 +58,6 @@ func (app *App) Run() {
}

ctx := context.Background()

for _, hook := range app.startHooks {
if err := hook(ctx); err != nil {
app.Logger.Fatal("failed to start hook", zap.Error(err))
Expand All @@ -84,19 +83,19 @@ func (app *App) OnStop(hook func(ctx context.Context) error) {
app.stopHooks = append(app.stopHooks, hook)
}

func (app *App) Provide(v any) {
app.values[reflect.TypeOf(v)] = reflect.ValueOf(v)
func (c *Container) Provide(v any) {
c.values[reflect.TypeOf(v)] = reflect.ValueOf(v)
}

func (app *App) Invoke(f any) ([]reflect.Value, error) {
func (c *Container) Invoke(f any) ([]reflect.Value, error) {
fType := reflect.TypeOf(f)
if fType.Kind() != reflect.Func {
return nil, fmt.Errorf("app.Invoke: invalid func type %v", fType)
}
var dependencies []reflect.Value
for i := 0; i < fType.NumIn(); i++ {
depType := fType.In(i)
value, ok := app.values[depType]
value, ok := c.values[depType]
if !ok {
return nil, fmt.Errorf("app.Invoke: cannot find dependency %v", depType)
}
Expand Down
59 changes: 36 additions & 23 deletions xweb/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,16 @@ func newRouter(app *xfoundation.App) *Router {
}

func (r *Router) Route(method, path string, handler any) {
handlerType := reflect.TypeOf(handler)
log := r.app.Logger.With(
zap.String("method", method), zap.String("path", path), zap.Any("handler", handlerType))
if handlerType.Kind() != reflect.Func {
log.Error("route handler must be a func")
httpHandler := r.getHttpHandler(handler)
if httpHandler == nil {
r.app.Logger.Error("invalid handler",
zap.String("method", method),
zap.String("path", path),
zap.String("handler", reflect.TypeOf(handler).String()),
)
return
}

if handlerType.NumOut() == 1 && handlerType.Out(0).Kind() == reflect.Func {
values, err := r.app.Invoke(handler)
if err != nil {
log.Error("failed to invoke route constructor", zap.Error(err))
return
} else if len(values) != 1 {
log.Error("an handler func must be returned", zap.Error(err))
return
}
handler = values[0].Interface()
handlerType = reflect.TypeOf(handler)
}

if value, ok := handler.(func(http.ResponseWriter, *http.Request)); ok {
handler = http.HandlerFunc(value)
}
r.handler.Method(method, path, handler.(http.Handler))
r.handler.Method(method, path, httpHandler)
}

func (r *Router) Use(handler ...any) {
Expand All @@ -71,3 +56,31 @@ func (r *Router) Patch(path string, handler any) {
func (r *Router) Delete(path string, handler any) {
r.Route(http.MethodDelete, path, handler)
}

func (r *Router) getHttpHandler(handler any) http.Handler {
handlerType := reflect.TypeOf(handler)
if handlerType.Kind() != reflect.Func {
return nil
}

if handlerType.NumOut() == 1 && handlerType.Out(0).Kind() == reflect.Func {
values, err := r.app.Invoke(handler)
if err != nil {
return nil
} else if len(values) != 1 {
return nil
}
handler = values[0].Interface()
handlerType = reflect.TypeOf(handler)
}

if value, ok := handler.(func(http.ResponseWriter, *http.Request)); ok {
handler = http.HandlerFunc(value)
}

value, ok := handler.(http.Handler)
if !ok {
return nil
}
return value
}

0 comments on commit e187bd9

Please sign in to comment.