1
0
mirror of https://github.com/kataras/iris.git synced 2026-06-09 23:23:35 +00:00

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
+19
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.
+13 -13
View File
@@ -1,6 +1,6 @@
<p align="center"> <p align="center">
<a href="https://www.gitbook.com/book/kataras/iris/details"> <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"> alt="Logo created by an Iris community member, @OneebMalik">
</a> </a>
@@ -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>
@@ -68,7 +68,7 @@ package main
import ( import (
"github.com/kataras/iris" "github.com/kataras/iris"
"github.com/kataras/go-template/html" "github.com/kataras/go-template/html"
) )
func main(){ func main(){
@@ -83,34 +83,34 @@ func main(){
// //
// Use the html standard engine for all files inside "./views" folder with extension ".html" // Use the html standard engine for all files inside "./views" folder with extension ".html"
iris.UseTemplate(html.New()).Directory("./views", ".html") iris.UseTemplate(html.New()).Directory("./views", ".html")
// http://localhost:6111 // http://localhost:6111
// Method: "GET" // Method: "GET"
// Render ./views/index.html // Render ./views/index.html
iris.Get("/", func(ctx *iris.Context){ iris.Get("/", func(ctx *iris.Context){
ctx.Render("index.html", nil) 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). userAPI := iris.Party("/users", userAPIMiddleware).
Layout("layouts/userLayout.html") Layout("layouts/userLayout.html")
{ {
// Fire userNotFoundHandler when Not Found // Fire userNotFoundHandler when Not Found
// inside http://localhost:6111/users/*anything // inside http://localhost:6111/users/*anything
userAPI.OnError(404, userNotFoundHandler) userAPI.OnError(404, userNotFoundHandler)
// http://localhost:6111/users // http://localhost:6111/users
// Method: "GET" // Method: "GET"
userAPI.Get("/", getAllHandler) userAPI.Get("/", getAllHandler)
// http://localhost:6111/users/42 // http://localhost:6111/users/42
// Method: "GET" // Method: "GET"
userAPI.Get("/:id", getByIDHandler) userAPI.Get("/:id", getByIDHandler)
// http://localhost:6111/users // http://localhost:6111/users
// Method: "POST" // Method: "POST"
userAPI.Post("/", saveUserHandler) userAPI.Post("/", saveUserHandler)
} }
getByIDHandler := func(ctx *iris.Context){ getByIDHandler := func(ctx *iris.Context){
// take the :id from the path, parse to integer // take the :id from the path, parse to integer
@@ -128,7 +128,7 @@ func main(){
// like the iris.Map{"username" : user.Username}. // like the iris.Map{"username" : user.Username}.
ctx.JSON(iris.StatusOK, user) ctx.JSON(iris.StatusOK, user)
} }
// Start the server at 0.0.0.0:6111 // Start the server at 0.0.0.0:6111
iris.Listen(":6111") iris.Listen(":6111")
} }
@@ -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
+44 -21
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{},
} }
} }
+6
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*
+19 -1
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) {
+1 -1
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 = ` _____ _
|_ _| (_) |_ _| (_)