mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
Introduce version 5.0.1
This commit is contained in:
parent
9958337e5d
commit
78d145c207
24
HISTORY.md
24
HISTORY.md
|
@ -2,6 +2,30 @@
|
||||||
|
|
||||||
**How to upgrade**: remove your `$GOPATH/src/github.com/kataras` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris/iris`.
|
**How to upgrade**: remove your `$GOPATH/src/github.com/kataras` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris/iris`.
|
||||||
|
|
||||||
|
|
||||||
|
## v4 -> 5.0.1
|
||||||
|
|
||||||
|
- **IMPROVE**: [Iris command line tool](https://github.com/kataras/iris/tree/master/iris) introduces a **new** `get` command (replacement for the old `create`)
|
||||||
|
|
||||||
|
|
||||||
|
**The get command** downloads, installs and runs a project based on a `prototype`, such as `basic`, `static` and `mongo` .
|
||||||
|
|
||||||
|
> These projects are located [online](https://github.com/iris-contrib/examples/tree/master/AIO_examples)
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
iris get basic
|
||||||
|
```
|
||||||
|
|
||||||
|
Downloads the [basic](https://github.com/iris-contrib/examples/tree/master/AIO_examples/basic) sample protoype project to the `$GOPATH/src/github.com/iris-contrib/examples` directory(the iris cmd will open this folder to you, automatically) builds, runs and watch for source code changes (hot-reload)
|
||||||
|
|
||||||
|
[![Iris get command preview](https://raw.githubusercontent.com/iris-contrib/website/gh-pages/assets/iriscmd.gif)](https://raw.githubusercontent.com/iris-contrib/website/gh-pages/assets/iriscmd.gif)
|
||||||
|
|
||||||
|
|
||||||
|
- **CHANGE**: The `Path parameters` are now **immutable**. Now you don't have to copy a `path parameter` before passing to another function which maybe modifies it, this has a side-affect of `context.GetString("key") = context.Param("key")` so you have to be careful to not override a path parameter via other custom (per-context) user value.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## v3 -> v4 long term support
|
## v3 -> v4 long term support
|
||||||
|
|
||||||
- **NEW**: `iris.StaticEmbedded`/`app := iris.New(); app.StaticEmbedded` - Embed static assets into your executable with [go-bindata](https://github.com/jteeuwen/go-bindata) and serve them.
|
- **NEW**: `iris.StaticEmbedded`/`app := iris.New(); app.StaticEmbedded` - Embed static assets into your executable with [go-bindata](https://github.com/jteeuwen/go-bindata) and serve them.
|
||||||
|
|
13
README.md
13
README.md
|
@ -19,7 +19,7 @@
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
<a href="https://github.com/kataras/iris/releases"><img src="https://img.shields.io/badge/%20version%20-%204%20LTS%20-blue.svg?style=flat-square" alt="Releases"></a>
|
<a href="https://github.com/kataras/iris/releases"><img src="https://img.shields.io/badge/%20version%20-%205.0.1%20-blue.svg?style=flat-square" alt="Releases"></a>
|
||||||
|
|
||||||
<a href="https://github.com/iris-contrib/examples"><img src="https://img.shields.io/badge/%20examples-repository-3362c2.svg?style=flat-square" alt="Examples"></a>
|
<a href="https://github.com/iris-contrib/examples"><img src="https://img.shields.io/badge/%20examples-repository-3362c2.svg?style=flat-square" alt="Examples"></a>
|
||||||
|
|
||||||
|
@ -870,14 +870,9 @@ I recommend writing your API tests using this new library, [httpexpect](https://
|
||||||
Versioning
|
Versioning
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Current: **V4 LTS**
|
Current: **5.0.1**
|
||||||
|
|
||||||
A new LTS version is released every 6 months
|
Todo
|
||||||
|
|
||||||
> LTS stands for Long Term Support
|
|
||||||
|
|
||||||
|
|
||||||
Todo for the next release
|
|
||||||
------------
|
------------
|
||||||
|
|
||||||
- [ ] Server-side React render, as requested [here](https://github.com/kataras/iris/issues/503)
|
- [ ] Server-side React render, as requested [here](https://github.com/kataras/iris/issues/503)
|
||||||
|
@ -913,7 +908,7 @@ under the Apache Version 2 license found in the [LICENSE file](LICENSE).
|
||||||
[Travis]: http://travis-ci.org/kataras/iris
|
[Travis]: http://travis-ci.org/kataras/iris
|
||||||
[License Widget]: https://img.shields.io/badge/license-Apache%20Version%202-E91E63.svg?style=flat-square
|
[License Widget]: https://img.shields.io/badge/license-Apache%20Version%202-E91E63.svg?style=flat-square
|
||||||
[License]: https://github.com/kataras/iris/blob/master/LICENSE
|
[License]: https://github.com/kataras/iris/blob/master/LICENSE
|
||||||
[Release Widget]: https://img.shields.io/badge/release-V4%20LTS%20-blue.svg?style=flat-square
|
[Release Widget]: https://img.shields.io/badge/release-V5.0.1%20-blue.svg?style=flat-square
|
||||||
[Release]: https://github.com/kataras/iris/releases
|
[Release]: https://github.com/kataras/iris/releases
|
||||||
[Chat Widget]: https://img.shields.io/badge/community-chat%20-00BCD4.svg?style=flat-square
|
[Chat Widget]: https://img.shields.io/badge/community-chat%20-00BCD4.svg?style=flat-square
|
||||||
[Chat]: https://kataras.rocket.chat/channel/iris
|
[Chat]: https://kataras.rocket.chat/channel/iris
|
||||||
|
|
111
context.go
111
context.go
|
@ -2,6 +2,7 @@ package iris
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
@ -93,7 +94,6 @@ type (
|
||||||
// it is not good practice to use this object in goroutines, for these cases use the .Clone()
|
// it is not good practice to use this object in goroutines, for these cases use the .Clone()
|
||||||
Context struct {
|
Context struct {
|
||||||
*fasthttp.RequestCtx
|
*fasthttp.RequestCtx
|
||||||
Params PathParameters
|
|
||||||
framework *Framework
|
framework *Framework
|
||||||
//keep track all registed middleware (handlers)
|
//keep track all registed middleware (handlers)
|
||||||
Middleware Middleware // exported because is useful for debugging
|
Middleware Middleware // exported because is useful for debugging
|
||||||
|
@ -145,36 +145,6 @@ func (ctx *Context) GetHandlerName() string {
|
||||||
|
|
||||||
/* Request */
|
/* Request */
|
||||||
|
|
||||||
// Param returns the string representation of the key's path named parameter's value
|
|
||||||
//
|
|
||||||
// Return value should be never stored directly, instead store it to a local variable,
|
|
||||||
// for example
|
|
||||||
// instead of: context.Session().Set("name", ctx.Param("user"))
|
|
||||||
// do this: username:= ctx.Param("user");ctx.Session().Set("name", username)
|
|
||||||
func (ctx *Context) Param(key string) string {
|
|
||||||
return ctx.Params.Get(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamInt returns the int representation of the key's path named parameter's value
|
|
||||||
//
|
|
||||||
// Return value should be never stored directly, instead store it to a local variable,
|
|
||||||
// for example
|
|
||||||
// instead of: context.Session().Set("age", ctx.Param("age"))
|
|
||||||
// do this: age:= ctx.Param("age");ctx.Session().Set("age", age)
|
|
||||||
func (ctx *Context) ParamInt(key string) (int, error) {
|
|
||||||
return strconv.Atoi(ctx.Param(key))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamInt64 returns the int64 representation of the key's path named parameter's value
|
|
||||||
//
|
|
||||||
// Return value should be never stored directly, instead store it to a local variable,
|
|
||||||
// for example
|
|
||||||
// instead of: context.Session().Set("ms", ctx.ParamInt64("ms"))
|
|
||||||
// do this: ms:= ctx.ParamInt64("ms");ctx.Session().Set("ms", ms)
|
|
||||||
func (ctx *Context) ParamInt64(key string) (int64, error) {
|
|
||||||
return strconv.ParseInt(ctx.Param(key), 10, 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
// URLParam returns the get parameter from a request , if any
|
// URLParam returns the get parameter from a request , if any
|
||||||
func (ctx *Context) URLParam(key string) string {
|
func (ctx *Context) URLParam(key string) string {
|
||||||
return string(ctx.RequestCtx.Request.URI().QueryArgs().Peek(key))
|
return string(ctx.RequestCtx.Request.URI().QueryArgs().Peek(key))
|
||||||
|
@ -826,6 +796,14 @@ func (ctx *Context) StreamReader(bodyStream io.Reader, bodySize int) {
|
||||||
|
|
||||||
/* Storage */
|
/* Storage */
|
||||||
|
|
||||||
|
// ValuesLen returns the total length of the user values storage, some of them maybe path parameters
|
||||||
|
func (ctx *Context) ValuesLen() (n int) {
|
||||||
|
ctx.VisitUserValues(func([]byte, interface{}) {
|
||||||
|
n++
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the user's value from a key
|
// Get returns the user's value from a key
|
||||||
// if doesn't exists returns nil
|
// if doesn't exists returns nil
|
||||||
func (ctx *Context) Get(key string) interface{} {
|
func (ctx *Context) Get(key string) interface{} {
|
||||||
|
@ -852,14 +830,19 @@ func (ctx *Context) GetString(key string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInt same as Get but returns the value as int
|
var errIntParse = errors.New("Unable to find or parse the integer, found: %#v")
|
||||||
// if nothing founds returns -1
|
|
||||||
func (ctx *Context) GetInt(key string) int {
|
// GetInt same as Get but tries to convert the return value as integer
|
||||||
if v, ok := ctx.Get(key).(int); ok {
|
// if nothing found or canno be parsed to integer it returns an error
|
||||||
return v
|
func (ctx *Context) GetInt(key string) (int, error) {
|
||||||
|
v := ctx.Get(key)
|
||||||
|
if vint, ok := v.(int); ok {
|
||||||
|
return vint, nil
|
||||||
|
} else if vstring, sok := v.(string); sok {
|
||||||
|
return strconv.Atoi(vstring)
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1
|
return -1, errIntParse.Format(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets a value to a key in the values map
|
// Set sets a value to a key in the values map
|
||||||
|
@ -867,6 +850,60 @@ func (ctx *Context) Set(key string, value interface{}) {
|
||||||
ctx.RequestCtx.SetUserValue(key, value)
|
ctx.RequestCtx.SetUserValue(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParamsLen tries to return all the stored values which values are string, probably most of them will be the path parameters
|
||||||
|
func (ctx *Context) ParamsLen() (n int) {
|
||||||
|
ctx.VisitUserValues(func(kb []byte, vg interface{}) {
|
||||||
|
if _, ok := vg.(string); ok {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param returns the string representation of the key's path named parameter's value
|
||||||
|
// same as GetString
|
||||||
|
func (ctx *Context) Param(key string) string {
|
||||||
|
return ctx.GetString(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParamInt returns the int representation of the key's path named parameter's value
|
||||||
|
// same as GetInt
|
||||||
|
func (ctx *Context) ParamInt(key string) (int, error) {
|
||||||
|
return ctx.GetInt(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParamInt64 returns the int64 representation of the key's path named parameter's value
|
||||||
|
func (ctx *Context) ParamInt64(key string) (int64, error) {
|
||||||
|
return strconv.ParseInt(ctx.Param(key), 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParamsSentence returns a string implementation of all parameters that this context keeps
|
||||||
|
// hasthe form of key1=value1,key2=value2...
|
||||||
|
func (ctx *Context) ParamsSentence() string {
|
||||||
|
var buff bytes.Buffer
|
||||||
|
ctx.VisitUserValues(func(kb []byte, vg interface{}) {
|
||||||
|
v, ok := vg.(string)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
k := string(kb)
|
||||||
|
buff.WriteString(k)
|
||||||
|
buff.WriteString("=")
|
||||||
|
buff.WriteString(v)
|
||||||
|
// we don't know where that (yet) stops so...
|
||||||
|
buff.WriteString(",")
|
||||||
|
|
||||||
|
})
|
||||||
|
result := buff.String()
|
||||||
|
if len(result) < 2 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return result[0 : len(result)-1]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// VisitAllCookies takes a visitor which loops on each (request's) cookie key and value
|
// VisitAllCookies takes a visitor which loops on each (request's) cookie key and value
|
||||||
//
|
//
|
||||||
// Note: the method ctx.Request.Header.VisitAllCookie by fasthttp, has a strange bug which I cannot solve at the moment.
|
// Note: the method ctx.Request.Header.VisitAllCookie by fasthttp, has a strange bug which I cannot solve at the moment.
|
||||||
|
|
|
@ -72,16 +72,24 @@ func TestContextDoNextStop(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type pathParameter struct {
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
type pathParameters []pathParameter
|
||||||
|
|
||||||
// White-box testing *
|
// White-box testing *
|
||||||
func TestContextParams(t *testing.T) {
|
func TestContextParams(t *testing.T) {
|
||||||
var context iris.Context
|
context := &iris.Context{RequestCtx: &fasthttp.RequestCtx{}}
|
||||||
params := iris.PathParameters{
|
params := pathParameters{
|
||||||
iris.PathParameter{Key: "testkey", Value: "testvalue"},
|
pathParameter{Key: "testkey", Value: "testvalue"},
|
||||||
iris.PathParameter{Key: "testkey2", Value: "testvalue2"},
|
pathParameter{Key: "testkey2", Value: "testvalue2"},
|
||||||
iris.PathParameter{Key: "id", Value: "3"},
|
pathParameter{Key: "id", Value: "3"},
|
||||||
iris.PathParameter{Key: "bigint", Value: "548921854390354"},
|
pathParameter{Key: "bigint", Value: "548921854390354"},
|
||||||
|
}
|
||||||
|
for _, p := range params {
|
||||||
|
context.Set(p.Key, p.Value)
|
||||||
}
|
}
|
||||||
context.Params = params
|
|
||||||
|
|
||||||
if v := context.Param(params[0].Key); v != params[0].Value {
|
if v := context.Param(params[0].Key); v != params[0].Value {
|
||||||
t.Fatalf("Expecting parameter value to be %s but we got %s", params[0].Value, context.Param("testkey"))
|
t.Fatalf("Expecting parameter value to be %s but we got %s", params[0].Value, context.Param("testkey"))
|
||||||
|
@ -90,8 +98,8 @@ func TestContextParams(t *testing.T) {
|
||||||
t.Fatalf("Expecting parameter value to be %s but we got %s", params[1].Value, context.Param("testkey2"))
|
t.Fatalf("Expecting parameter value to be %s but we got %s", params[1].Value, context.Param("testkey2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(context.Params) != len(params) {
|
if context.ParamsLen() != len(params) {
|
||||||
t.Fatalf("Expecting to have %d parameters but we got %d", len(params), len(context.Params))
|
t.Fatalf("Expecting to have %d parameters but we got %d", len(params), context.ParamsLen())
|
||||||
}
|
}
|
||||||
|
|
||||||
if vi, err := context.ParamInt(params[2].Key); err != nil {
|
if vi, err := context.ParamInt(params[2].Key); err != nil {
|
||||||
|
@ -111,7 +119,7 @@ func TestContextParams(t *testing.T) {
|
||||||
iris.ResetDefault()
|
iris.ResetDefault()
|
||||||
expectedParamsStr := "param1=myparam1,param2=myparam2,param3=myparam3afterstatic,anything=/andhere/anything/you/like"
|
expectedParamsStr := "param1=myparam1,param2=myparam2,param3=myparam3afterstatic,anything=/andhere/anything/you/like"
|
||||||
iris.Get("/path/:param1/:param2/staticpath/:param3/*anything", func(ctx *iris.Context) {
|
iris.Get("/path/:param1/:param2/staticpath/:param3/*anything", func(ctx *iris.Context) {
|
||||||
paramsStr := ctx.Params.String()
|
paramsStr := ctx.ParamsSentence()
|
||||||
ctx.Write(paramsStr)
|
ctx.Write(paramsStr)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -349,8 +357,8 @@ func TestContextRedirectTo(t *testing.T) {
|
||||||
iris.Get("/mypath", h)("my-path")
|
iris.Get("/mypath", h)("my-path")
|
||||||
iris.Get("/mypostpath", h)("my-post-path")
|
iris.Get("/mypostpath", h)("my-post-path")
|
||||||
iris.Get("mypath/with/params/:param1/:param2", func(ctx *iris.Context) {
|
iris.Get("mypath/with/params/:param1/:param2", func(ctx *iris.Context) {
|
||||||
if len(ctx.Params) != 2 {
|
if l := ctx.ParamsLen(); l != 2 {
|
||||||
t.Fatalf("Strange error, expecting parameters to be two but we got: %d", len(ctx.Params))
|
t.Fatalf("Strange error, expecting parameters to be two but we got: %d", l)
|
||||||
}
|
}
|
||||||
ctx.Write(ctx.PathString())
|
ctx.Write(ctx.PathString())
|
||||||
})("my-path-with-params")
|
})("my-path-with-params")
|
||||||
|
@ -462,7 +470,7 @@ func TestContextFlashMessages(t *testing.T) {
|
||||||
firstKey := "name"
|
firstKey := "name"
|
||||||
lastKey := "package"
|
lastKey := "package"
|
||||||
|
|
||||||
values := iris.PathParameters{iris.PathParameter{Key: firstKey, Value: "kataras"}, iris.PathParameter{Key: lastKey, Value: "iris"}}
|
values := pathParameters{pathParameter{Key: firstKey, Value: "kataras"}, pathParameter{Key: lastKey, Value: "iris"}}
|
||||||
jsonExpected := map[string]string{firstKey: "kataras", lastKey: "iris"}
|
jsonExpected := map[string]string{firstKey: "kataras", lastKey: "iris"}
|
||||||
// set the flashes, the cookies are filled
|
// set the flashes, the cookies are filled
|
||||||
iris.Put("/set", func(ctx *iris.Context) {
|
iris.Put("/set", func(ctx *iris.Context) {
|
||||||
|
|
94
http.go
94
http.go
|
@ -317,16 +317,6 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// PathParameter is a struct which contains Key and Value, used for named path parameters
|
|
||||||
PathParameter struct {
|
|
||||||
Key string
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
// PathParameters type for a slice of PathParameter
|
|
||||||
// Tt's a slice of PathParameter type, because it's faster than map
|
|
||||||
PathParameters []PathParameter
|
|
||||||
|
|
||||||
// entryCase is the type which the type of muxEntryusing in order to determinate what type (parameterized, anything, static...) is the perticular node
|
// entryCase is the type which the type of muxEntryusing in order to determinate what type (parameterized, anything, static...) is the perticular node
|
||||||
entryCase uint8
|
entryCase uint8
|
||||||
|
|
||||||
|
@ -356,58 +346,6 @@ var (
|
||||||
errMuxEntryWildcardMissingSlash = errors.New("Router: No slash(/) were found before wildcard in the route path: '%s' !")
|
errMuxEntryWildcardMissingSlash = errors.New("Router: No slash(/) were found before wildcard in the route path: '%s' !")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get returns a value from a key inside this Parameters
|
|
||||||
// If no parameter with this key given then it returns an empty string
|
|
||||||
func (params PathParameters) Get(key string) string {
|
|
||||||
for _, p := range params {
|
|
||||||
if p.Key == key {
|
|
||||||
return p.Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a string implementation of all parameters that this PathParameters object keeps
|
|
||||||
// hasthe form of key1=value1,key2=value2...
|
|
||||||
func (params PathParameters) String() string {
|
|
||||||
var buff bytes.Buffer
|
|
||||||
for i := range params {
|
|
||||||
buff.WriteString(params[i].Key)
|
|
||||||
buff.WriteString("=")
|
|
||||||
buff.WriteString(params[i].Value)
|
|
||||||
if i < len(params)-1 {
|
|
||||||
buff.WriteString(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return buff.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseParams receives a string and returns PathParameters (slice of PathParameter)
|
|
||||||
// received string must have this form: key1=value1,key2=value2...
|
|
||||||
func ParseParams(str string) PathParameters {
|
|
||||||
_paramsstr := strings.Split(str, ",")
|
|
||||||
if len(_paramsstr) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
params := make(PathParameters, 0) // PathParameters{}
|
|
||||||
|
|
||||||
// for i := 0; i < len(_paramsstr); i++ {
|
|
||||||
for i := range _paramsstr {
|
|
||||||
idxOfEq := strings.IndexRune(_paramsstr[i], '=')
|
|
||||||
if idxOfEq == -1 {
|
|
||||||
//error
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
key := _paramsstr[i][:idxOfEq]
|
|
||||||
val := _paramsstr[i][idxOfEq+1:]
|
|
||||||
params = append(params, PathParameter{key, val})
|
|
||||||
}
|
|
||||||
return params
|
|
||||||
}
|
|
||||||
|
|
||||||
// getParamsLen returns the parameters length from a given path
|
// getParamsLen returns the parameters length from a given path
|
||||||
func getParamsLen(path string) uint8 {
|
func getParamsLen(path string) uint8 {
|
||||||
var n uint
|
var n uint
|
||||||
|
@ -644,8 +582,7 @@ func (e *muxEntry) addNode(numParams uint8, path string, fullPath string, middle
|
||||||
}
|
}
|
||||||
|
|
||||||
// get is used by the Router, it finds and returns the correct muxEntry for a path
|
// get is used by the Router, it finds and returns the correct muxEntry for a path
|
||||||
func (e *muxEntry) get(path string, _params PathParameters) (middleware Middleware, params PathParameters, mustRedirect bool) {
|
func (e *muxEntry) get(path string, ctx *Context) (mustRedirect bool) {
|
||||||
params = _params
|
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
if len(path) > len(e.part) {
|
if len(path) > len(e.part) {
|
||||||
|
@ -674,13 +611,7 @@ loop:
|
||||||
end++
|
end++
|
||||||
}
|
}
|
||||||
|
|
||||||
if cap(params) < int(e.paramsLen) {
|
ctx.Set(e.part[1:], path[:end])
|
||||||
params = make(PathParameters, 0, e.paramsLen)
|
|
||||||
}
|
|
||||||
i := len(params)
|
|
||||||
params = params[:i+1]
|
|
||||||
params[i].Key = e.part[1:]
|
|
||||||
params[i].Value = path[:end]
|
|
||||||
|
|
||||||
if end < len(path) {
|
if end < len(path) {
|
||||||
if len(e.nodes) > 0 {
|
if len(e.nodes) > 0 {
|
||||||
|
@ -692,8 +623,7 @@ loop:
|
||||||
mustRedirect = (len(path) == end+1)
|
mustRedirect = (len(path) == end+1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if ctx.Middleware = e.middleware; ctx.Middleware != nil {
|
||||||
if middleware = e.middleware; middleware != nil {
|
|
||||||
return
|
return
|
||||||
} else if len(e.nodes) == 1 {
|
} else if len(e.nodes) == 1 {
|
||||||
e = e.nodes[0]
|
e = e.nodes[0]
|
||||||
|
@ -703,15 +633,9 @@ loop:
|
||||||
return
|
return
|
||||||
|
|
||||||
case matchEverything:
|
case matchEverything:
|
||||||
if cap(params) < int(e.paramsLen) {
|
|
||||||
params = make(PathParameters, 0, e.paramsLen)
|
|
||||||
}
|
|
||||||
i := len(params)
|
|
||||||
params = params[:i+1]
|
|
||||||
params[i].Key = e.part[2:]
|
|
||||||
params[i].Value = path
|
|
||||||
|
|
||||||
middleware = e.middleware
|
ctx.Set(e.part[2:], path)
|
||||||
|
ctx.Middleware = e.middleware
|
||||||
return
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -719,7 +643,7 @@ loop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if path == e.part {
|
} else if path == e.part {
|
||||||
if middleware = e.middleware; middleware != nil {
|
if ctx.Middleware = e.middleware; ctx.Middleware != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1159,11 +1083,9 @@ func (mux *serveMux) BuildHandler() HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
middleware, params, mustRedirect := tree.entry.get(routePath, context.Params) // pass the parameters here for 0 allocation
|
mustRedirect := tree.entry.get(routePath, context) // pass the parameters here for 0 allocation
|
||||||
if middleware != nil {
|
if context.Middleware != nil {
|
||||||
// ok we found the correct route, serve it and exit entirely from here
|
// ok we found the correct route, serve it and exit entirely from here
|
||||||
context.Params = params
|
|
||||||
context.Middleware = middleware
|
|
||||||
//ctx.Request.Header.SetUserAgentBytes(DefaultUserAgent)
|
//ctx.Request.Header.SetUserAgentBytes(DefaultUserAgent)
|
||||||
context.Do()
|
context.Do()
|
||||||
return
|
return
|
||||||
|
|
|
@ -348,7 +348,7 @@ func TestMuxSimple(t *testing.T) {
|
||||||
iris.HandleFunc(r.Method, r.Path, func(ctx *iris.Context) {
|
iris.HandleFunc(r.Method, r.Path, func(ctx *iris.Context) {
|
||||||
ctx.SetStatusCode(r.Status)
|
ctx.SetStatusCode(r.Status)
|
||||||
if r.Params != nil && len(r.Params) > 0 {
|
if r.Params != nil && len(r.Params) > 0 {
|
||||||
ctx.SetBodyString(ctx.Params.String())
|
ctx.SetBodyString(ctx.ParamsSentence())
|
||||||
} else if r.URLParams != nil && len(r.URLParams) > 0 {
|
} else if r.URLParams != nil && len(r.URLParams) > 0 {
|
||||||
if len(r.URLParams) != len(ctx.URLParams()) {
|
if len(r.URLParams) != len(ctx.URLParams()) {
|
||||||
t.Fatalf("Error when comparing length of url parameters %d != %d", len(r.URLParams), len(ctx.URLParams()))
|
t.Fatalf("Error when comparing length of url parameters %d != %d", len(r.URLParams), len(ctx.URLParams()))
|
||||||
|
|
22
iris.go
22
iris.go
|
@ -64,6 +64,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"bytes"
|
||||||
"github.com/kataras/go-errors"
|
"github.com/kataras/go-errors"
|
||||||
"github.com/kataras/go-fs"
|
"github.com/kataras/go-fs"
|
||||||
"github.com/kataras/go-serializer"
|
"github.com/kataras/go-serializer"
|
||||||
|
@ -76,9 +77,9 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// IsLongTermSupport flag is true when the below version number is a long-term-support version
|
// IsLongTermSupport flag is true when the below version number is a long-term-support version
|
||||||
IsLongTermSupport = true
|
IsLongTermSupport = false
|
||||||
// Version is the current version number of the Iris web framework
|
// Version is the current version number of the Iris web framework
|
||||||
Version = "4"
|
Version = "5.0.1"
|
||||||
|
|
||||||
banner = ` _____ _
|
banner = ` _____ _
|
||||||
|_ _| (_)
|
|_ _| (_)
|
||||||
|
@ -681,7 +682,6 @@ func ReleaseCtx(ctx *Context) {
|
||||||
// ReleaseCtx puts the Iris' Context back to the pool in order to be re-used
|
// ReleaseCtx puts the Iris' Context back to the pool in order to be re-used
|
||||||
// see .AcquireCtx & .Serve
|
// see .AcquireCtx & .Serve
|
||||||
func (s *Framework) ReleaseCtx(ctx *Context) {
|
func (s *Framework) ReleaseCtx(ctx *Context) {
|
||||||
ctx.Params = ctx.Params[0:0]
|
|
||||||
ctx.Middleware = nil
|
ctx.Middleware = nil
|
||||||
ctx.session = nil
|
ctx.session = nil
|
||||||
s.contextPool.Put(ctx)
|
s.contextPool.Put(ctx)
|
||||||
|
@ -1425,7 +1425,7 @@ func (api *muxAPI) API(path string, restAPI HandlerAPI, middleware ...HandlerFun
|
||||||
// or no, I changed my mind, let all be named parameters and let users to decide what info they need,
|
// or no, I changed my mind, let all be named parameters and let users to decide what info they need,
|
||||||
// using the Context to take more values (post form,url params and so on).-
|
// using the Context to take more values (post form,url params and so on).-
|
||||||
|
|
||||||
paramPrefix := "param"
|
paramPrefix := []byte("param")
|
||||||
for _, methodName := range AllMethods {
|
for _, methodName := range AllMethods {
|
||||||
methodWithBy := strings.Title(strings.ToLower(methodName)) + "By"
|
methodWithBy := strings.Title(strings.ToLower(methodName)) + "By"
|
||||||
if method, found := typ.MethodByName(methodWithBy); found {
|
if method, found := typ.MethodByName(methodWithBy); found {
|
||||||
|
@ -1439,9 +1439,9 @@ func (api *muxAPI) API(path string, restAPI HandlerAPI, middleware ...HandlerFun
|
||||||
|
|
||||||
for i := 1; i < numInLen; i++ { // from 1 because the first is the 'object'
|
for i := 1; i < numInLen; i++ { // from 1 because the first is the 'object'
|
||||||
if registedPath[len(registedPath)-1] == slashByte {
|
if registedPath[len(registedPath)-1] == slashByte {
|
||||||
registedPath += ":" + paramPrefix + strconv.Itoa(i)
|
registedPath += ":" + string(paramPrefix) + strconv.Itoa(i)
|
||||||
} else {
|
} else {
|
||||||
registedPath += "/:" + paramPrefix + strconv.Itoa(i)
|
registedPath += "/:" + string(paramPrefix) + strconv.Itoa(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,15 +1454,15 @@ func (api *muxAPI) API(path string, restAPI HandlerAPI, middleware ...HandlerFun
|
||||||
newController.FieldByName("Context").Set(reflect.ValueOf(ctx))
|
newController.FieldByName("Context").Set(reflect.ValueOf(ctx))
|
||||||
args := make([]reflect.Value, paramsLen+1, paramsLen+1)
|
args := make([]reflect.Value, paramsLen+1, paramsLen+1)
|
||||||
args[0] = newController
|
args[0] = newController
|
||||||
realParamsLen := len(ctx.Params)
|
|
||||||
j := 1
|
j := 1
|
||||||
for i := 0; i < realParamsLen; i++ { // here we don't looping with the len we are already known by the 'API' because maybe there is a party/or/path witch accepting parameters before, see https://github.com/kataras/iris/issues/293
|
|
||||||
if strings.HasPrefix(ctx.Params[i].Key, paramPrefix) {
|
ctx.VisitUserValues(func(k []byte, v interface{}) {
|
||||||
args[j] = reflect.ValueOf(ctx.Params[i].Value)
|
if bytes.HasPrefix(k, paramPrefix) {
|
||||||
|
args[j] = reflect.ValueOf(v.(string))
|
||||||
|
|
||||||
j++ // the first parameter is the context, other are the path parameters, j++ to be align with (API's registered)paramsLen
|
j++ // the first parameter is the context, other are the path parameters, j++ to be align with (API's registered)paramsLen
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
methodFunc.Call(args)
|
methodFunc.Call(args)
|
||||||
})
|
})
|
||||||
|
|
|
@ -91,7 +91,7 @@ func buildGetCommand() *cli.Cmd {
|
||||||
availabletypes = append(availabletypes, "'"+k+"'")
|
availabletypes = append(availabletypes, "'"+k+"'")
|
||||||
}
|
}
|
||||||
// comma separated of projects' map key
|
// comma separated of projects' map key
|
||||||
return cli.Command("get", "gets & runs a simple protoype-based project").
|
return cli.Command("get", "gets & runs a simple prototype-based project").
|
||||||
Flag("type",
|
Flag("type",
|
||||||
"basic",
|
"basic",
|
||||||
// we take the os.Args in order to have access both via subcommand and when flag passed
|
// we take the os.Args in order to have access both via subcommand and when flag passed
|
||||||
|
|
Loading…
Reference in New Issue
Block a user