Add DisableBodyConsumptionOnUnmarshal configuration field as discussed on [chat](https://kataras.rocket.chat/channel/iris). Read HISTORY.md

This commit is contained in:
Gerasimos (Makis) Maropoulos 2017-01-30 12:35:43 +02:00
parent a563b37ba1
commit 2a911a450c
6 changed files with 102 additions and 36 deletions

View File

@ -2,6 +2,25 @@
**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.1.2 -> 6.1.3
- Added a configuration field `iris.Config.DisableBodyConsumptionOnUnmarshal`
```go
// DisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders.
// If setted to true then it
// disables the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`.
//
// By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
// if this field setted to true then a new buffer will be created to read from and the request body.
// The body will not be changed and existing data before the context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
DisableBodyConsumptionOnUnmarshal bool
```
If that option is setted to true then you can read more than one times from the same `context.Request.Body`.
Defaults to false because the majority of developers expecting request body to be empty after unmarshal.
## 6.1.1 -> 6.1.2
Better internalization and localization support, with ability to change the cookie's key and context's keys.

View File

@ -1,6 +1,6 @@
<p align="center">
<a href="https://www.gitbook.com/book/kataras/iris/details">
<img width="500" src="https://raw.githubusercontent.com/kataras/iris/master/logo.jpg"
<img width="500" src="https://raw.githubusercontent.com/kataras/iris/master/logo.jpg"
alt="Logo created by an Iris community member, @OneebMalik">
</a>
@ -20,7 +20,7 @@
<br/>
<a href="https://github.com/kataras/iris/blob/master/HISTORY.md"><img src="https://img.shields.io/badge/%20version%20-%206.1.2%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.1.3%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>
@ -68,7 +68,7 @@ package main
import (
"github.com/kataras/iris"
"github.com/kataras/go-template/html"
)
)
func main(){
@ -83,34 +83,34 @@ func main(){
//
// Use the html standard engine for all files inside "./views" folder with extension ".html"
iris.UseTemplate(html.New()).Directory("./views", ".html")
// http://localhost:6111
// Method: "GET"
// Render ./views/index.html
iris.Get("/", func(ctx *iris.Context){
ctx.Render("index.html", nil)
})
// Group routes, optionally: share middleware, template layout and custom http errors.
// Group routes, optionally: share middleware, template layout and custom http errors.
userAPI := iris.Party("/users", userAPIMiddleware).
Layout("layouts/userLayout.html")
{
// Fire userNotFoundHandler when Not Found
// Fire userNotFoundHandler when Not Found
// inside http://localhost:6111/users/*anything
userAPI.OnError(404, userNotFoundHandler)
// http://localhost:6111/users
// Method: "GET"
userAPI.Get("/", getAllHandler)
// http://localhost:6111/users/42
// Method: "GET"
userAPI.Get("/:id", getByIDHandler)
// http://localhost:6111/users
// Method: "POST"
userAPI.Post("/", saveUserHandler)
}
}
getByIDHandler := func(ctx *iris.Context){
// take the :id from the path, parse to integer
@ -128,7 +128,7 @@ func main(){
// like the iris.Map{"username" : user.Username}.
ctx.JSON(iris.StatusOK, user)
}
// Start the server at 0.0.0.0:6111
iris.Listen(":6111")
}
@ -209,7 +209,7 @@ Besides the fact that we have a [community chat][Chat] for questions or reports
Versioning
------------
Current: **v6.1.2**
Current: **v6.1.3**
v5: https://github.com/kataras/iris/tree/5.0.0

View File

@ -150,6 +150,15 @@ type Configuration struct {
// Default is false
DisableBanner bool
// DisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders.
// If setted to true then it
// disables the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`.
//
// By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
// if this field setted to true then a new buffer will be created to read from and the request body.
// The body will not be changed and existing data before the context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
DisableBodyConsumptionOnUnmarshal bool
// LoggerOut is the destination for output
//
// Default is os.Stdout
@ -349,6 +358,19 @@ var (
}
}
// OptionDisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders.
// If setted to true then it
// disables the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`.
//
// By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
// if this field setted to true then a new buffer will be created to read from and the request body.
// The body will not be changed and existing data before the context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
OptionDisableBodyConsumptionOnUnmarshal = func(val bool) OptionSet {
return func(c *Configuration) {
c.DisableBodyConsumptionOnUnmarshal = val
}
}
// OptionLoggerOut is the destination for output
//
// Default is os.Stdout
@ -461,27 +483,28 @@ var (
// DefaultConfiguration returns the default configuration for an Iris station, fills the main Configuration
func DefaultConfiguration() Configuration {
return Configuration{
VHost: "",
VScheme: "",
ReadTimeout: DefaultReadTimeout,
WriteTimeout: DefaultWriteTimeout,
MaxHeaderBytes: DefaultMaxHeaderBytes,
CheckForUpdates: false,
CheckForUpdatesSync: false,
DisablePathCorrection: DefaultDisablePathCorrection,
EnablePathEscape: DefaultEnablePathEscape,
FireMethodNotAllowed: false,
DisableBanner: false,
LoggerOut: DefaultLoggerOut,
LoggerPreffix: DefaultLoggerPreffix,
DisableTemplateEngines: false,
IsDevelopment: false,
TimeFormat: DefaultTimeFormat,
Charset: DefaultCharset,
Gzip: false,
Sessions: DefaultSessionsConfiguration(),
Websocket: DefaultWebsocketConfiguration(),
Other: options.Options{},
VHost: "",
VScheme: "",
ReadTimeout: DefaultReadTimeout,
WriteTimeout: DefaultWriteTimeout,
MaxHeaderBytes: DefaultMaxHeaderBytes,
CheckForUpdates: false,
CheckForUpdatesSync: false,
DisablePathCorrection: DefaultDisablePathCorrection,
EnablePathEscape: DefaultEnablePathEscape,
FireMethodNotAllowed: false,
DisableBanner: false,
DisableBodyConsumptionOnUnmarshal: false,
LoggerOut: DefaultLoggerOut,
LoggerPreffix: DefaultLoggerPreffix,
DisableTemplateEngines: false,
IsDevelopment: false,
TimeFormat: DefaultTimeFormat,
Charset: DefaultCharset,
Gzip: false,
Sessions: DefaultSessionsConfiguration(),
Websocket: DefaultWebsocketConfiguration(),
Other: options.Options{},
}
}

View File

@ -548,6 +548,12 @@ func (ctx *Context) UnmarshalBody(v interface{}, unmarshaler Unmarshaler) error
return err
}
if ctx.framework.Config.DisableBodyConsumptionOnUnmarshal {
// * remember, Request.Body has no Bytes(), we have to consume them first
// and after re-set them to the body, this is the only solution.
ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(rawData))
}
// check if the v contains its own decode
// in this case the v should be a pointer also,
// but this is up to the user's custom Decode implementation*

View File

@ -251,6 +251,13 @@ func testUnmarshaler(t *testing.T, tb *testBinder,
if write != nil {
write(ctx)
}
if iris.Config.DisableBodyConsumptionOnUnmarshal {
rawData, _ := ioutil.ReadAll(ctx.Request.Body)
if len(rawData) == 0 {
t.Fatalf("Expected data to NOT BE consumed by the previous UnmarshalBody call but we got empty body.")
}
}
}
iris.Post("/bind_req_body", h)
@ -301,7 +308,6 @@ func TestContextBinders(t *testing.T) {
expectedObj.Birth + `</birth><stars>` +
strconv.Itoa(expectedObj.Stars) + `</stars></info>`
// JSON
vXML := &testBinder{&testBinderXMLData{},
iris.UnmarshalerFunc(xml.Unmarshal), false}
testUnmarshaler(
@ -315,6 +321,18 @@ func TestContextBinders(t *testing.T) {
Status(iris.StatusOK).
Body().Equal(expectedAndPassedObjText)
// JSON with DisableBodyConsumptionOnUnmarshal
iris.Config.DisableBodyConsumptionOnUnmarshal = true
testUnmarshaler(
t,
vJSON,
func(ctx *iris.Context) {
ctx.JSON(iris.StatusOK, vJSON.vp)
}).
WithJSON(passed).
Expect().
Status(iris.StatusOK).
JSON().Object().Equal(expectedObject)
}
func TestContextReadForm(t *testing.T) {

View File

@ -81,7 +81,7 @@ const (
// IsLongTermSupport flag is true when the below version number is a long-term-support version
IsLongTermSupport = false
// Version is the current version number of the Iris web framework
Version = "6.1.2"
Version = "6.1.3"
banner = ` _____ _
|_ _| (_)