Browse Source

dependency injection: func (...<T>) iris.Handler can be generated to a simple iris handler if <T> are static dependencies

pull/1778/head
Gerasimos (Makis) Maropoulos 1 month ago
parent
commit
96c2dec47f
No known key found for this signature in database GPG Key ID: ACAB76DFB0DD3F3B
6 changed files with 58 additions and 7 deletions
  1. +1
    -1
      core/router/api_builder.go
  2. +1
    -3
      core/router/fs.go
  3. +11
    -0
      hero/binding.go
  4. +20
    -0
      hero/container.go
  5. +2
    -3
      hero/func_result.go
  6. +23
    -0
      hero/handler.go

+ 1
- 1
core/router/api_builder.go View File

@@ -933,7 +933,7 @@ type (
// }
// Usage with (static) dependencies:
// app.RegisterDependency(userRepo, ...)
// app.PartyConfigure("/users", &api.UsersAPI{})
// app.PartyConfigure("/users", new(api.UsersAPI))
func (api *APIBuilder) PartyConfigure(relativePath string, partyReg ...PartyConfigurator) Party {
var child Party



+ 1
- 3
core/router/fs.go View File

@@ -1059,12 +1059,10 @@ func cacheFiles(ctx stdContext.Context, fs http.FileSystem, names []string, comp
// so, unless requested keep it as it's.
buf := new(bytes.Buffer)
for _, alg := range compressAlgs {
// stop all compressions if at least one file failed to.
select {
case <-ctx.Done():
return ctx.Err()
return ctx.Err() // stop all compressions if at least one file failed to.
default:
break // lint:ignore
}

if alg == "brotli" {


+ 11
- 0
hero/binding.go View File

@@ -347,6 +347,17 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, markExpor
return
}

func getStaticInputs(bindings []*binding, numIn int) []reflect.Value {
inputs := make([]reflect.Value, numIn)
for _, b := range bindings {
if d := b.Dependency; d != nil && d.Static {
inputs[b.Input.Index], _ = d.Handle(nil, nil)
}
}

return inputs
}

/*
Builtin dynamic bindings.
*/


+ 20
- 0
hero/container.go View File

@@ -315,6 +315,26 @@ func Handler(fn interface{}) context.Handler {
// custom structs, Result(View | Response) and more.
// It returns a standard `iris/context.Handler` which can be used anywhere in an Iris Application,
// as middleware or as simple route handler or subdomain's handler.
//
// func(...<T>) iris.Handler
// - if <T> are all static dependencies then
// there is no reflection involved at serve-time.
//
// func(pathParameter string, ...<T>)
// - one or more path parameters (e.g. :uid, :string, :int, :path, :uint64)
// are automatically binded to the first input Go standard types (string, int, uint64 and e.t.c.)
//
// func(<T>) error
// - if a function returns an error then this error's text is sent to the client automatically.
//
// func(<T>) <R>
// - The result of the function is a dependency too.
// If <R> is a request-scope dependency (dynamic) then
// this function will be called at every request.
//
// func(<T>) <R>
// - If <R> is static dependency (e.g. a database or a service) then its result
// can be used as a static dependency to the next dependencies or to the controller/function itself.
func (c *Container) Handler(fn interface{}) context.Handler {
return c.HandlerWithParams(fn, 0)
}


+ 2
- 3
hero/func_result.go View File

@@ -454,10 +454,9 @@ func (r Response) Dispatch(ctx *context.Context) {

ctx.SetLanguage(r.Lang)
r.Content = []byte(ctx.Tr(r.Text, r.Object))
return
} else {
r.Content = []byte(r.Text)
}

r.Content = []byte(r.Text)
}

err := dispatchCommon(ctx, r.Code, r.ContentType, r.Content, r.Object, defaultResultHandler, true)


+ 23
- 0
hero/handler.go View File

@@ -84,6 +84,15 @@ var (
})
)

var (
irisHandlerType = reflect.TypeOf((*context.Handler)(nil)).Elem()
irisHandlerFuncType = reflect.TypeOf(func(*context.Context) {})
)

func isIrisHandlerType(typ reflect.Type) bool {
return typ == irisHandlerType || typ == irisHandlerFuncType
}

func makeHandler(fn interface{}, c *Container, paramsCount int) context.Handler {
if fn == nil {
panic("makeHandler: function is nil")
@@ -110,6 +119,20 @@ func makeHandler(fn interface{}, c *Container, paramsCount int) context.Handler
bindings := getBindingsForFunc(v, c.Dependencies, c.DisablePayloadAutoBinding, paramsCount)
c.fillReport(context.HandlerName(fn), bindings)

// Check if it's a function that accept zero or more dependencies
// and returns an Iris Handler.
if paramsCount <= 0 {
// println(irisHandlerType.String())
if typ.NumOut() == 1 && isIrisHandlerType(typ.Out(0)) {
inputs := getStaticInputs(bindings, numIn)
if len(inputs) != numIn {
panic(fmt.Sprintf("makeHandler: func(...<T>) iris.Handler: expected %d function input parameters but fewer static dependencies matched (%d)", numIn, len(inputs)))
}
handler := v.Call(inputs)[0].Interface().(context.Handler)
return handler
}
}

resultHandler := defaultResultHandler
for i, lidx := 0, len(c.resultHandlers)-1; i <= lidx; i++ {
resultHandler = c.resultHandlers[lidx-i](resultHandler)


Loading…
Cancel
Save