diff --git a/core/router/api_builder.go b/core/router/api_builder.go index 554076a1..ea95ff42 100644 --- a/core/router/api_builder.go +++ b/core/router/api_builder.go @@ -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 diff --git a/core/router/fs.go b/core/router/fs.go index ca9b5734..057c9cbf 100644 --- a/core/router/fs.go +++ b/core/router/fs.go @@ -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" { diff --git a/hero/binding.go b/hero/binding.go index 46ade3d4..63d9287f 100644 --- a/hero/binding.go +++ b/hero/binding.go @@ -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. */ diff --git a/hero/container.go b/hero/container.go index f368207f..b34a5c12 100644 --- a/hero/container.go +++ b/hero/container.go @@ -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(...) iris.Handler +// - if are all static dependencies then +// there is no reflection involved at serve-time. +// +// func(pathParameter string, ...) +// - 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() error +// - if a function returns an error then this error's text is sent to the client automatically. +// +// func() +// - The result of the function is a dependency too. +// If is a request-scope dependency (dynamic) then +// this function will be called at every request. +// +// func() +// - If 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) } diff --git a/hero/func_result.go b/hero/func_result.go index 7d9b7d45..ce925773 100644 --- a/hero/func_result.go +++ b/hero/func_result.go @@ -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) diff --git a/hero/handler.go b/hero/handler.go index 8a35ae89..3a31e9f4 100644 --- a/hero/handler.go +++ b/hero/handler.go @@ -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(...) 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)