hero

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2020 License: BSD-3-Clause Imports: 17 Imported by: 258

Documentation

Index

Constants

This section is empty.

Variables

View Source
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")
)
View Source
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()
	})
)
View Source
var BuiltinDependencies = []*Dependency{

	NewDependency(func(ctx *context.Context) *context.Context { return ctx }).Explicitly(),

	NewDependency(func(ctx *context.Context) stdContext.Context {
		return ctx.Request().Context()
	}).Explicitly(),

	NewDependency(func(ctx *context.Context) *sessions.Session {
		session := sessions.Get(ctx)
		if session == nil {
			panic("binding: session is nil - app.Use(sess.Handler()) to fix it")
		}

		return session
	}).Explicitly(),

	NewDependency(func(ctx *context.Context) *golog.Logger {
		return ctx.Application().Logger()
	}).Explicitly(),

	NewDependency(func(ctx *context.Context) time.Time {
		return time.Now()
	}).Explicitly(),

	NewDependency(func(ctx *context.Context) *http.Request {
		return ctx.Request()
	}).Explicitly(),

	NewDependency(func(ctx *context.Context) http.ResponseWriter {
		return ctx.ResponseWriter()
	}).Explicitly(),

	NewDependency(func(ctx *context.Context) http.Header {
		return ctx.Request().Header
	}).Explicitly(),

	NewDependency(func(ctx *context.Context) net.IP {
		return net.ParseIP(ctx.RemoteAddr())
	}).Explicitly(),
}

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.

View Source
var Default = New()

Default is the default container value which can be used for dependencies share.

View Source
var DefaultViewExt = ".html"

DefaultViewExt is the default extension if `view.Name `is missing, but note that it doesn't care about the app.RegisterView(iris.$VIEW_ENGINE("./$dir", "$ext"))'s $ext. so if you don't use the ".html" as extension for your files you have to append the extension manually into the `view.Name` or change this global variable.

View Source
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

func Handler(fn interface{}) context.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 Container

type Container struct {
	// 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
	// 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.
	// 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

func (c *Container) Clone() *Container

Clone returns a new cloned container. It copies the ErrorHandler, Dependencies and all Options from "c" receiver.

func (*Container) Handler

func (c *Container) Handler(fn interface{}) context.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 (*Container) HandlerWithParams

func (c *Container) HandlerWithParams(fn interface{}, paramsCount int) context.Handler

HandlerWithParams same as `Handler` but it can receive a total path parameters counts to resolve coblex path parameters input dependencies.

func (*Container) Inject

func (c *Container) Inject(toPtr interface{}) error

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

func (c *Container) Struct(ptrValue interface{}, partyParamsCount int) *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 dependnecy 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
}

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

type DependencyHandler func(ctx *context.Context, input *Input) (reflect.Value, error)

DependencyHandler is the native function declaration which implementors should return a value match to an input.

type ErrorHandler

type ErrorHandler interface {
	HandleError(*context.Context, error)
}

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

type ErrorHandlerFunc func(*context.Context, error)

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.
	Type             reflect.Type
	// contains filtered or unexported fields
}

Input contains the input reference of which a dependency is binded to.

type PreflightResult

type PreflightResult interface {
	Preflight(*context.Context) error
}

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.

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.

func (Response) Dispatch

func (r Response) Dispatch(ctx *context.Context)

Dispatch writes the response result to the context's response writer.

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/kataras/iris/tree/master/_examples/dependency-injection/overview.

func Try

func Try(fn func() Result, failure ...Result) Result

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/kataras/iris/blob/master/hero/func_result_test.go.

type ResultHandler

type ResultHandler func(ctx *context.Context, v interface{}) error

ResultHandler describes the function type which should serve the "v" struct value.

type Sorter

type Sorter func(t1 reflect.Type, t2 reflect.Type) bool

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 Source

type Source struct {
	File   string
	Line   int
	Caller string
}

Source describes where a dependency is located at the source code itself.

func (Source) String

func (s Source) String() string

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

func (s *Struct) Acquire(ctx *context.Context) (reflect.Value, error)

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

func (s *Struct) MethodHandler(methodName string, paramsCount int) context.Handler

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/kataras/iris/blob/master/_examples/dependency-injection/overview/web/routes/hello.go.

func (View) Dispatch

func (r View) Dispatch(ctx *context.Context)

Dispatch writes the template filename, template layout and (any) data to the client. Completes the `Result` interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL