Documentation ¶
Index ¶
- Variables
- func Handler(fn interface{}) context.Handler
- type Code
- type Container
- func (c *Container) Clone() *Container
- func (c *Container) Handler(fn interface{}) context.Handler
- func (c *Container) HandlerWithParams(fn interface{}, paramsCount int) context.Handler
- func (c *Container) Inject(toPtr interface{}) error
- func (c *Container) Register(dependency interface{}) *Dependency
- func (c *Container) Struct(ptrValue interface{}, partyParamsCount int) *Struct
- func (c *Container) UseResultHandler(handler func(next ResultHandler) ResultHandler) *Container
- func (c *Container) WithLogger(logger *golog.Logger) *Container
- type Dependency
- type DependencyHandler
- type DependencyMatchFunc
- type DependencyMatcher
- type Err
- type ErrorHandler
- type ErrorHandlerFunc
- type Input
- type PreflightResult
- type Report
- type ReportEntry
- type Response
- type Result
- type ResultHandler
- type Sorter
- type Source
- type Struct
- type View
Constants ¶
This section is empty.
Variables ¶
var ( // ErrSeeOther may be returned from a dependency handler to skip a specific dependency // based on custom logic. ErrSeeOther = fmt.Errorf("see other") // ErrStopExecution may be returned from a dependency handler to stop // and return the execution of the function without error (it calls ctx.StopExecution() too). // It may be occurred from request-scoped dependencies as well. ErrStopExecution = fmt.Errorf("stop execution") )
var ( // DefaultErrStatusCode is the default error status code (400) // when the response contains a non-nil error or a request-scoped binding error occur. DefaultErrStatusCode = 400 // DefaultErrorHandler is the default error handler which is fired // when a function returns a non-nil error or a request-scoped dependency failed to binded. DefaultErrorHandler = ErrorHandlerFunc(func(ctx *context.Context, err error) { if err != ErrStopExecution { if status := ctx.GetStatusCode(); status == 0 || !context.StatusCodeNotSuccessful(status) { ctx.StatusCode(DefaultErrStatusCode) } _, _ = ctx.WriteString(err.Error()) } ctx.StopExecution() }) )
var BuiltinDependencies = []*Dependency{ newDependency(func(ctx *context.Context) *context.Context { return ctx }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) stdContext.Context { return ctx.Request().Context() }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) *sessions.Session { session := sessions.Get(ctx) if session == nil { ctx.Application().Logger().Debugf("binding: session is nil\nMaybe inside HandleHTTPError? Register it with app.UseRouter(sess.Handler()) to fix it") } return session }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) *golog.Logger { return ctx.Application().Logger() }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) time.Time { return time.Now() }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) *http.Request { return ctx.Request() }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) http.ResponseWriter { return ctx.ResponseWriter() }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) http.Header { return ctx.Request().Header }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) net.IP { return net.ParseIP(ctx.RemoteAddr()) }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) Code { return Code(ctx.GetStatusCode()) }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) Err { err := ctx.GetErr() if err == nil { return nil } return err }, true, nil).Explicitly(), newDependency(func(ctx *context.Context) context.User { u := ctx.User() if u == nil { return nil } return u }, true, nil), }
BuiltinDependencies is a list of builtin dependencies that are added on Container's initilization. Contains the iris context, standard context, iris sessions and time dependencies.
var Default = New().WithLogger(golog.Default)
Default is the default container value which can be used for dependencies share.
var DefaultDependencyMatcher = func(dep *Dependency, in reflect.Type) bool { if dep.Explicit { return dep.DestType == in } return dep.DestType == nil || equalTypes(dep.DestType, in) }
DefaultDependencyMatcher is the default dependency match function for all DI containers. It is used to collect dependencies from struct's fields and function's parameters.
var ErrMissingDependency = errors.New("missing dependency")
ErrMissingDependency may returned only from the `Container.Inject` method when not a matching dependency found for "toPtr".
Functions ¶
func Handler ¶
Handler accepts a "handler" function which can accept any input arguments that match with the Container's `Dependencies` and any output result; like string, int (string,int), custom structs, Result(View | Response) and anything you can imagine. 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.
Types ¶
type Code ¶
type Code int
Code is a special type for status code. It's used for a builtin dependency to map the status code given by a previous method or middleware. Use a type like that in order to not conflict with any developer-registered dependencies. Alternatively: ctx.GetStatusCode().
type Container ¶
type Container struct { // Optional Logger to report dependencies and matched bindings // per struct, function and method. // By default it is set by the Party creator of this Container. Logger *golog.Logger // Sorter specifies how the inputs should be sorted before binded. // Defaults to sort by "thinnest" target empty interface. Sorter Sorter // The dependencies entries. Dependencies []*Dependency // MarkExportedFieldsAsRequired reports whether all struct's fields // MUST be binded to a dependency from the `Dependencies` list field. // In-short, if it is set to true and if at least one exported field // of a struct is not binded to a dependency then // the entire application will exit with a panic message before server startup. MarkExportedFieldsAsRequired bool // DisablePayloadAutoBinding reports whether // a function's parameter or struct's field of struct type // should not be binded automatically to the request body (e.g. JSON) // if a dependency for that type is missing. // By default the binder will bind structs to request body, // set to true to disable that kind of behavior. DisablePayloadAutoBinding bool // DisableStructDynamicBindings if true panics on struct handler (controller) // if at least one input binding depends on the request and not in a static structure. DisableStructDynamicBindings bool // DependencyMatcher holds the function that compares equality between // a dependency with an input. Defaults to DefaultMatchDependencyFunc. DependencyMatcher DependencyMatcher // GetErrorHandler should return a valid `ErrorHandler` to handle bindings AND handler dispatch errors. // Defaults to a functon which returns the `DefaultErrorHandler`. GetErrorHandler func(*context.Context) ErrorHandler // cannot be nil. // Reports contains an ordered list of information about bindings for further analysys and testing. Reports []*Report // contains filtered or unexported fields }
Container contains and delivers the Dependencies that will be binded to the controller(s) or handler(s) that can be created using the Container's `Handler` and `Struct` methods.
This is not exported for being used by everyone, use it only when you want to share containers between multi mvc.go#Application or make custom hero handlers that can be used on the standard iris' APIBuilder.
For a more high-level structure please take a look at the "mvc.go#Application".
func New ¶
func New(dependencies ...interface{}) *Container
New returns a new Container, a container for dependencies and a factory for handlers and controllers, this is used internally by the `mvc#Application` structure. Please take a look at the structure's documentation for more information.
func (*Container) Clone ¶
Clone returns a new cloned container. It copies the ErrorHandler, Dependencies and all Options from "c" receiver.
func (*Container) Handler ¶
Handler accepts a handler "fn" function which can accept any input arguments that match with the Container's `Dependencies` and any output result; like string, int (string,int), 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 (*Container) HandlerWithParams ¶
HandlerWithParams same as `Handler` but it can receive a total path parameters counts to resolve coblex path parameters input dependencies.
func (*Container) Inject ¶
Inject SHOULD only be used outside of HTTP handlers (performance is not priority for this method) as it does not pre-calculate the available list of bindings for the "toPtr" and the registered dependencies.
It sets a static-only matching dependency to the value of "toPtr". The parameter "toPtr" SHOULD be a pointer to a value corresponding to a dependency, like input parameter of a handler or field of a struct.
If no matching dependency found, the `Inject` method returns an `ErrMissingDependency` and "toPtr" keeps its original state (e.g. nil).
Example Code: c.Register(&LocalDatabase{...}) [...] var db Database err := c.Inject(&db)
func (*Container) Register ¶
func (c *Container) Register(dependency interface{}) *Dependency
Register adds a dependency. The value can be a single struct value or a function. Follow the rules: * <T>{structValue} * func(accepts <T>) returns <D> or (<D>, error) * func(accepts iris.Context) returns <D> or (<D>, error) * func(accepts1 iris.Context, accepts2 *hero.Input) returns <D> or (<D>, error)
A Dependency can accept a previous registered dependency and return a new one or the same updated. * func(accepts1 <D>, accepts2 <T>) returns <E> or (<E>, error) or error * func(acceptsPathParameter1 string, id uint64) returns <T> or (<T>, error)
Usage:
- Register(loggerService{prefix: "dev"}) - Register(func(ctx iris.Context) User {...}) - Register(func(User) OtherResponse {...})
func (*Container) Struct ¶
Struct accepts a pointer to a struct value and returns a structure which contains bindings for the struct's fields and a method to extract a Handler from this struct's method.
func (*Container) UseResultHandler ¶
func (c *Container) UseResultHandler(handler func(next ResultHandler) ResultHandler) *Container
UseResultHandler adds a result handler to the Container. A result handler can be used to inject the returned struct value from a request handler or to replace the default renderer.
type Dependency ¶
type Dependency struct { OriginalValue interface{} // Used for debugging and for logging only. Source Source Handle DependencyHandler // It's the exact type of return to bind, if declared to return <T>, otherwise nil. DestType reflect.Type Static bool // If true then input and dependency DestType should be indedical, // not just assiginable to each other. // Example of use case: depenendency like time.Time that we want to be bindable // only to time.Time inputs and not to a service with a `String() string` method that time.Time struct implements too. Explicit bool // Match holds the matcher. Defaults to the Container's one. Match DependencyMatchFunc }
Dependency describes the design-time dependency to be injected at serve time. Contains its source location, the dependency handler (provider) itself and information such as static for static struct values or explicit to bind a value to its exact DestType and not if just assignable to it (interfaces).
func NewDependency ¶
func NewDependency(dependency interface{}, funcDependencies ...*Dependency) *Dependency
NewDependency converts a function or a function which accepts other dependencies or static struct value to a *Dependency.
See `Container.Handler` for more.
func Register ¶
func Register(dependency interface{}) *Dependency
Register adds a dependency. The value can be a single struct value-instance or a function which has one input and one output, that output type will be binded to the handler's input argument, if matching.
Usage: - Register(loggerService{prefix: "dev"}) - Register(func(ctx iris.Context) User {...}) - Register(func(User) OtherResponse {...})
func (*Dependency) Explicitly ¶
func (d *Dependency) Explicitly() *Dependency
Explicitly sets Explicit option to true. See `Dependency.Explicit` field godoc for more.
Returns itself.
func (*Dependency) String ¶
func (d *Dependency) String() string
type DependencyHandler ¶
DependencyHandler is the native function declaration which implementors should return a value match to an input.
type DependencyMatchFunc ¶
DependencyMatchFunc type alias describes dependency match function with an input (field or parameter).
See "DependencyMatcher" too, which can be used on a Container to change the way dependencies are matched to inputs for all dependencies.
func ToDependencyMatchFunc ¶
func ToDependencyMatchFunc(d *Dependency, match DependencyMatcher) DependencyMatchFunc
ToDependencyMatchFunc converts a DependencyMatcher (generic for all dependencies) to a dependency-specific input matcher.
type DependencyMatcher ¶
type DependencyMatcher = func(*Dependency, reflect.Type) bool
DependencyMatcher type alias describes a dependency match function.
type Err ¶
type Err error
Err is a special type for error stored in mvc responses or context. It's used for a builtin dependency to map the error given by a previous method or middleware. Use a type like that in order to not conflict with any developer-registered dependencies. Alternatively: ctx.GetErr().
type ErrorHandler ¶
ErrorHandler describes an interface to handle errors per hero handler and its dependencies.
Handles non-nil errors return from a hero handler or a controller's method (see `getBindingsFor` and `Handler`) the error may return from a request-scoped dependency too (see `Handler`).
type ErrorHandlerFunc ¶
ErrorHandlerFunc implements the `ErrorHandler`. It describes the type defnition for an error function handler.
func (ErrorHandlerFunc) HandleError ¶
func (fn ErrorHandlerFunc) HandleError(ctx *context.Context, err error)
HandleError fires when a non-nil error returns from a request-scoped dependency at serve-time or the handler itself.
type Input ¶
type Input struct { Index int // for func inputs StructFieldIndex []int // for struct fields in order to support embedded ones. StructFieldName string // the struct field's name. Type reflect.Type // contains filtered or unexported fields }
Input contains the input reference of which a dependency is binded to.
type PreflightResult ¶
PreflightResult is an interface which implementers should be responsible to perform preflight checks of a <T> resource (or Result) before sent to the client.
If a non-nil error returned from the `Preflight` method then the JSON result will be not sent to the client and an ErrorHandler will be responsible to render the error.
Usage: a custom struct value will be a JSON body response (by-default) but it contains "Code int" and `ID string` fields, the "Code" should be the status code of the response and the "ID" should be sent as a Header of "X-Request-ID: $ID".
The caller can manage it at the handler itself. However, to reduce thoese type of duplications it's preferable to use such a standard interface instead.
The Preflight method can return `iris.ErrStopExecution` to render and override any interface that the structure value may implement, e.g. mvc.Result.
type Report ¶
type Report struct { // The name is the last part of the name of a struct or its methods or a function. // Each name is splited by its package.struct.field or package.funcName or package.func.inlineFunc. Name string // If it's a struct or package or function // then it contains children reports of each one of its methods or input parameters // respectfully. Reports []*Report Parent *Report Entries []ReportEntry }
A Report holds meta information about dependency sources and target values per package, struct, struct's fields, struct's method, package-level function or closure. E.g. main -> (*UserController) -> HandleHTTPError.
type ReportEntry ¶
type ReportEntry struct { InputPosition int // struct field position or parameter position. InputFieldName string // if it's a struct field, then this is its type name (we can't get param names). InputFieldType reflect.Type // the input's type. DependencyValue interface{} // the dependency value binded to that InputPosition of Name. DependencyFile string // the file DependencyLine int // and line number of the dependency's value. Static bool }
A ReportEntry holds the information about a binding.
type Response ¶
type Response struct { Code int ContentType string Content []byte // If not empty then content type is the "text/plain" // and content is the text as []byte. If not empty and // the "Lang" field is not empty then this "Text" field // becomes the current locale file's key. Text string // If not empty then "Text" field becomes the locale file's key that should point // to a translation file's unique key. See `Object` for locale template data. // The "Lang" field is the language code // that should render the text inside the locale file's key. Lang string // If not nil then it will fire that as "application/json" or any // previously set "ContentType". If "Lang" and "Text" are not empty // then this "Object" field becomes the template data that the // locale text should use to be rendered. Object interface{} // If Path is not empty then it will redirect // the client to this Path, if Code is >= 300 and < 400 // then it will use that Code to do the redirection, otherwise // StatusFound(302) or StatusSeeOther(303) for post methods will be used. // Except when err != nil. Path string // if not empty then fire a 400 bad request error // unless the Status is > 200, then fire that error code // with the Err.Error() string as its content. // // if Err.Error() is empty then it fires the custom error handler // if any otherwise the framework sends the default http error text based on the status. Err error Try func() int }
Response completes the `methodfunc.Result` interface. It's being used as an alternative return value which wraps the status code, the content type, a content as bytes or as string and an error, it's smart enough to complete the request and send the correct response to the client.
type Result ¶
type Result interface { // Dispatch should send a response to the client. Dispatch(*context.Context) }
Result is a response dispatcher. All types that complete this interface can be returned as values from the method functions.
Example at: https://github.com/XpamAmAdEuS/iris/tree/master/_examples/dependency-injection/overview.
func Try ¶
Try will check if "fn" ran without any panics, using recovery, and return its result as the final response otherwise it returns the "failure" response if any, if not then a 400 bad request is being sent.
Example usage at: https://github.com/XpamAmAdEuS/iris/blob/master/hero/func_result_test.go.
type ResultHandler ¶
ResultHandler describes the function type which should serve the "v" struct value.
type Sorter ¶
Sorter is the type for sort customization of a struct's fields and its available bindable values.
Sorting applies only when a field can accept more than one registered value.
type Struct ¶
type Struct struct { Container *Container Singleton bool // contains filtered or unexported fields }
Struct keeps a record of a particular struct value injection. See `Container.Struct` and `mvc#Application.Handle` methods.
func (*Struct) Acquire ¶
Acquire returns a struct value based on the request. If the dependencies are all static then these are already set-ed at the initialization of this Struct and the same struct value instance will be returned, ignoring the Context. Otherwise a new struct value with filled fields by its pre-calculated bindings will be returned instead.
func (*Struct) MethodHandler ¶
MethodHandler accepts a "methodName" that should be a valid an exported method of the struct and returns its converted Handler.
Second input is optional, even zero is a valid value and can resolve path parameters correctly if from root party.
type View ¶
type View struct { Name string Layout string Data interface{} // map or a custom struct. Code int Err error }
View completes the `hero.Result` interface. It's being used as an alternative return value which wraps the template file name, layout, (any) view data, status code and error. It's smart enough to complete the request and send the correct response to the client.
Example at: https://github.com/XpamAmAdEuS/iris/blob/master/_examples/dependency-injection/overview/web/routes/hello.go.