mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
☕ add a dependency-injection examples folder for the next release and some improvements
Former-commit-id: 040168afb7caf808618f7da5e68ae8eb01cb7170
This commit is contained in:
parent
5fc24812bc
commit
ce2eae9121
|
@ -72,6 +72,11 @@ func main() {
|
||||||
|
|
||||||
Your eyes don't lie you. You read well, no `ctx.ReadJSON(&v)` and `ctx.JSON(send)` neither `error` handling are presented. It is a huge relief but don't worry you can still control everything if you ever need, even errors from dependencies. Any error may occur from request-scoped dependencies or your own handler is dispatched through `Party.GetContainer().GetErrorHandler` which defaults to the `hero.DefaultErrorHandler` which sends a `400 Bad Request` response with the error's text as its body contents. If you want to handle `testInput` otherwise then just add a `Party.RegisterDependency(func(ctx iris.Context) testInput {...})` and you are ready to go.
|
Your eyes don't lie you. You read well, no `ctx.ReadJSON(&v)` and `ctx.JSON(send)` neither `error` handling are presented. It is a huge relief but don't worry you can still control everything if you ever need, even errors from dependencies. Any error may occur from request-scoped dependencies or your own handler is dispatched through `Party.GetContainer().GetErrorHandler` which defaults to the `hero.DefaultErrorHandler` which sends a `400 Bad Request` response with the error's text as its body contents. If you want to handle `testInput` otherwise then just add a `Party.RegisterDependency(func(ctx iris.Context) testInput {...})` and you are ready to go.
|
||||||
|
|
||||||
|
Other Improvements:
|
||||||
|
|
||||||
|
- `ctx.JSON, JSONP, XML`: if `iris.WithOptimizations` is NOT passed on `app.Run/Listen` then the indentation defaults to `" "` (two spaces) otherwise it is empty or the provided value.
|
||||||
|
- Hero Handlers (and `app.HandleFunc`) do not have to require `iris.Context` just to call `ctx.Next()` anymore, this is done automatically now.
|
||||||
|
|
||||||
New Context Methods:
|
New Context Methods:
|
||||||
|
|
||||||
- `context.Defer(Handler)` works like `Party.Done` but for the request life-cycle.
|
- `context.Defer(Handler)` works like `Party.Done` but for the request life-cycle.
|
||||||
|
|
|
@ -14,10 +14,17 @@ Internal selected benchmarks between modified features across different versions
|
||||||
|
|
||||||
Measures handler factory time.
|
Measures handler factory time.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ cd v12.1.x
|
||||||
|
$ go test -run=NONE --bench=. -count=5 --benchmem > di_test.txt
|
||||||
|
$ cd ../vNext
|
||||||
|
$ go test -run=NONE --bench=. -count=5 --benchmem > di_test.txt
|
||||||
|
```
|
||||||
|
|
||||||
| Name | Ops | Ns/op | B/op | Allocs/op |
|
| Name | Ops | Ns/op | B/op | Allocs/op |
|
||||||
|---------|:------|:--------|:--------|----|
|
|---------|:------|:--------|:--------|----|
|
||||||
| vNext | 181726 | 6631 | 1544 | 17 |
|
| vNext | 184512 | 6607 | 1544 | 17 |
|
||||||
| v12.1.x | 96001 | 12604 | 976 | 26 |
|
| v12.1.x | 95974 | 12653 | 976 | 26 |
|
||||||
|
|
||||||
It accepts a dynamic path parameter and a JSON request. It returns a JSON response. Fires 500000 requests with 125 concurrent connections.
|
It accepts a dynamic path parameter and a JSON request. It returns a JSON response. Fires 500000 requests with 125 concurrent connections.
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -1,8 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/kataras/iris/v12"
|
||||||
"github.com/kataras/iris/v12"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
testInput struct {
|
testInput struct {
|
||||||
|
|
Binary file not shown.
|
@ -4,4 +4,7 @@ go 1.14
|
||||||
|
|
||||||
replace github.com/kataras/iris/v12 => C:/mygopath/src/github.com/kataras/iris
|
replace github.com/kataras/iris/v12 => C:/mygopath/src/github.com/kataras/iris
|
||||||
|
|
||||||
require github.com/kataras/iris/v12 v12.1.8
|
require (
|
||||||
|
github.com/kataras/iris/v12 v12.1.8
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||||
|
)
|
||||||
|
|
|
@ -8,6 +8,8 @@ It doesn't always contain the "best ways" but it does cover each important featu
|
||||||
|
|
||||||
## Running the examples
|
## Running the examples
|
||||||
|
|
||||||
|
[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/bd489282b676e30de158)
|
||||||
|
|
||||||
1. Install the Go Programming Language, version 1.12+ from https://golang.org/dl.
|
1. Install the Go Programming Language, version 1.12+ from https://golang.org/dl.
|
||||||
2. [Install Iris](https://github.com/kataras/iris/wiki/installation)
|
2. [Install Iris](https://github.com/kataras/iris/wiki/installation)
|
||||||
3. Install any external packages that required by the examples
|
3. Install any external packages that required by the examples
|
||||||
|
|
27
_examples/dependency-injection/basic/main.go
Normal file
27
_examples/dependency-injection/basic/main.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/kataras/iris/v12"
|
||||||
|
|
||||||
|
type (
|
||||||
|
testInput struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutput struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func handler(id int, in testInput) testOutput {
|
||||||
|
return testOutput{
|
||||||
|
ID: id,
|
||||||
|
Name: in.Email,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := iris.New()
|
||||||
|
app.HandleFunc(iris.MethodPost, "/{id:int}", handler)
|
||||||
|
app.Listen(":5000", iris.WithOptimizations)
|
||||||
|
}
|
61
_examples/dependency-injection/basic/middleware/main.go
Normal file
61
_examples/dependency-injection/basic/middleware/main.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/v12"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
testInput struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutput struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func handler(id int, in testInput) testOutput {
|
||||||
|
return testOutput{
|
||||||
|
ID: id,
|
||||||
|
Name: in.Email,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var errCustom = errors.New("my_error")
|
||||||
|
|
||||||
|
func middleware(in testInput) (int, error) {
|
||||||
|
if in.Email == "invalid" {
|
||||||
|
// stop the execution and don't continue to "handler"
|
||||||
|
// without firing an error.
|
||||||
|
return iris.StatusAccepted, iris.ErrStopExecution
|
||||||
|
} else if in.Email == "error" {
|
||||||
|
// stop the execution and fire a custom error.
|
||||||
|
return iris.StatusConflict, errCustom
|
||||||
|
}
|
||||||
|
|
||||||
|
return iris.StatusOK, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newApp() *iris.Application {
|
||||||
|
app := iris.New()
|
||||||
|
|
||||||
|
// handle the route, respond with
|
||||||
|
// a JSON and 200 status code
|
||||||
|
// or 202 status code and empty body
|
||||||
|
// or a 409 status code and "my_error" body.
|
||||||
|
app.HandleFunc(iris.MethodPost, "/{id:int}", middleware, handler)
|
||||||
|
|
||||||
|
app.Configure(
|
||||||
|
iris.WithOptimizations, /* optional */
|
||||||
|
iris.WithoutBodyConsumptionOnUnmarshal /* required when more than one handler is consuming request payload(testInput) */)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := newApp()
|
||||||
|
app.Listen(":8080")
|
||||||
|
}
|
25
_examples/dependency-injection/basic/middleware/main_test.go
Normal file
25
_examples/dependency-injection/basic/middleware/main_test.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/v12/httptest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDependencyInjectionBasic_Middleware(t *testing.T) {
|
||||||
|
app := newApp()
|
||||||
|
|
||||||
|
e := httptest.New(t, app)
|
||||||
|
e.POST("/42").WithJSON(testInput{Email: "my_email"}).Expect().
|
||||||
|
Status(httptest.StatusOK).
|
||||||
|
JSON().Equal(testOutput{ID: 42, Name: "my_email"})
|
||||||
|
|
||||||
|
// it should stop the execution at the middleware and return the middleware's status code,
|
||||||
|
// because the error is `ErrStopExecution`.
|
||||||
|
e.POST("/42").WithJSON(testInput{Email: "invalid"}).Expect().
|
||||||
|
Status(httptest.StatusAccepted).Body().Empty()
|
||||||
|
|
||||||
|
// it should stop the execution at the middleware and return the error's text.
|
||||||
|
e.POST("/42").WithJSON(testInput{Email: "error"}).Expect().
|
||||||
|
Status(httptest.StatusConflict).Body().Equal("my_error")
|
||||||
|
}
|
|
@ -3200,13 +3200,16 @@ var (
|
||||||
|
|
||||||
// WriteJSON marshals the given interface object and writes the JSON response to the 'writer'.
|
// WriteJSON marshals the given interface object and writes the JSON response to the 'writer'.
|
||||||
// Ignores StatusCode, Gzip, StreamingJSON options.
|
// Ignores StatusCode, Gzip, StreamingJSON options.
|
||||||
func WriteJSON(writer io.Writer, v interface{}, options JSON, enableOptimization ...bool) (int, error) {
|
func WriteJSON(writer io.Writer, v interface{}, options JSON, optimize bool) (int, error) {
|
||||||
var (
|
var (
|
||||||
result []byte
|
result []byte
|
||||||
err error
|
err error
|
||||||
optimize = len(enableOptimization) > 0 && enableOptimization[0]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if !optimize && options.Indent == "" {
|
||||||
|
options.Indent = " "
|
||||||
|
}
|
||||||
|
|
||||||
if indent := options.Indent; indent != "" {
|
if indent := options.Indent; indent != "" {
|
||||||
marshalIndent := json.MarshalIndent
|
marshalIndent := json.MarshalIndent
|
||||||
if optimize {
|
if optimize {
|
||||||
|
@ -3291,7 +3294,7 @@ func (ctx *context) JSON(v interface{}, opts ...JSON) (n int, err error) {
|
||||||
var finishCallbackB = []byte(");")
|
var finishCallbackB = []byte(");")
|
||||||
|
|
||||||
// WriteJSONP marshals the given interface object and writes the JSON response to the writer.
|
// WriteJSONP marshals the given interface object and writes the JSON response to the writer.
|
||||||
func WriteJSONP(writer io.Writer, v interface{}, options JSONP, enableOptimization ...bool) (int, error) {
|
func WriteJSONP(writer io.Writer, v interface{}, options JSONP, optimize bool) (int, error) {
|
||||||
if callback := options.Callback; callback != "" {
|
if callback := options.Callback; callback != "" {
|
||||||
n, err := writer.Write([]byte(callback + "("))
|
n, err := writer.Write([]byte(callback + "("))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3300,7 +3303,9 @@ func WriteJSONP(writer io.Writer, v interface{}, options JSONP, enableOptimizati
|
||||||
defer writer.Write(finishCallbackB)
|
defer writer.Write(finishCallbackB)
|
||||||
}
|
}
|
||||||
|
|
||||||
optimize := len(enableOptimization) > 0 && enableOptimization[0]
|
if !optimize && options.Indent == "" {
|
||||||
|
options.Indent = " "
|
||||||
|
}
|
||||||
|
|
||||||
if indent := options.Indent; indent != "" {
|
if indent := options.Indent; indent != "" {
|
||||||
marshalIndent := json.MarshalIndent
|
marshalIndent := json.MarshalIndent
|
||||||
|
@ -3396,7 +3401,7 @@ func (m xmlMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteXML marshals the given interface object and writes the XML response to the writer.
|
// WriteXML marshals the given interface object and writes the XML response to the writer.
|
||||||
func WriteXML(writer io.Writer, v interface{}, options XML) (int, error) {
|
func WriteXML(writer io.Writer, v interface{}, options XML, optimize bool) (int, error) {
|
||||||
if prefix := options.Prefix; prefix != "" {
|
if prefix := options.Prefix; prefix != "" {
|
||||||
n, err := writer.Write([]byte(prefix))
|
n, err := writer.Write([]byte(prefix))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3404,6 +3409,10 @@ func WriteXML(writer io.Writer, v interface{}, options XML) (int, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !optimize && options.Indent == "" {
|
||||||
|
options.Indent = " "
|
||||||
|
}
|
||||||
|
|
||||||
if indent := options.Indent; indent != "" {
|
if indent := options.Indent; indent != "" {
|
||||||
result, err := xml.MarshalIndent(v, "", indent)
|
result, err := xml.MarshalIndent(v, "", indent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3435,7 +3444,7 @@ func (ctx *context) XML(v interface{}, opts ...XML) (int, error) {
|
||||||
|
|
||||||
ctx.ContentType(ContentXMLHeaderValue)
|
ctx.ContentType(ContentXMLHeaderValue)
|
||||||
|
|
||||||
n, err := WriteXML(ctx.writer, v, options)
|
n, err := WriteXML(ctx.writer, v, options, ctx.shouldOptimize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Application().Logger().Debugf("XML: %v", err)
|
ctx.Application().Logger().Debugf("XML: %v", err)
|
||||||
ctx.StatusCode(http.StatusInternalServerError)
|
ctx.StatusCode(http.StatusInternalServerError)
|
||||||
|
|
|
@ -282,12 +282,22 @@ func (api *APIBuilder) RegisterDependency(dependency interface{}) *hero.Dependen
|
||||||
// can accept any input arguments that match with the Party's registered Container's `Dependencies` and
|
// can accept any input arguments that match with the Party's registered Container's `Dependencies` and
|
||||||
// any output result; like custom structs <T>, string, []byte, int, error,
|
// any output result; like custom structs <T>, string, []byte, int, error,
|
||||||
// a combination of the above, hero.Result(hero.View | hero.Response) and more.
|
// a combination of the above, hero.Result(hero.View | hero.Response) and more.
|
||||||
|
//
|
||||||
|
// It's common from a hero handler to not even need to accept a `Context`, for that reason,
|
||||||
|
// the "handlersFn" will call `ctx.Next()` automatically when not called manually.
|
||||||
|
// To stop the execution and not continue to the next "handlersFn"
|
||||||
|
// the end-developer should output an error and return `iris.ErrStopExecution`.
|
||||||
func (api *APIBuilder) HandleFunc(method, relativePath string, handlersFn ...interface{}) *Route {
|
func (api *APIBuilder) HandleFunc(method, relativePath string, handlersFn ...interface{}) *Route {
|
||||||
handlers := make(context.Handlers, 0, len(handlersFn))
|
handlers := make(context.Handlers, 0, len(handlersFn))
|
||||||
for _, h := range handlersFn {
|
for _, h := range handlersFn {
|
||||||
handlers = append(handlers, api.container.Handler(h))
|
handlers = append(handlers, api.container.Handler(h))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On that type of handlers the end-developer does not have to include the Context in the handler,
|
||||||
|
// so the ctx.Next is automatically called unless an `ErrStopExecution` returned (implementation inside hero pkg).
|
||||||
|
o := ExecutionOptions{Force: true}
|
||||||
|
o.apply(&handlers)
|
||||||
|
|
||||||
return api.Handle(method, relativePath, handlers...)
|
return api.Handle(method, relativePath, handlers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,11 @@ type Party interface {
|
||||||
// can accept any input arguments that match with the Party's registered Container's `Dependencies` and
|
// can accept any input arguments that match with the Party's registered Container's `Dependencies` and
|
||||||
// any output result; like custom structs <T>, string, []byte, int, error,
|
// any output result; like custom structs <T>, string, []byte, int, error,
|
||||||
// a combination of the above, hero.Result(hero.View | hero.Response) and more.
|
// a combination of the above, hero.Result(hero.View | hero.Response) and more.
|
||||||
|
//
|
||||||
|
// It's common from a hero handler to not even need to accept a `Context`, for that reason,
|
||||||
|
// the "handlersFn" will call `ctx.Next()` automatically when not called manually.
|
||||||
|
// To stop the execution and not continue to the next "handlersFn"
|
||||||
|
// the end-developer should output an error and return `iris.ErrStopExecution`.
|
||||||
HandleFunc(method, relativePath string, handlersFn ...interface{}) *Route
|
HandleFunc(method, relativePath string, handlersFn ...interface{}) *Route
|
||||||
|
|
||||||
// Handle registers a route to the server's router.
|
// Handle registers a route to the server's router.
|
||||||
|
|
|
@ -225,7 +225,7 @@ func dispatchFuncResult(ctx context.Context, values []reflect.Value) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if statusCode < 400 {
|
if statusCode < 400 && value != ErrStopExecution {
|
||||||
statusCode = DefaultErrStatusCode
|
statusCode = DefaultErrStatusCode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,11 @@ func dispatchCommon(ctx context.Context,
|
||||||
if contentType == "" {
|
if contentType == "" {
|
||||||
// to respect any ctx.ContentType(...) call
|
// to respect any ctx.ContentType(...) call
|
||||||
// especially if v is not nil.
|
// especially if v is not nil.
|
||||||
contentType = ctx.GetContentType()
|
if contentType = ctx.GetContentType(); contentType == "" {
|
||||||
|
// if it's still empty set to JSON. (useful for dynamic middlewares that returns an int status code and the next handler dispatches the JSON,
|
||||||
|
// see dependency-injection/basic/middleware example)
|
||||||
|
contentType = context.ContentJSONHeaderValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v != nil {
|
if v != nil {
|
||||||
|
@ -302,10 +306,13 @@ func dispatchCommon(ctx context.Context,
|
||||||
if strings.HasPrefix(contentType, context.ContentJavascriptHeaderValue) {
|
if strings.HasPrefix(contentType, context.ContentJavascriptHeaderValue) {
|
||||||
_, err = ctx.JSONP(v)
|
_, err = ctx.JSONP(v)
|
||||||
} else if strings.HasPrefix(contentType, context.ContentXMLHeaderValue) {
|
} else if strings.HasPrefix(contentType, context.ContentXMLHeaderValue) {
|
||||||
_, err = ctx.XML(v, context.XML{Indent: " "})
|
_, err = ctx.XML(v)
|
||||||
|
// no need: context.XML{Indent: " "}), after v12.2,
|
||||||
|
// if not iris.WithOptimizations passed and indent is empty then it sets it to two spaces for JSON, JSONP and XML,
|
||||||
|
// otherwise given indentation.
|
||||||
} else {
|
} else {
|
||||||
// defaults to json if content type is missing or its application/json.
|
// defaults to json if content type is missing or its application/json.
|
||||||
_, err = ctx.JSON(v, context.JSON{Indent: " "})
|
_, err = ctx.JSON(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -18,23 +18,6 @@ func (fn ErrorHandlerFunc) HandleError(ctx context.Context, err error) {
|
||||||
fn(ctx, err)
|
fn(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 status := ctx.GetStatusCode(); status == 0 || !context.StatusCodeNotSuccessful(status) {
|
|
||||||
ctx.StatusCode(DefaultErrStatusCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.WriteString(err.Error())
|
|
||||||
ctx.StopExecution()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrSeeOther may be returned from a dependency handler to skip a specific dependency
|
// ErrSeeOther may be returned from a dependency handler to skip a specific dependency
|
||||||
// based on custom logic.
|
// based on custom logic.
|
||||||
|
@ -45,6 +28,26 @@ var (
|
||||||
ErrStopExecution = fmt.Errorf("stop execution")
|
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()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
func makeHandler(fn interface{}, c *Container) context.Handler {
|
func makeHandler(fn interface{}, c *Container) context.Handler {
|
||||||
if fn == nil {
|
if fn == nil {
|
||||||
panic("makeHandler: function is nil")
|
panic("makeHandler: function is nil")
|
||||||
|
@ -77,10 +80,12 @@ func makeHandler(fn interface{}, c *Container) context.Handler {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrSeeOther {
|
if err == ErrSeeOther {
|
||||||
continue
|
continue
|
||||||
} else if err == ErrStopExecution {
|
|
||||||
ctx.StopExecution()
|
|
||||||
return // return without error.
|
|
||||||
}
|
}
|
||||||
|
// handled inside ErrorHandler.
|
||||||
|
// else if err == ErrStopExecution {
|
||||||
|
// ctx.StopExecution()
|
||||||
|
// return // return without error.
|
||||||
|
// }
|
||||||
|
|
||||||
c.GetErrorHandler(ctx).HandleError(ctx, err)
|
c.GetErrorHandler(ctx).HandleError(ctx, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -156,7 +156,7 @@ before begin the implementation of it.
|
||||||
b.Register("user_dep", func(db myDB) User{...}).DependsOn("db")
|
b.Register("user_dep", func(db myDB) User{...}).DependsOn("db")
|
||||||
b.Handler(func(user User) error{...})
|
b.Handler(func(user User) error{...})
|
||||||
b.Handler(func(ctx iris.Context, reuseDB myDB) {...})
|
b.Handler(func(ctx iris.Context, reuseDB myDB) {...})
|
||||||
Why linked over automatically? Because more thna one dependency can implement the same input and
|
Why linked over automatically? Because more than one dependency can implement the same input and
|
||||||
end-user does not care about ordering the registered ones.
|
end-user does not care about ordering the registered ones.
|
||||||
Link with `DependsOn` SHOULD be optional, if exists then limit the available dependencies,
|
Link with `DependsOn` SHOULD be optional, if exists then limit the available dependencies,
|
||||||
`DependsOn` SHOULD accept comma-separated values, e.g. "db, otherdep" and SHOULD also work
|
`DependsOn` SHOULD accept comma-separated values, e.g. "db, otherdep" and SHOULD also work
|
||||||
|
@ -170,6 +170,8 @@ so, in theory, end-developers could achieve same results by hand-code(inside the
|
||||||
|
|
||||||
26 Feb 2020. Gerasimos Maropoulos
|
26 Feb 2020. Gerasimos Maropoulos
|
||||||
______________________________________________
|
______________________________________________
|
||||||
|
|
||||||
|
29 Feb 2020. It's done.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type testMessage struct {
|
type testMessage struct {
|
||||||
|
|
5
iris.go
5
iris.go
|
@ -18,6 +18,8 @@ import (
|
||||||
|
|
||||||
// context for the handlers
|
// context for the handlers
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
|
"github.com/kataras/iris/v12/hero"
|
||||||
|
|
||||||
// core packages, required to build the application
|
// core packages, required to build the application
|
||||||
"github.com/kataras/iris/v12/core/errgroup"
|
"github.com/kataras/iris/v12/core/errgroup"
|
||||||
"github.com/kataras/iris/v12/core/host"
|
"github.com/kataras/iris/v12/core/host"
|
||||||
|
@ -527,6 +529,9 @@ var (
|
||||||
//
|
//
|
||||||
// A shortcut for the `context#XMLMap`.
|
// A shortcut for the `context#XMLMap`.
|
||||||
XMLMap = context.XMLMap
|
XMLMap = context.XMLMap
|
||||||
|
// ErrStopExecution if returned from a hero middleware or a request-scope dependency
|
||||||
|
// stops the handler's execution, see _examples/dependency-injection/basic/middleware.
|
||||||
|
ErrStopExecution = hero.ErrStopExecution
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constants for input argument at `router.RouteRegisterRule`.
|
// Constants for input argument at `router.RouteRegisterRule`.
|
||||||
|
|
|
@ -341,9 +341,10 @@ func (c *ControllerActivator) handlerOf(methodName string) context.Handler {
|
||||||
return func(ctx context.Context) {
|
return func(ctx context.Context) {
|
||||||
ctrl, err := c.injector.Acquire(ctx)
|
ctrl, err := c.injector.Acquire(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != hero.ErrStopExecution {
|
// if err != hero.ErrStopExecution {
|
||||||
|
// c.injector.Container.GetErrorHandler(ctx).HandleError(ctx, err)
|
||||||
|
// }
|
||||||
c.injector.Container.GetErrorHandler(ctx).HandleError(ctx, err)
|
c.injector.Container.GetErrorHandler(ctx).HandleError(ctx, err)
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
mvc/param.go
34
mvc/param.go
|
@ -1,34 +0,0 @@
|
||||||
package mvc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/context"
|
|
||||||
"github.com/kataras/iris/v12/macro"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getPathParamsForInput(startParamIndex int, params []macro.TemplateParam, funcIn ...reflect.Type) (values []reflect.Value) {
|
|
||||||
if len(funcIn) == 0 || len(params) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
consumed := make(map[int]struct{})
|
|
||||||
for _, in := range funcIn {
|
|
||||||
for j, param := range params {
|
|
||||||
if _, ok := consumed[j]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
funcDep, ok := context.ParamResolverByTypeAndIndex(in, startParamIndex+param.Index)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
values = append(values, funcDep)
|
|
||||||
consumed[j] = struct{}{}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user