mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
Add status code 103 Early Hints. Add the ability to customize and change the order of controller's fields and their registered valid dependencies relative to: #1343
Former-commit-id: 5bd9e02e5fafca135d17cad87f4a9aec526b333b
This commit is contained in:
parent
9d09e8637b
commit
bd5f96086b
|
@ -1,6 +1,6 @@
|
||||||
<!-- # Iris Web Framework <a href="README_ZH.md"> <img width="20px" src="https://iris-go.com/images/flag-china.svg?v=10" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg?v=10" /></a> <a href="README_ID.md"> <img width="20px" src="https://iris-go.com/images/flag-indonesia.svg?v=10" /></a> <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg?v=10" /></a> <a href="README_PT_BR.md"><img width="20px" src="https://iris-go.com/images/flag-pt-br.svg?v=10" /></a> <a href="README_JPN.md"><img width="20px" src="https://iris-go.com/images/flag-japan.svg?v=10" /></a> -->
|
<!-- # Iris Web Framework <a href="README_ZH.md"> <img width="20px" src="https://iris-go.com/images/flag-china.svg?v=10" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg?v=10" /></a> <a href="README_ID.md"> <img width="20px" src="https://iris-go.com/images/flag-indonesia.svg?v=10" /></a> <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg?v=10" /></a> <a href="README_PT_BR.md"><img width="20px" src="https://iris-go.com/images/flag-pt-br.svg?v=10" /></a> <a href="README_JPN.md"><img width="20px" src="https://iris-go.com/images/flag-japan.svg?v=10" /></a> -->
|
||||||
|
|
||||||
# Iris <a href="README_ZH.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg?v=10" /></a> <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg?v=10" /></a> <a href="README_ES.md"><img width="20px" src="https://www.shareicon.net/data/48x48/2016/09/01/822583_world_512x512.png" /></a>
|
# Iris <a href="README_ZH.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg?v=10" /></a> <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg?v=10" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a>
|
||||||
|
|
||||||
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=for-the-badge)](https://travis-ci.org/kataras/iris) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)<!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://godoc.org/github.com/kataras/iris)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/tree/master/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=blue&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) [![release](https://img.shields.io/badge/release%20-v11.2-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases)
|
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=for-the-badge)](https://travis-ci.org/kataras/iris) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)<!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://godoc.org/github.com/kataras/iris)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/tree/master/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=blue&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) [![release](https://img.shields.io/badge/release%20-v11.2-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Iris <a href="README.md"> <img width="20px" src="https://iris-go.com/images/flag-unitedkingdom.svg?v=10" /></a> <a href="README_ZH.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg?v=10" /></a> <a href="README_ES.md"><img width="20px" src="https://www.shareicon.net/data/48x48/2016/09/01/822583_world_512x512.png" /></a>
|
# Iris <a href="README.md"> <img width="20px" src="https://iris-go.com/images/flag-unitedkingdom.svg?v=10" /></a> <a href="README_ZH.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg?v=10" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a>
|
||||||
|
|
||||||
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=for-the-badge)](https://travis-ci.org/kataras/iris) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)<!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://godoc.org/github.com/kataras/iris)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/tree/master/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=blue&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) [![release](https://img.shields.io/badge/release%20-v11.2-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases)
|
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=for-the-badge)](https://travis-ci.org/kataras/iris) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)<!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://godoc.org/github.com/kataras/iris)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/tree/master/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=blue&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) [![release](https://img.shields.io/badge/release%20-v11.2-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- # Iris Web Framework <a href="README_ZH.md"> <img width="20px" src="https://iris-go.com/images/flag-china.svg?v=10" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg?v=10" /></a> <a href="README_ID.md"> <img width="20px" src="https://iris-go.com/images/flag-indonesia.svg?v=10" /></a> <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg?v=10" /></a> <a href="README_PT_BR.md"><img width="20px" src="https://iris-go.com/images/flag-pt-br.svg?v=10" /></a> <a href="README_JPN.md"><img width="20px" src="https://iris-go.com/images/flag-japan.svg?v=10" /></a> -->
|
<!-- # Iris Web Framework <a href="README_ZH.md"> <img width="20px" src="https://iris-go.com/images/flag-china.svg?v=10" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg?v=10" /></a> <a href="README_ID.md"> <img width="20px" src="https://iris-go.com/images/flag-indonesia.svg?v=10" /></a> <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg?v=10" /></a> <a href="README_PT_BR.md"><img width="20px" src="https://iris-go.com/images/flag-pt-br.svg?v=10" /></a> <a href="README_JPN.md"><img width="20px" src="https://iris-go.com/images/flag-japan.svg?v=10" /></a> -->
|
||||||
|
|
||||||
# Iris <a href="README.md"> <img width="20px" src="https://iris-go.com/images/flag-unitedkingdom.svg?v=10" /></a> <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg?v=10" /></a> <a href="README_ES.md"><img width="20px" src="https://www.shareicon.net/data/48x48/2016/09/01/822583_world_512x512.png" /></a>
|
# Iris <a href="README.md"> <img width="20px" src="https://iris-go.com/images/flag-unitedkingdom.svg?v=10" /></a> <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg?v=10" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a>
|
||||||
|
|
||||||
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=for-the-badge)](https://travis-ci.org/kataras/iris) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)<!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://godoc.org/github.com/kataras/iris)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/tree/master/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=blue&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) [![release](https://img.shields.io/badge/release%20-v11.2-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases)
|
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=for-the-badge)](https://travis-ci.org/kataras/iris) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)<!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://godoc.org/github.com/kataras/iris)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/tree/master/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=blue&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) [![release](https://img.shields.io/badge/release%20-v11.2-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases)
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ func Struct(s interface{}, values ...reflect.Value) *StructInjector {
|
||||||
ValueOf(s),
|
ValueOf(s),
|
||||||
DefaultHijacker,
|
DefaultHijacker,
|
||||||
DefaultTypeChecker,
|
DefaultTypeChecker,
|
||||||
|
SortByNumMethods,
|
||||||
Values(values).CloneWithFieldsOf(s)...,
|
Values(values).CloneWithFieldsOf(s)...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -64,6 +65,7 @@ type D struct {
|
||||||
|
|
||||||
hijacker Hijacker
|
hijacker Hijacker
|
||||||
goodFunc TypeChecker
|
goodFunc TypeChecker
|
||||||
|
sorter Sorter
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates and returns a new Dependency Injection container.
|
// New creates and returns a new Dependency Injection container.
|
||||||
|
@ -85,13 +87,20 @@ func (d *D) GoodFunc(fn TypeChecker) *D {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort sets the fields and valid bindable values sorter for struct injection.
|
||||||
|
func (d *D) Sort(with Sorter) *D {
|
||||||
|
d.sorter = with
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
// Clone returns a new Dependency Injection container, it adopts the
|
// Clone returns a new Dependency Injection container, it adopts the
|
||||||
// parent's (current "D") hijacker, good func type checker and all dependencies values.
|
// parent's (current "D") hijacker, good func type checker, sorter and all dependencies values.
|
||||||
func (d *D) Clone() *D {
|
func (d *D) Clone() *D {
|
||||||
return &D{
|
return &D{
|
||||||
Values: d.Values.Clone(),
|
Values: d.Values.Clone(),
|
||||||
hijacker: d.hijacker,
|
hijacker: d.hijacker,
|
||||||
goodFunc: d.goodFunc,
|
goodFunc: d.goodFunc,
|
||||||
|
sorter: d.sorter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +117,7 @@ func (d *D) Struct(s interface{}) *StructInjector {
|
||||||
ValueOf(s),
|
ValueOf(s),
|
||||||
d.hijacker,
|
d.hijacker,
|
||||||
d.goodFunc,
|
d.goodFunc,
|
||||||
|
d.sorter,
|
||||||
d.Values.CloneWithFieldsOf(s)...,
|
d.Values.CloneWithFieldsOf(s)...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,11 +178,6 @@ type field struct {
|
||||||
Name string // the actual name.
|
Name string // the actual name.
|
||||||
Index []int // the index of the field, slice if it's part of a embedded struct
|
Index []int // the index of the field, slice if it's part of a embedded struct
|
||||||
CanSet bool // is true if it's exported.
|
CanSet bool // is true if it's exported.
|
||||||
|
|
||||||
// this could be empty, but in our cases it's not,
|
|
||||||
// it's filled with the bind object (as service which means as static value)
|
|
||||||
// and it's filled from the lookupFields' caller.
|
|
||||||
AnyValue reflect.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumFields returns the total number of fields, and the embedded, even if the embedded struct is not exported,
|
// NumFields returns the total number of fields, and the embedded, even if the embedded struct is not exported,
|
||||||
|
|
|
@ -3,6 +3,7 @@ package di
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scope is the struct injector's struct value scope/permant state.
|
// Scope is the struct injector's struct value scope/permant state.
|
||||||
|
@ -40,6 +41,8 @@ type (
|
||||||
targetStructField struct {
|
targetStructField struct {
|
||||||
Object *BindObject
|
Object *BindObject
|
||||||
FieldIndex []int
|
FieldIndex []int
|
||||||
|
// ValueIndex is used mostly for debugging, it's the order of the registered binded value targets to that field.
|
||||||
|
ValueIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
// StructInjector keeps the data that are needed in order to do the binding injection
|
// StructInjector keeps the data that are needed in order to do the binding injection
|
||||||
|
@ -68,13 +71,37 @@ func (s *StructInjector) countBindType(typ BindType) (n int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 Sorter func(t1 reflect.Type, t2 reflect.Type) bool
|
||||||
|
|
||||||
|
// SortByNumMethods is a builtin sorter to sort fields and values
|
||||||
|
// based on their type and its number of methods, highest number of methods goes first.
|
||||||
|
//
|
||||||
|
// It is the default sorter on package-level struct injector function `Struct`.
|
||||||
|
var SortByNumMethods Sorter = func(t1 reflect.Type, t2 reflect.Type) bool {
|
||||||
|
if t1.Kind() != t2.Kind() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if k := t1.Kind(); k == reflect.Interface || k == reflect.Struct {
|
||||||
|
return t1.NumMethod() > t2.NumMethod()
|
||||||
|
} else if k != reflect.Struct {
|
||||||
|
return false // non-structs goes last.
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// MakeStructInjector returns a new struct injector, which will be the object
|
// MakeStructInjector returns a new struct injector, which will be the object
|
||||||
// that the caller should use to bind exported fields or
|
// that the caller should use to bind exported fields or
|
||||||
// embedded unexported fields that contain exported fields
|
// embedded unexported fields that contain exported fields
|
||||||
// of the "v" struct value or pointer.
|
// of the "v" struct value or pointer.
|
||||||
//
|
//
|
||||||
// The hijack and the goodFunc are optional, the "values" is the dependencies collection.
|
// The hijack and the goodFunc are optional, the "values" is the dependencies collection.
|
||||||
func MakeStructInjector(v reflect.Value, hijack Hijacker, goodFunc TypeChecker, values ...reflect.Value) *StructInjector {
|
func MakeStructInjector(v reflect.Value, hijack Hijacker, goodFunc TypeChecker, sorter Sorter, values ...reflect.Value) *StructInjector {
|
||||||
s := &StructInjector{
|
s := &StructInjector{
|
||||||
initRef: v,
|
initRef: v,
|
||||||
initRefAsSlice: []reflect.Value{v},
|
initRefAsSlice: []reflect.Value{v},
|
||||||
|
@ -96,7 +123,19 @@ func MakeStructInjector(v reflect.Value, hijack Hijacker, goodFunc TypeChecker,
|
||||||
|
|
||||||
visited := make(map[int]struct{}, 0) // add a visited to not add twice a single value (09-Jul-2019).
|
visited := make(map[int]struct{}, 0) // add a visited to not add twice a single value (09-Jul-2019).
|
||||||
fields := lookupFields(s.elemType, true, nil)
|
fields := lookupFields(s.elemType, true, nil)
|
||||||
|
|
||||||
|
// for idx, val := range values {
|
||||||
|
// fmt.Printf("[%d] value type [%s] value name [%s]\n", idx, val.Type().String(), val.String())
|
||||||
|
// }
|
||||||
|
|
||||||
|
if len(fields) > 1 && sorter != nil {
|
||||||
|
sort.Slice(fields, func(i, j int) bool {
|
||||||
|
return sorter(fields[i].Type, fields[j].Type)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
for _, f := range fields {
|
for _, f := range fields {
|
||||||
|
// fmt.Printf("[%d] field type [%s] value name [%s]\n", idx, f.Type.String(), f.Name)
|
||||||
if hijack != nil {
|
if hijack != nil {
|
||||||
if b, ok := hijack(f.Type); ok && b != nil {
|
if b, ok := hijack(f.Type); ok && b != nil {
|
||||||
s.fields = append(s.fields, &targetStructField{
|
s.fields = append(s.fields, &targetStructField{
|
||||||
|
@ -108,6 +147,8 @@ func MakeStructInjector(v reflect.Value, hijack Hijacker, goodFunc TypeChecker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var possibleValues []*targetStructField
|
||||||
|
|
||||||
for idx, val := range values {
|
for idx, val := range values {
|
||||||
if _, alreadySet := visited[idx]; alreadySet {
|
if _, alreadySet := visited[idx]; alreadySet {
|
||||||
continue
|
continue
|
||||||
|
@ -120,15 +161,33 @@ func MakeStructInjector(v reflect.Value, hijack Hijacker, goodFunc TypeChecker,
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.IsAssignable(f.Type) {
|
if b.IsAssignable(f.Type) {
|
||||||
visited[idx] = struct{}{}
|
possibleValues = append(possibleValues, &targetStructField{
|
||||||
// fmt.Printf("bind the object to the field: %s at index: %#v and type: %s\n", f.Name, f.Index, f.Type.String())
|
ValueIndex: idx,
|
||||||
s.fields = append(s.fields, &targetStructField{
|
|
||||||
FieldIndex: f.Index,
|
FieldIndex: f.Index,
|
||||||
Object: &b,
|
Object: &b,
|
||||||
})
|
})
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if l := len(possibleValues); l == 0 {
|
||||||
|
continue
|
||||||
|
} else if l > 1 && sorter != nil {
|
||||||
|
sort.Slice(possibleValues, func(i, j int) bool {
|
||||||
|
// if first.Object.BindType != second.Object.BindType {
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if first.Object.BindType != Static { // dynamic goes last.
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
return sorter(possibleValues[i].Object.Type, possibleValues[j].Object.Type)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
tf := possibleValues[0]
|
||||||
|
visited[tf.ValueIndex] = struct{}{}
|
||||||
|
// fmt.Printf("bind the object to the field: %s at index: %#v and type: %s\n", f.Name, f.Index, f.Type.String())
|
||||||
|
s.fields = append(s.fields, tf)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Has = len(s.fields) > 0
|
s.Has = len(s.fields) > 0
|
||||||
|
|
|
@ -2,14 +2,12 @@ package httptest
|
||||||
|
|
||||||
// HTTP status codes as registered with IANA.
|
// HTTP status codes as registered with IANA.
|
||||||
// See: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
// See: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||||
// Raw Copy from the net/http std package in order to recude the import path of "net/http" for the users.
|
// Raw Copy from the future(tip) net/http std package in order to recude the import path of "net/http" for the users.
|
||||||
//
|
|
||||||
// These may or may not stay.
|
|
||||||
const (
|
const (
|
||||||
StatusContinue = 100 // RFC 7231, 6.2.1
|
StatusContinue = 100 // RFC 7231, 6.2.1
|
||||||
StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
|
StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
|
||||||
StatusProcessing = 102 // RFC 2518, 10.1
|
StatusProcessing = 102 // RFC 2518, 10.1
|
||||||
|
StatusEarlyHints = 103 // RFC 8297
|
||||||
StatusOK = 200 // RFC 7231, 6.3.1
|
StatusOK = 200 // RFC 7231, 6.3.1
|
||||||
StatusCreated = 201 // RFC 7231, 6.3.2
|
StatusCreated = 201 // RFC 7231, 6.3.2
|
||||||
StatusAccepted = 202 // RFC 7231, 6.3.3
|
StatusAccepted = 202 // RFC 7231, 6.3.3
|
||||||
|
|
8
iris.go
8
iris.go
|
@ -39,15 +39,13 @@ import (
|
||||||
const Version = "11.2.8"
|
const Version = "11.2.8"
|
||||||
|
|
||||||
// HTTP status codes as registered with IANA.
|
// HTTP status codes as registered with IANA.
|
||||||
// See: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
// See: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml.
|
||||||
// Raw Copy from the net/http std package in order to recude the import path of "net/http" for the users.
|
// Raw Copy from the future(tip) net/http std package in order to recude the import path of "net/http" for the users.
|
||||||
//
|
|
||||||
// Copied from `net/http` package.
|
|
||||||
const (
|
const (
|
||||||
StatusContinue = 100 // RFC 7231, 6.2.1
|
StatusContinue = 100 // RFC 7231, 6.2.1
|
||||||
StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
|
StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
|
||||||
StatusProcessing = 102 // RFC 2518, 10.1
|
StatusProcessing = 102 // RFC 2518, 10.1
|
||||||
|
StatusEarlyHints = 103 // RFC 8297
|
||||||
StatusOK = 200 // RFC 7231, 6.3.1
|
StatusOK = 200 // RFC 7231, 6.3.1
|
||||||
StatusCreated = 201 // RFC 7231, 6.3.2
|
StatusCreated = 201 // RFC 7231, 6.3.2
|
||||||
StatusAccepted = 202 // RFC 7231, 6.3.3
|
StatusAccepted = 202 // RFC 7231, 6.3.3
|
||||||
|
|
|
@ -86,6 +86,7 @@ type ControllerActivator struct {
|
||||||
// Can be bind-ed to the the new controller's fields and method that is fired
|
// Can be bind-ed to the the new controller's fields and method that is fired
|
||||||
// on incoming requests.
|
// on incoming requests.
|
||||||
dependencies di.Values
|
dependencies di.Values
|
||||||
|
sorter di.Sorter
|
||||||
|
|
||||||
errorHandler hero.ErrorHandler
|
errorHandler hero.ErrorHandler
|
||||||
|
|
||||||
|
@ -108,7 +109,7 @@ func NameOf(v interface{}) string {
|
||||||
return fullname
|
return fullname
|
||||||
}
|
}
|
||||||
|
|
||||||
func newControllerActivator(router router.Party, controller interface{}, dependencies []reflect.Value, errorHandler hero.ErrorHandler) *ControllerActivator {
|
func newControllerActivator(router router.Party, controller interface{}, dependencies []reflect.Value, sorter di.Sorter, errorHandler hero.ErrorHandler) *ControllerActivator {
|
||||||
typ := reflect.TypeOf(controller)
|
typ := reflect.TypeOf(controller)
|
||||||
|
|
||||||
c := &ControllerActivator{
|
c := &ControllerActivator{
|
||||||
|
@ -128,6 +129,7 @@ func newControllerActivator(router router.Party, controller interface{}, depende
|
||||||
routes: whatReservedMethods(typ),
|
routes: whatReservedMethods(typ),
|
||||||
// CloneWithFieldsOf: include the manual fill-ed controller struct's fields to the dependencies.
|
// CloneWithFieldsOf: include the manual fill-ed controller struct's fields to the dependencies.
|
||||||
dependencies: di.Values(dependencies).CloneWithFieldsOf(controller),
|
dependencies: di.Values(dependencies).CloneWithFieldsOf(controller),
|
||||||
|
sorter: sorter,
|
||||||
errorHandler: errorHandler,
|
errorHandler: errorHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +388,14 @@ var emptyIn = []reflect.Value{}
|
||||||
|
|
||||||
func (c *ControllerActivator) attachInjector() {
|
func (c *ControllerActivator) attachInjector() {
|
||||||
if c.injector == nil {
|
if c.injector == nil {
|
||||||
c.injector = di.Struct(c.Value, c.dependencies...)
|
c.injector = di.MakeStructInjector(
|
||||||
|
di.ValueOf(c.Value),
|
||||||
|
di.DefaultHijacker,
|
||||||
|
di.DefaultTypeChecker,
|
||||||
|
c.sorter,
|
||||||
|
di.Values(c.dependencies).CloneWithFieldsOf(c.Value)...,
|
||||||
|
)
|
||||||
|
// c.injector = di.Struct(c.Value, c.dependencies...)
|
||||||
if !c.servesWebsocket {
|
if !c.servesWebsocket {
|
||||||
golog.Debugf("MVC Controller [%s] [Scope=%s]", c.fullName, c.injector.Scope)
|
golog.Debugf("MVC Controller [%s] [Scope=%s]", c.fullName, c.injector.Scope)
|
||||||
} else {
|
} else {
|
||||||
|
|
16
mvc/mvc.go
16
mvc/mvc.go
|
@ -40,6 +40,11 @@ var HeroDependencies = true
|
||||||
// See `mvc#New` for more.
|
// See `mvc#New` for more.
|
||||||
type Application struct {
|
type Application struct {
|
||||||
Dependencies di.Values
|
Dependencies di.Values
|
||||||
|
// Sorter is a `di.Sorter`, can be used to customize the order of controller's fields
|
||||||
|
// and their available bindable values to set.
|
||||||
|
// Sorting matters only when a field can accept more than one registered value.
|
||||||
|
// Defaults to nil; order of registration matters when more than one field can accept the same value.
|
||||||
|
Sorter di.Sorter
|
||||||
Router router.Party
|
Router router.Party
|
||||||
Controllers []*ControllerActivator
|
Controllers []*ControllerActivator
|
||||||
websocketControllers []websocket.ConnHandler
|
websocketControllers []websocket.ConnHandler
|
||||||
|
@ -129,6 +134,15 @@ Set the Logger's Level to "debug" to view the active dependencies per controller
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SortByNumMethods is the same as `app.Sorter = di.SortByNumMethods` which
|
||||||
|
// prioritize fields and their available values (only if more than one)
|
||||||
|
// with the highest number of methods,
|
||||||
|
// this way an empty interface{} is getting the "thinnest" available value.
|
||||||
|
func (app *Application) SortByNumMethods() *Application {
|
||||||
|
app.Sorter = di.SortByNumMethods
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
// Handle serves a controller for the current mvc application's Router.
|
// Handle serves a controller for the current mvc application's Router.
|
||||||
// It accept any custom struct which its functions will be transformed
|
// It accept any custom struct which its functions will be transformed
|
||||||
// to routes.
|
// to routes.
|
||||||
|
@ -218,7 +232,7 @@ func (app *Application) GetNamespaces() websocket.Namespaces {
|
||||||
|
|
||||||
func (app *Application) handle(controller interface{}) *ControllerActivator {
|
func (app *Application) handle(controller interface{}) *ControllerActivator {
|
||||||
// initialize the controller's activator, nothing too magical so far.
|
// initialize the controller's activator, nothing too magical so far.
|
||||||
c := newControllerActivator(app.Router, controller, app.Dependencies, app.ErrorHandler)
|
c := newControllerActivator(app.Router, controller, app.Dependencies, app.Sorter, app.ErrorHandler)
|
||||||
|
|
||||||
// check the controller's "BeforeActivation" or/and "AfterActivation" method(s) between the `activate`
|
// check the controller's "BeforeActivation" or/and "AfterActivation" method(s) between the `activate`
|
||||||
// call, which is simply parses the controller's methods, end-dev can register custom controller's methods
|
// call, which is simply parses the controller's methods, end-dev can register custom controller's methods
|
||||||
|
|
Loading…
Reference in New Issue
Block a user