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`. **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 ## 6.1.1 -> 6.1.2
Better internalization and localization support, with ability to change the cookie's key and context's keys. Better internalization and localization support, with ability to change the cookie's key and context's keys.

View File

@ -20,7 +20,7 @@
<br/> <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> <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>
@ -209,7 +209,7 @@ Besides the fact that we have a [community chat][Chat] for questions or reports
Versioning Versioning
------------ ------------
Current: **v6.1.2** Current: **v6.1.3**
v5: https://github.com/kataras/iris/tree/5.0.0 v5: https://github.com/kataras/iris/tree/5.0.0

View File

@ -150,6 +150,15 @@ type Configuration struct {
// Default is false // Default is false
DisableBanner bool 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 // LoggerOut is the destination for output
// //
// Default is os.Stdout // 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 // OptionLoggerOut is the destination for output
// //
// Default is os.Stdout // Default is os.Stdout
@ -461,27 +483,28 @@ var (
// DefaultConfiguration returns the default configuration for an Iris station, fills the main Configuration // DefaultConfiguration returns the default configuration for an Iris station, fills the main Configuration
func DefaultConfiguration() Configuration { func DefaultConfiguration() Configuration {
return Configuration{ return Configuration{
VHost: "", VHost: "",
VScheme: "", VScheme: "",
ReadTimeout: DefaultReadTimeout, ReadTimeout: DefaultReadTimeout,
WriteTimeout: DefaultWriteTimeout, WriteTimeout: DefaultWriteTimeout,
MaxHeaderBytes: DefaultMaxHeaderBytes, MaxHeaderBytes: DefaultMaxHeaderBytes,
CheckForUpdates: false, CheckForUpdates: false,
CheckForUpdatesSync: false, CheckForUpdatesSync: false,
DisablePathCorrection: DefaultDisablePathCorrection, DisablePathCorrection: DefaultDisablePathCorrection,
EnablePathEscape: DefaultEnablePathEscape, EnablePathEscape: DefaultEnablePathEscape,
FireMethodNotAllowed: false, FireMethodNotAllowed: false,
DisableBanner: false, DisableBanner: false,
LoggerOut: DefaultLoggerOut, DisableBodyConsumptionOnUnmarshal: false,
LoggerPreffix: DefaultLoggerPreffix, LoggerOut: DefaultLoggerOut,
DisableTemplateEngines: false, LoggerPreffix: DefaultLoggerPreffix,
IsDevelopment: false, DisableTemplateEngines: false,
TimeFormat: DefaultTimeFormat, IsDevelopment: false,
Charset: DefaultCharset, TimeFormat: DefaultTimeFormat,
Gzip: false, Charset: DefaultCharset,
Sessions: DefaultSessionsConfiguration(), Gzip: false,
Websocket: DefaultWebsocketConfiguration(), Sessions: DefaultSessionsConfiguration(),
Other: options.Options{}, Websocket: DefaultWebsocketConfiguration(),
Other: options.Options{},
} }
} }

View File

@ -548,6 +548,12 @@ func (ctx *Context) UnmarshalBody(v interface{}, unmarshaler Unmarshaler) error
return err 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 // check if the v contains its own decode
// in this case the v should be a pointer also, // in this case the v should be a pointer also,
// but this is up to the user's custom Decode implementation* // 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 { if write != nil {
write(ctx) 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) iris.Post("/bind_req_body", h)
@ -301,7 +308,6 @@ func TestContextBinders(t *testing.T) {
expectedObj.Birth + `</birth><stars>` + expectedObj.Birth + `</birth><stars>` +
strconv.Itoa(expectedObj.Stars) + `</stars></info>` strconv.Itoa(expectedObj.Stars) + `</stars></info>`
// JSON
vXML := &testBinder{&testBinderXMLData{}, vXML := &testBinder{&testBinderXMLData{},
iris.UnmarshalerFunc(xml.Unmarshal), false} iris.UnmarshalerFunc(xml.Unmarshal), false}
testUnmarshaler( testUnmarshaler(
@ -315,6 +321,18 @@ func TestContextBinders(t *testing.T) {
Status(iris.StatusOK). Status(iris.StatusOK).
Body().Equal(expectedAndPassedObjText) 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) { 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 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.1.2" Version = "6.1.3"
banner = ` _____ _ banner = ` _____ _
|_ _| (_) |_ _| (_)