Update to 6.0.7

This commit is contained in:
Gerasimos (Makis) Maropoulos 2017-01-10 08:54:39 +02:00
parent c476fe8921
commit 893271bf02
8 changed files with 59 additions and 29 deletions

View File

@ -2,6 +2,27 @@
**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`.
## 6.0.6 -> 6.0.7
- `iris.Config.DisablePathEscape` -> renamed to `iris.Config.EnablePathEscape`, which defaults to false. Path escape is turned off by-default now,
if you're waiting for unescaped path parameters, then just enable it by putting: `iris.Config.EnablePathEscape = true` anywhere in your code OR
use the `context.ParamDecoded` instead of the context.Param when you want to escape a single path parameter.
- Example for `iris.UsePreRender` https://github.com/iris-contrib/examples/tree/master/template_engines/template_prerender
## 6.0.5 -> 6.0.6
http.Request access from WebsocketConnection.
Example:
- https://github.com/iris-contrib/examples/blob/master/websocket/main.go#L34
Relative commits to kataras/go-websocket:
- https://github.com/kataras/go-websocket/commit/550fc8b32eb13b3b4a4bfeb227ef1a896c8f8698
- https://github.com/kataras/go-websocket/commit/62c2d989d8b5e9126cdbf451c0e41e2e2b0b31b8
## 6.0.4 -> 6.0.5 ## 6.0.4 -> 6.0.5
- Add `iris.DestroySessionByID(string)` and `iris.DestroyAllSessions()` functions as requested by a community member in the [chat](https://kataras.rocket.chat/channel/iris) - Add `iris.DestroySessionByID(string)` and `iris.DestroyAllSessions()` functions as requested by a community member in the [chat](https://kataras.rocket.chat/channel/iris)

View File

@ -18,7 +18,7 @@
<br/> <br/>
<a href="https://github.com/kataras/iris/blob/master/HISTORY.md"><img src="https://img.shields.io/badge/%20version%20-%206.0.6%20-blue.svg?style=flat-square" alt="CHANGELOG/HISTORY"></a> <a href="https://github.com/kataras/iris/blob/master/HISTORY.md"><img src="https://img.shields.io/badge/%20version%20-%206.0.7%20-blue.svg?style=flat-square" alt="CHANGELOG/HISTORY"></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>
@ -938,14 +938,14 @@ You can read the full article [here](https://translate.google.com/translate?sl=a
Testing Testing
------------ ------------
I recommend writing your API tests using this new library, [httpexpect](https://github.com/gavv/httpexpect). You can find Iris examples [here](https://github.com/kataras/iris/blob/master/vendor/github.com/gavv/httpexpect/_examples/iris_test.go), [here](https://github.com/kataras/iris/blob/master/http_test.go) and [here](https://github.com/kataras/iris/blob/master/context_test.go). I recommend testing your API using this new library, [httpexpect](https://github.com/gavv/httpexpect). You can find Iris examples [here](https://github.com/gavv/httpexpect/blob/master/_examples/iris_test.go), [here](https://github.com/kataras/iris/blob/master/http_test.go) and [here](https://github.com/kataras/iris/blob/master/context_test.go).
Versioning Versioning
------------ ------------
Current: **v6.0.6** Current: **v6.0.7**
Stable: **[v5/fasthttp](https://github.com/kataras/iris/tree/5.0.0)** Older: **[v5/fasthttp](https://github.com/kataras/iris/tree/5.0.0)**
Iris is a **Community-Driven** Project, waiting for your suggestions and [feature requests](https://github.com/kataras/iris/issues?utf8=%E2%9C%93&q=label%3A%22feature%20request%22)! Iris is a **Community-Driven** Project, waiting for your suggestions and [feature requests](https://github.com/kataras/iris/issues?utf8=%E2%9C%93&q=label%3A%22feature%20request%22)!

View File

@ -127,10 +127,10 @@ type Configuration struct {
// Default is false // Default is false
DisablePathCorrection bool DisablePathCorrection bool
// DisablePathEscape when is false then its escapes the path, the named parameters (if any). // EnablePathEscape when is true then its escapes the path, the named parameters (if any).
// Change to true it if you want something like this https://github.com/kataras/iris/issues/135 to work // Change to false it if you want something like this https://github.com/kataras/iris/issues/135 to work
// //
// When do you need to Disable(true) it: // When do you need to Disable(false) it:
// accepts parameters with slash '/' // accepts parameters with slash '/'
// Request: http://localhost:8080/details/Project%2FDelta // Request: http://localhost:8080/details/Project%2FDelta
// ctx.Param("project") returns the raw named parameter: Project%2FDelta // ctx.Param("project") returns the raw named parameter: Project%2FDelta
@ -139,7 +139,7 @@ type Configuration struct {
// Look here: https://github.com/kataras/iris/issues/135 for more // Look here: https://github.com/kataras/iris/issues/135 for more
// //
// Default is false // Default is false
DisablePathEscape bool EnablePathEscape bool
// FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and fires the 405 error instead of 404 // FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and fires the 405 error instead of 404
// Default is false // Default is false
@ -325,10 +325,10 @@ var (
} }
// OptionDisablePathEscape when is false then its escapes the path, the named parameters (if any). // OptionEnablePathEscape when is true then its escapes the path, the named path parameters (if any).
OptionDisablePathEscape = func(val bool) OptionSet { OptionEnablePathEscape = func(val bool) OptionSet {
return func(c *Configuration) { return func(c *Configuration) {
c.DisablePathEscape = val c.EnablePathEscape = val
} }
} }
@ -435,7 +435,7 @@ var (
// Default values for base Iris conf // Default values for base Iris conf
const ( const (
DefaultDisablePathCorrection = false DefaultDisablePathCorrection = false
DefaultDisablePathEscape = false DefaultEnablePathEscape = false
DefaultCharset = "UTF-8" DefaultCharset = "UTF-8"
DefaultLoggerPreffix = "[IRIS] " DefaultLoggerPreffix = "[IRIS] "
// Per-connection buffer size for requests' reading. // Per-connection buffer size for requests' reading.
@ -469,7 +469,7 @@ func DefaultConfiguration() Configuration {
CheckForUpdates: false, CheckForUpdates: false,
CheckForUpdatesSync: false, CheckForUpdatesSync: false,
DisablePathCorrection: DefaultDisablePathCorrection, DisablePathCorrection: DefaultDisablePathCorrection,
DisablePathEscape: DefaultDisablePathEscape, EnablePathEscape: DefaultEnablePathEscape,
FireMethodNotAllowed: false, FireMethodNotAllowed: false,
DisableBanner: false, DisableBanner: false,
LoggerOut: DefaultLoggerOut, LoggerOut: DefaultLoggerOut,

View File

@ -242,15 +242,15 @@ func (ctx *Context) VirtualHostname() string {
// Path returns the full escaped path as string // Path returns the full escaped path as string
// for unescaped use: ctx.RequestCtx.RequestURI() or RequestPath(escape bool) // for unescaped use: ctx.RequestCtx.RequestURI() or RequestPath(escape bool)
func (ctx *Context) Path() string { func (ctx *Context) Path() string {
return ctx.RequestPath(!ctx.framework.Config.DisablePathEscape) return ctx.RequestPath(ctx.framework.Config.EnablePathEscape)
} }
// RequestPath returns the requested path // RequestPath returns the requested path
func (ctx *Context) RequestPath(escape bool) string { func (ctx *Context) RequestPath(escape bool) string {
if escape { if escape {
return ctx.Request.URL.EscapedPath() return DecodeQuery(ctx.Request.URL.EscapedPath())
} }
return ctx.Request.RequestURI return ctx.Request.URL.Path
} }
// RemoteAddr tries to return the real client's request IP // RemoteAddr tries to return the real client's request IP
@ -957,16 +957,16 @@ func (ctx *Context) Set(key string, value interface{}) {
// //
// visitor must not retain references to key and value after returning. // visitor must not retain references to key and value after returning.
// Make key and/or value copies if you need storing them after returning. // Make key and/or value copies if you need storing them after returning.
func (ctx *Context) VisitValues(visitor func([]byte, interface{})) { func (ctx *Context) VisitValues(visitor func(string, interface{})) {
for i, n := 0, len(ctx.values); i < n; i++ { for i, n := 0, len(ctx.values); i < n; i++ {
kv := &ctx.values[i] kv := &ctx.values[i]
visitor(kv.key, kv.value) visitor(string(kv.key), kv.value)
} }
} }
// ParamsLen tries to return all the stored values which values are string, probably most of them will be the path parameters // 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) { func (ctx *Context) ParamsLen() (n int) {
ctx.VisitValues(func(kb []byte, vg interface{}) { ctx.VisitValues(func(kb string, vg interface{}) {
if _, ok := vg.(string); ok { if _, ok := vg.(string); ok {
n++ n++
} }
@ -1001,7 +1001,7 @@ func (ctx *Context) ParamInt64(key string) (int64, error) {
// hasthe form of key1=value1,key2=value2... // hasthe form of key1=value1,key2=value2...
func (ctx *Context) ParamsSentence() string { func (ctx *Context) ParamsSentence() string {
var buff bytes.Buffer var buff bytes.Buffer
ctx.VisitValues(func(kb []byte, vg interface{}) { ctx.VisitValues(func(kb string, vg interface{}) {
v, ok := vg.(string) v, ok := vg.(string)
if !ok { if !ok {
return return

View File

@ -127,7 +127,7 @@ func TestContextURLParams(t *testing.T) {
params := ctx.URLParams() params := ctx.URLParams()
ctx.JSON(iris.StatusOK, params) ctx.JSON(iris.StatusOK, params)
}) })
e := httptest.New(iris.Default, t) e := httptest.New(iris.Default, t, httptest.Debug(true))
e.GET("/").WithQueryObject(passedParams).Expect().Status(iris.StatusOK).JSON().Equal(passedParams) e.GET("/").WithQueryObject(passedParams).Expect().Status(iris.StatusOK).JSON().Equal(passedParams)
} }

View File

@ -322,7 +322,7 @@ func TestMuxSimple(t *testing.T) {
{"GET", "/test_get_urlparameter2/second", "/test_get_urlparameter2/second", "name=irisurl&something=anything", "name=irisurl,something=anything", 200, true, nil, []param{{"name", "irisurl"}, {"something", "anything"}}}, {"GET", "/test_get_urlparameter2/second", "/test_get_urlparameter2/second", "name=irisurl&something=anything", "name=irisurl,something=anything", 200, true, nil, []param{{"name", "irisurl"}, {"something", "anything"}}},
{"GET", "/test_get_urlparameter2/first/second/third", "/test_get_urlparameter2/first/second/third", "name=irisurl&something=anything&else=elsehere", "name=irisurl,something=anything,else=elsehere", 200, true, nil, []param{{"name", "irisurl"}, {"something", "anything"}, {"else", "elsehere"}}}, {"GET", "/test_get_urlparameter2/first/second/third", "/test_get_urlparameter2/first/second/third", "name=irisurl&something=anything&else=elsehere", "name=irisurl,something=anything,else=elsehere", 200, true, nil, []param{{"name", "irisurl"}, {"something", "anything"}, {"else", "elsehere"}}},
} }
defer iris.Close()
iris.ResetDefault() iris.ResetDefault()
for idx := range testRoutes { for idx := range testRoutes {
@ -353,7 +353,7 @@ func TestMuxSimple(t *testing.T) {
} }
} }
e := httptest.New(iris.Default, t) e := httptest.New(iris.Default, t, httptest.Debug(true))
// run the tests (1) // run the tests (1)
for idx := range testRoutes { for idx := range testRoutes {
@ -483,6 +483,7 @@ func TestRealSubdomainSimple(t *testing.T) {
func TestMuxPathEscape(t *testing.T) { func TestMuxPathEscape(t *testing.T) {
iris.ResetDefault() iris.ResetDefault()
iris.Config.EnablePathEscape = true
iris.Get("/details/:name", func(ctx *iris.Context) { iris.Get("/details/:name", func(ctx *iris.Context) {
name := ctx.ParamDecoded("name") name := ctx.ParamDecoded("name")

15
iris.go
View File

@ -54,7 +54,6 @@ visit https://docs.iris-go.com
package iris // import "github.com/kataras/iris" package iris // import "github.com/kataras/iris"
import ( import (
"bytes"
"fmt" "fmt"
"log" "log"
"net" "net"
@ -81,7 +80,7 @@ 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 = false 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 = "6.0.6" Version = "6.0.7"
banner = ` _____ _ banner = ` _____ _
|_ _| (_) |_ _| (_)
@ -866,6 +865,8 @@ func (s *Framework) UseSerializer(forContentType string, e serializer.Serializer
// so, you can change the filenameOrSource, the page binding, the options, and even add cookies, session value or a flash message through ctx // so, you can change the filenameOrSource, the page binding, the options, and even add cookies, session value or a flash message through ctx
// the return value of a PreRender is a boolean, if returns false then the next PreRender will not be executed, keep note // the return value of a PreRender is a boolean, if returns false then the next PreRender will not be executed, keep note
// that the actual context's Render will be called at any case. // that the actual context's Render will be called at any case.
//
// Example: https://github.com/iris-contrib/examples/tree/master/template_engines/template_prerender
func UsePreRender(pre PreRender) { func UsePreRender(pre PreRender) {
Default.UsePreRender(pre) Default.UsePreRender(pre)
} }
@ -877,6 +878,8 @@ func UsePreRender(pre PreRender) {
// so, you can change the filenameOrSource, the page binding, the options, and even add cookies, session value or a flash message through ctx // so, you can change the filenameOrSource, the page binding, the options, and even add cookies, session value or a flash message through ctx
// the return value of a PreRender is a boolean, if returns false then the next PreRender will not be executed, keep note // the return value of a PreRender is a boolean, if returns false then the next PreRender will not be executed, keep note
// that the actual context's Render will be called at any case. // that the actual context's Render will be called at any case.
//
// Example: https://github.com/iris-contrib/examples/tree/master/template_engines/template_prerender
func (s *Framework) UsePreRender(pre PreRender) { func (s *Framework) UsePreRender(pre PreRender) {
s.templates.usePreRender(pre) s.templates.usePreRender(pre)
} }
@ -1069,7 +1072,7 @@ func DecodeQuery(path string) string {
func DecodeURL(uri string) string { func DecodeURL(uri string) string {
u, err := url.Parse(uri) u, err := url.Parse(uri)
if err != nil { if err != nil {
return "" return uri
} }
return u.String() return u.String()
} }
@ -1521,7 +1524,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 := []byte("param") paramPrefix := "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 {
@ -1552,8 +1555,8 @@ func (api *muxAPI) API(path string, restAPI HandlerAPI, middleware ...HandlerFun
args[0] = newController args[0] = newController
j := 1 j := 1
ctx.VisitValues(func(k []byte, v interface{}) { ctx.VisitValues(func(k string, v interface{}) {
if bytes.HasPrefix(k, paramPrefix) { if strings.HasPrefix(k, paramPrefix) {
args[j] = reflect.ValueOf(v.(string)) 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

View File

@ -27,6 +27,8 @@ type (
// so, you can change the filenameOrSource, the page binding, the options, and even add cookies, session value or a flash message through ctx // so, you can change the filenameOrSource, the page binding, the options, and even add cookies, session value or a flash message through ctx
// the return value of a PreRender is a boolean, if returns false then the next PreRender will not be executed, keep note // the return value of a PreRender is a boolean, if returns false then the next PreRender will not be executed, keep note
// that the actual context's Render will be called at any case. // that the actual context's Render will be called at any case.
//
// Example: https://github.com/iris-contrib/examples/tree/master/template_engines/template_prerender
PreRender func(ctx *Context, filenameOrSource string, binding interface{}, options ...map[string]interface{}) bool PreRender func(ctx *Context, filenameOrSource string, binding interface{}, options ...map[string]interface{}) bool
) )
@ -74,9 +76,12 @@ func (t *templateEngines) render(isFile bool, ctx *Context, filenameOrSource str
} }
if len(t.prerenders) > 0 { if len(t.prerenders) > 0 {
for i := range t.prerenders { for i := range t.prerenders {
// I'm not making any checks here for performance reasons, means that // I'm not making any checks here for performance reasons, means that
// if binding is pointer it can be changed, otherwise not. // if binding is pointer it can be changed, otherwise not.
if shouldContinue := t.prerenders[i](ctx, filenameOrSource, binding, options...); !shouldContinue { if shouldContinue := t.prerenders[i](ctx, filenameOrSource, binding, options...); !shouldContinue {
break break
} }