mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +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`.
|
||||
|
||||
|
||||
## 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
|
||||
|
||||
- **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/>
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -870,14 +870,9 @@ I recommend writing your API tests using this new library, [httpexpect](https://
|
|||
Versioning
|
||||
------------
|
||||
|
||||
Current: **V4 LTS**
|
||||
Current: **5.0.1**
|
||||
|
||||
A new LTS version is released every 6 months
|
||||
|
||||
> LTS stands for Long Term Support
|
||||
|
||||
|
||||
Todo for the next release
|
||||
Todo
|
||||
------------
|
||||
|
||||
- [ ] 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
|
||||
[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
|
||||
[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
|
||||
[Chat Widget]: https://img.shields.io/badge/community-chat%20-00BCD4.svg?style=flat-square
|
||||
[Chat]: https://kataras.rocket.chat/channel/iris
|
||||
|
|
111
context.go
111
context.go
|
@ -2,6 +2,7 @@ package iris
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
|
@ -93,7 +94,6 @@ type (
|
|||
// it is not good practice to use this object in goroutines, for these cases use the .Clone()
|
||||
Context struct {
|
||||
*fasthttp.RequestCtx
|
||||
Params PathParameters
|
||||
framework *Framework
|
||||
//keep track all registed middleware (handlers)
|
||||
Middleware Middleware // exported because is useful for debugging
|
||||
|
@ -145,36 +145,6 @@ func (ctx *Context) GetHandlerName() string {
|
|||
|
||||
/* 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
|
||||
func (ctx *Context) URLParam(key string) string {
|
||||
return string(ctx.RequestCtx.Request.URI().QueryArgs().Peek(key))
|
||||
|
@ -826,6 +796,14 @@ func (ctx *Context) StreamReader(bodyStream io.Reader, bodySize int) {
|
|||
|
||||
/* 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
|
||||
// if doesn't exists returns nil
|
||||
func (ctx *Context) Get(key string) interface{} {
|
||||
|
@ -852,14 +830,19 @@ func (ctx *Context) GetString(key string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// GetInt same as Get but returns the value as int
|
||||
// if nothing founds returns -1
|
||||
func (ctx *Context) GetInt(key string) int {
|
||||
if v, ok := ctx.Get(key).(int); ok {
|
||||
return v
|
||||
var errIntParse = errors.New("Unable to find or parse the integer, found: %#v")
|
||||
|
||||
// GetInt same as Get but tries to convert the return value as integer
|
||||
// if nothing found or canno be parsed to integer it returns an error
|
||||
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
|
||||
|
@ -867,6 +850,60 @@ func (ctx *Context) Set(key string, value interface{}) {
|
|||
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
|
||||
//
|
||||
// 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 *
|
||||
func TestContextParams(t *testing.T) {
|
||||
var context iris.Context
|
||||
params := iris.PathParameters{
|
||||
iris.PathParameter{Key: "testkey", Value: "testvalue"},
|
||||
iris.PathParameter{Key: "testkey2", Value: "testvalue2"},
|
||||
iris.PathParameter{Key: "id", Value: "3"},
|
||||
iris.PathParameter{Key: "bigint", Value: "548921854390354"},
|
||||
context := &iris.Context{RequestCtx: &fasthttp.RequestCtx{}}
|
||||
params := pathParameters{
|
||||
pathParameter{Key: "testkey", Value: "testvalue"},
|
||||
pathParameter{Key: "testkey2", Value: "testvalue2"},
|
||||
pathParameter{Key: "id", Value: "3"},
|
||||
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 {
|
||||
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"))
|
||||
}
|
||||
|
||||
if len(context.Params) != len(params) {
|
||||
t.Fatalf("Expecting to have %d parameters but we got %d", len(params), len(context.Params))
|
||||
if context.ParamsLen() != len(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 {
|
||||
|
@ -111,7 +119,7 @@ func TestContextParams(t *testing.T) {
|
|||
iris.ResetDefault()
|
||||
expectedParamsStr := "param1=myparam1,param2=myparam2,param3=myparam3afterstatic,anything=/andhere/anything/you/like"
|
||||
iris.Get("/path/:param1/:param2/staticpath/:param3/*anything", func(ctx *iris.Context) {
|
||||
paramsStr := ctx.Params.String()
|
||||
paramsStr := ctx.ParamsSentence()
|
||||
ctx.Write(paramsStr)
|
||||
})
|
||||
|
||||
|
@ -349,8 +357,8 @@ func TestContextRedirectTo(t *testing.T) {
|
|||
iris.Get("/mypath", h)("my-path")
|
||||
iris.Get("/mypostpath", h)("my-post-path")
|
||||
iris.Get("mypath/with/params/:param1/:param2", func(ctx *iris.Context) {
|
||||
if len(ctx.Params) != 2 {
|
||||
t.Fatalf("Strange error, expecting parameters to be two but we got: %d", len(ctx.Params))
|
||||
if l := ctx.ParamsLen(); l != 2 {
|
||||
t.Fatalf("Strange error, expecting parameters to be two but we got: %d", l)
|
||||
}
|
||||
ctx.Write(ctx.PathString())
|
||||
})("my-path-with-params")
|
||||
|
@ -462,7 +470,7 @@ func TestContextFlashMessages(t *testing.T) {
|
|||
firstKey := "name"
|
||||
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"}
|
||||
// set the flashes, the cookies are filled
|
||||
iris.Put("/set", func(ctx *iris.Context) {
|
||||
|
|
94
http.go
94
http.go
|
@ -317,16 +317,6 @@ const (
|
|||
)
|
||||
|
||||
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 uint8
|
||||
|
||||
|
@ -356,58 +346,6 @@ var (
|
|||
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
|
||||
func getParamsLen(path string) uint8 {
|
||||
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
|
||||
func (e *muxEntry) get(path string, _params PathParameters) (middleware Middleware, params PathParameters, mustRedirect bool) {
|
||||
params = _params
|
||||
func (e *muxEntry) get(path string, ctx *Context) (mustRedirect bool) {
|
||||
loop:
|
||||
for {
|
||||
if len(path) > len(e.part) {
|
||||
|
@ -674,13 +611,7 @@ loop:
|
|||
end++
|
||||
}
|
||||
|
||||
if cap(params) < int(e.paramsLen) {
|
||||
params = make(PathParameters, 0, e.paramsLen)
|
||||
}
|
||||
i := len(params)
|
||||
params = params[:i+1]
|
||||
params[i].Key = e.part[1:]
|
||||
params[i].Value = path[:end]
|
||||
ctx.Set(e.part[1:], path[:end])
|
||||
|
||||
if end < len(path) {
|
||||
if len(e.nodes) > 0 {
|
||||
|
@ -692,8 +623,7 @@ loop:
|
|||
mustRedirect = (len(path) == end+1)
|
||||
return
|
||||
}
|
||||
|
||||
if middleware = e.middleware; middleware != nil {
|
||||
if ctx.Middleware = e.middleware; ctx.Middleware != nil {
|
||||
return
|
||||
} else if len(e.nodes) == 1 {
|
||||
e = e.nodes[0]
|
||||
|
@ -703,15 +633,9 @@ loop:
|
|||
return
|
||||
|
||||
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
|
||||
|
||||
default:
|
||||
|
@ -719,7 +643,7 @@ loop:
|
|||
}
|
||||
}
|
||||
} else if path == e.part {
|
||||
if middleware = e.middleware; middleware != nil {
|
||||
if ctx.Middleware = e.middleware; ctx.Middleware != nil {
|
||||
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
|
||||
if middleware != nil {
|
||||
mustRedirect := tree.entry.get(routePath, context) // pass the parameters here for 0 allocation
|
||||
if context.Middleware != nil {
|
||||
// ok we found the correct route, serve it and exit entirely from here
|
||||
context.Params = params
|
||||
context.Middleware = middleware
|
||||
//ctx.Request.Header.SetUserAgentBytes(DefaultUserAgent)
|
||||
context.Do()
|
||||
return
|
||||
|
|
|
@ -348,7 +348,7 @@ func TestMuxSimple(t *testing.T) {
|
|||
iris.HandleFunc(r.Method, r.Path, func(ctx *iris.Context) {
|
||||
ctx.SetStatusCode(r.Status)
|
||||
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 {
|
||||
if 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"
|
||||
"time"
|
||||
|
||||
"bytes"
|
||||
"github.com/kataras/go-errors"
|
||||
"github.com/kataras/go-fs"
|
||||
"github.com/kataras/go-serializer"
|
||||
|
@ -76,9 +77,9 @@ import (
|
|||
|
||||
const (
|
||||
// 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 = "4"
|
||||
Version = "5.0.1"
|
||||
|
||||
banner = ` _____ _
|
||||
|_ _| (_)
|
||||
|
@ -681,7 +682,6 @@ func ReleaseCtx(ctx *Context) {
|
|||
// ReleaseCtx puts the Iris' Context back to the pool in order to be re-used
|
||||
// see .AcquireCtx & .Serve
|
||||
func (s *Framework) ReleaseCtx(ctx *Context) {
|
||||
ctx.Params = ctx.Params[0:0]
|
||||
ctx.Middleware = nil
|
||||
ctx.session = nil
|
||||
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,
|
||||
// using the Context to take more values (post form,url params and so on).-
|
||||
|
||||
paramPrefix := "param"
|
||||
paramPrefix := []byte("param")
|
||||
for _, methodName := range AllMethods {
|
||||
methodWithBy := strings.Title(strings.ToLower(methodName)) + "By"
|
||||
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'
|
||||
if registedPath[len(registedPath)-1] == slashByte {
|
||||
registedPath += ":" + paramPrefix + strconv.Itoa(i)
|
||||
registedPath += ":" + string(paramPrefix) + strconv.Itoa(i)
|
||||
} 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))
|
||||
args := make([]reflect.Value, paramsLen+1, paramsLen+1)
|
||||
args[0] = newController
|
||||
realParamsLen := len(ctx.Params)
|
||||
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) {
|
||||
args[j] = reflect.ValueOf(ctx.Params[i].Value)
|
||||
|
||||
ctx.VisitUserValues(func(k []byte, v interface{}) {
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
methodFunc.Call(args)
|
||||
})
|
||||
|
|
|
@ -91,7 +91,7 @@ func buildGetCommand() *cli.Cmd {
|
|||
availabletypes = append(availabletypes, "'"+k+"'")
|
||||
}
|
||||
// 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",
|
||||
"basic",
|
||||
// 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