mirror of
https://github.com/kataras/iris.git
synced 2025-03-13 21:36:28 +01:00
Former-commit-id: 2b48b9b912e9eb8f5f2c6d413907dbfdae857e08
This commit is contained in:
parent
272566950d
commit
0f907a3dae
|
@ -798,7 +798,9 @@ func (api *APIBuilder) Favicon(favPath string, requestPath ...string) *Route {
|
|||
//
|
||||
// As a special case, the returned file server redirects any request
|
||||
// ending in "/index.html" to the same path, without the final
|
||||
// "index.html".
|
||||
// "/index.html", if `index.html` should be served then register a
|
||||
// new route for it, i.e
|
||||
// `app.Get("/static", func(ctx iris.Context){ ctx.ServeFile("./static/index.html", false) })`.
|
||||
//
|
||||
// StaticWeb calls the `StripPrefix(fullpath, NewStaticHandlerBuilder(systemPath).Listing(false).Build())`.
|
||||
//
|
||||
|
|
|
@ -127,7 +127,7 @@ func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error
|
|||
// fileserver := iris.StaticHandler("./static_files", false, false)
|
||||
// h := router.StripPrefix("/static", fileserver)
|
||||
// /* http://mydomain.com/static/css/style.css */
|
||||
// app.Get("/static", h)
|
||||
// app.Get("/static/{file:path}", h)
|
||||
// ...
|
||||
//
|
||||
func StaticHandler(systemPath string, showList bool, gzip bool) context.Handler {
|
||||
|
|
|
@ -82,7 +82,7 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
|
|||
registeredRoutes := provider.GetRoutes()
|
||||
h.trees = h.trees[0:0] // reset, inneed when rebuilding.
|
||||
|
||||
// sort, subdomains goes first.
|
||||
// sort, subdomains go first.
|
||||
sort.Slice(registeredRoutes, func(i, j int) bool {
|
||||
first, second := registeredRoutes[i], registeredRoutes[j]
|
||||
lsub1 := len(first.Subdomain)
|
||||
|
|
|
@ -28,7 +28,8 @@ type Route struct {
|
|||
// temp storage, they're appended to the Handlers on build.
|
||||
// Execution happens after Begin and main Handler(s), can be empty.
|
||||
doneHandlers context.Handlers
|
||||
Path string `json:"path"` // "/api/user/:id"
|
||||
|
||||
Path string `json:"path"` // "/api/user/{id:uint64}"
|
||||
// FormattedPath all dynamic named parameters (if any) replaced with %v,
|
||||
// used by Application to validate param values of a Route based on its name.
|
||||
FormattedPath string `json:"formattedPath"`
|
||||
|
|
|
@ -93,7 +93,7 @@ func (router *Router) BuildRouter(cPool *context.Pool, requestHandler RequestHan
|
|||
}
|
||||
|
||||
// Downgrade "downgrades", alters the router supervisor service(Router.mainHandler)
|
||||
// algorithm to a custom one,
|
||||
// algorithm to a custom one,
|
||||
// be aware to change the global variables of 'ParamStart' and 'ParamWildcardStart'.
|
||||
// can be used to implement a custom proxy or
|
||||
// a custom router which should work with raw ResponseWriter, *Request
|
||||
|
|
|
@ -73,6 +73,7 @@ func IndirectValue(v reflect.Value) reflect.Value {
|
|||
if k := v.Kind(); k == reflect.Ptr { //|| k == reflect.Interface {
|
||||
return v.Elem()
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
|
@ -106,6 +107,17 @@ func IndirectType(typ reflect.Type) reflect.Type {
|
|||
return typ
|
||||
}
|
||||
|
||||
// IsNil same as `reflect.IsNil` but a bit safer to use, returns false if not a correct type.
|
||||
func IsNil(v reflect.Value) bool {
|
||||
k := v.Kind()
|
||||
switch k {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
|
||||
return v.IsNil()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func goodVal(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
|
||||
|
|
|
@ -211,7 +211,6 @@ func DispatchFuncResult(ctx context.Context, errorHandler ErrorHandler, values [
|
|||
)
|
||||
|
||||
for _, v := range values {
|
||||
|
||||
// order of these checks matters
|
||||
// for example, first we need to check for status code,
|
||||
// secondly the string (for content type and content)...
|
||||
|
@ -310,27 +309,46 @@ func DispatchFuncResult(ctx context.Context, errorHandler ErrorHandler, values [
|
|||
// it's raw content, get the latest
|
||||
content = value
|
||||
case compatibleErr:
|
||||
if value != nil { // it's always not nil but keep it here.
|
||||
if errorHandler != nil {
|
||||
errorHandler.HandleError(ctx, value)
|
||||
break
|
||||
}
|
||||
|
||||
err = value
|
||||
if statusCode < 400 {
|
||||
statusCode = DefaultErrStatusCode
|
||||
}
|
||||
break // break on first error, error should be in the end but we
|
||||
// need to know break the dispatcher if any error.
|
||||
// at the end; we don't want to write anything to the response if error is not nil.
|
||||
if value == nil || di.IsNil(v) {
|
||||
continue
|
||||
}
|
||||
|
||||
if errorHandler != nil {
|
||||
errorHandler.HandleError(ctx, value)
|
||||
break
|
||||
}
|
||||
|
||||
err = value
|
||||
if statusCode < 400 {
|
||||
statusCode = DefaultErrStatusCode
|
||||
}
|
||||
break // break on first error, error should be in the end but we
|
||||
// need to know break the dispatcher if any error.
|
||||
// at the end; we don't want to write anything to the response if error is not nil.
|
||||
|
||||
default:
|
||||
// else it's a custom struct or a dispatcher, we'll decide later
|
||||
// because content type and status code matters
|
||||
// do that check in order to be able to correctly dispatch:
|
||||
// (customStruct, error) -> customStruct filled and error is nil
|
||||
if custom == nil && f != nil {
|
||||
custom = f
|
||||
if custom == nil {
|
||||
// if it's a pointer to struct/map.
|
||||
|
||||
if di.IsNil(v) {
|
||||
// if just a ptr to struct with no content type given
|
||||
// then try to get the previous response writer's content type,
|
||||
// and if that is empty too then force-it to application/json
|
||||
// as the default content type we use for structs/maps.
|
||||
contentType = ctx.GetContentType()
|
||||
if contentType == "" {
|
||||
contentType = context.ContentJSONHeaderValue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if value != nil {
|
||||
custom = value // content type will be take care later on.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ func GetCustomStructWithContentType() (testCustomStruct, string) {
|
|||
return testCustomStruct{"Iris", 2}, "text/xml"
|
||||
}
|
||||
|
||||
func GetCustomStructWithError(ctx iris.Context) (s testCustomStruct, err error) {
|
||||
func GetCustomStructWithError(ctx context.Context) (s testCustomStruct, err error) {
|
||||
s = testCustomStruct{"Iris", 2}
|
||||
if ctx.URLParamExists("err") {
|
||||
err = errors.New("omit return of testCustomStruct and fire error")
|
||||
|
@ -86,7 +86,7 @@ type err struct {
|
|||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e err) Dispatch(ctx iris.Context) {
|
||||
func (e err) Dispatch(ctx context.Context) {
|
||||
// write the status code based on the err's StatusCode.
|
||||
ctx.StatusCode(e.Status)
|
||||
// send to the client the whole object as json
|
||||
|
@ -97,6 +97,22 @@ func GetCustomErrorAsDispatcher() err {
|
|||
return err{iris.StatusBadRequest, "this is my error as json"}
|
||||
}
|
||||
|
||||
func GetCustomTypedNilEmptyResponse() iris.Map {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetCustomTypedPtrNilEmptyResponse() *iris.Map {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetCustomMapNilEmptyResponse() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetCustomPtrStructNilEmptyResponse() *testCustomStruct {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestFuncResult(t *testing.T) {
|
||||
app := iris.New()
|
||||
h := New()
|
||||
|
@ -120,6 +136,11 @@ func TestFuncResult(t *testing.T) {
|
|||
app.Get("/custom/struct/with/error", h.Handler(GetCustomStructWithError))
|
||||
app.Get("/custom/error/as/dispatcher", h.Handler(GetCustomErrorAsDispatcher))
|
||||
|
||||
app.Get("/custom/nil/typed", h.Handler(GetCustomTypedNilEmptyResponse))
|
||||
app.Get("/custom/nil/typed/ptr", h.Handler(GetCustomTypedPtrNilEmptyResponse))
|
||||
app.Get("/custom/nil/map", h.Handler(GetCustomMapNilEmptyResponse))
|
||||
app.Get("/custom/nil/struct", h.Handler(GetCustomPtrStructNilEmptyResponse))
|
||||
|
||||
e := httptest.New(t, app)
|
||||
|
||||
e.GET("/text").Expect().Status(iris.StatusOK).
|
||||
|
@ -172,4 +193,14 @@ func TestFuncResult(t *testing.T) {
|
|||
// the content should be not JSON it should be the status code's text
|
||||
// it will fire the error's text
|
||||
JSON().Equal(err{iris.StatusBadRequest, "this is my error as json"})
|
||||
|
||||
// its result is nil should give an empty response but content-type is set correctly.
|
||||
e.GET("/custom/nil/typed").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
e.GET("/custom/nil/typed/ptr").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
e.GET("/custom/nil/map").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
e.GET("/custom/nil/struct").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user