mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
breaking change: remove static field context.DefaultMaxMemory
and replace it with a better configurable option inside the main configuration, this makes things clear and it allows users to prevent any unwanted client behavior without digging into the framework's internals
Former-commit-id: 875afd32acfab8abdea15ce9be2ad384eb6bad5e
This commit is contained in:
parent
6254ade603
commit
90c825efc8
|
@ -315,6 +315,18 @@ func WithCharset(charset string) Configurator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithPostMaxMemory sets the maximum post data size
|
||||||
|
// that a client can send to the server, this differs
|
||||||
|
// from the overral request body size which can be modified
|
||||||
|
// by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize.
|
||||||
|
//
|
||||||
|
// Defaults to 32MB or 32 << 20 if you prefer.
|
||||||
|
func WithPostMaxMemory(limit int64) Configurator {
|
||||||
|
return func(app *Application) {
|
||||||
|
app.config.PostMaxMemory = limit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithRemoteAddrHeader enables or adds a new or existing request header name
|
// WithRemoteAddrHeader enables or adds a new or existing request header name
|
||||||
// that can be used to validate the client's real IP.
|
// that can be used to validate the client's real IP.
|
||||||
//
|
//
|
||||||
|
@ -463,6 +475,13 @@ type Configuration struct {
|
||||||
// Defaults to "UTF-8".
|
// Defaults to "UTF-8".
|
||||||
Charset string `json:"charset,omitempty" yaml:"Charset" toml:"Charset"`
|
Charset string `json:"charset,omitempty" yaml:"Charset" toml:"Charset"`
|
||||||
|
|
||||||
|
// PostMaxMemory sets the maximum post data size
|
||||||
|
// that a client can send to the server, this differs
|
||||||
|
// from the overral request body size which can be modified
|
||||||
|
// by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize.
|
||||||
|
//
|
||||||
|
// Defaults to 32MB or 32 << 20 if you prefer.
|
||||||
|
PostMaxMemory int64 `json:"postMaxMemory" yaml:"PostMaxMemory" toml:"PostMaxMemory"`
|
||||||
// +----------------------------------------------------+
|
// +----------------------------------------------------+
|
||||||
// | Context's keys for values used on various featuers |
|
// | Context's keys for values used on various featuers |
|
||||||
// +----------------------------------------------------+
|
// +----------------------------------------------------+
|
||||||
|
@ -579,6 +598,16 @@ func (c Configuration) GetCharset() string {
|
||||||
return c.Charset
|
return c.Charset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPostMaxMemory returns the maximum configured post data size
|
||||||
|
// that a client can send to the server, this differs
|
||||||
|
// from the overral request body size which can be modified
|
||||||
|
// by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize.
|
||||||
|
//
|
||||||
|
// Defaults to 32MB or 32 << 20 if you prefer.
|
||||||
|
func (c Configuration) GetPostMaxMemory() int64 {
|
||||||
|
return c.PostMaxMemory
|
||||||
|
}
|
||||||
|
|
||||||
// GetTranslateFunctionContextKey returns the configuration's TranslateFunctionContextKey value,
|
// GetTranslateFunctionContextKey returns the configuration's TranslateFunctionContextKey value,
|
||||||
// used for i18n.
|
// used for i18n.
|
||||||
func (c Configuration) GetTranslateFunctionContextKey() string {
|
func (c Configuration) GetTranslateFunctionContextKey() string {
|
||||||
|
@ -684,6 +713,10 @@ func WithConfiguration(c Configuration) Configurator {
|
||||||
main.Charset = v
|
main.Charset = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v := c.PostMaxMemory; v > 0 {
|
||||||
|
main.PostMaxMemory = v
|
||||||
|
}
|
||||||
|
|
||||||
if v := c.TranslateFunctionContextKey; v != "" {
|
if v := c.TranslateFunctionContextKey; v != "" {
|
||||||
main.TranslateFunctionContextKey = v
|
main.TranslateFunctionContextKey = v
|
||||||
}
|
}
|
||||||
|
@ -733,10 +766,17 @@ func DefaultConfiguration() Configuration {
|
||||||
DisableAutoFireStatusCode: false,
|
DisableAutoFireStatusCode: false,
|
||||||
TimeFormat: "Mon, Jan 02 2006 15:04:05 GMT",
|
TimeFormat: "Mon, Jan 02 2006 15:04:05 GMT",
|
||||||
Charset: "UTF-8",
|
Charset: "UTF-8",
|
||||||
TranslateFunctionContextKey: "iris.translate",
|
|
||||||
TranslateLanguageContextKey: "iris.language",
|
// PostMaxMemory is for post body max memory.
|
||||||
ViewLayoutContextKey: "iris.viewLayout",
|
//
|
||||||
ViewDataContextKey: "iris.viewData",
|
// The request body the size limit
|
||||||
|
// can be set by the middleware `LimitRequestBodySize`
|
||||||
|
// or `context#SetMaxRequestBodySize`.
|
||||||
|
PostMaxMemory: 32 << 20, // 32MB
|
||||||
|
TranslateFunctionContextKey: "iris.translate",
|
||||||
|
TranslateLanguageContextKey: "iris.language",
|
||||||
|
ViewLayoutContextKey: "iris.viewLayout",
|
||||||
|
ViewDataContextKey: "iris.viewData",
|
||||||
RemoteAddrHeaders: map[string]bool{
|
RemoteAddrHeaders: map[string]bool{
|
||||||
"X-Real-Ip": false,
|
"X-Real-Ip": false,
|
||||||
"X-Forwarded-For": false,
|
"X-Forwarded-For": false,
|
||||||
|
|
|
@ -54,6 +54,14 @@ type ConfigurationReadOnly interface {
|
||||||
// used for templates and the rest of the responses.
|
// used for templates and the rest of the responses.
|
||||||
GetCharset() string
|
GetCharset() string
|
||||||
|
|
||||||
|
// GetPostMaxMemory returns the maximum configured post data size
|
||||||
|
// that a client can send to the server, this differs
|
||||||
|
// from the overral request body size which can be modified
|
||||||
|
// by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize.
|
||||||
|
//
|
||||||
|
// Defaults to 32MB or 32 << 20 if you prefer.
|
||||||
|
GetPostMaxMemory() int64
|
||||||
|
|
||||||
// GetTranslateLanguageContextKey returns the configuration's TranslateFunctionContextKey value,
|
// GetTranslateLanguageContextKey returns the configuration's TranslateFunctionContextKey value,
|
||||||
// used for i18n.
|
// used for i18n.
|
||||||
GetTranslateFunctionContextKey() string
|
GetTranslateFunctionContextKey() string
|
||||||
|
|
|
@ -486,7 +486,7 @@ type Context interface {
|
||||||
// FormValues returns the parsed form data, including both the URL
|
// FormValues returns the parsed form data, including both the URL
|
||||||
// field's query parameters and the POST or PUT form data.
|
// field's query parameters and the POST or PUT form data.
|
||||||
//
|
//
|
||||||
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultMaxMemory`.
|
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultPostMaxMemory`.
|
||||||
//
|
//
|
||||||
// NOTE: A check for nil is necessary.
|
// NOTE: A check for nil is necessary.
|
||||||
FormValues() map[string][]string
|
FormValues() map[string][]string
|
||||||
|
@ -540,11 +540,11 @@ type Context interface {
|
||||||
// PostValues returns all the parsed form data from POST, PATCH,
|
// PostValues returns all the parsed form data from POST, PATCH,
|
||||||
// or PUT body parameters based on a "name" as a string slice.
|
// or PUT body parameters based on a "name" as a string slice.
|
||||||
//
|
//
|
||||||
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultMaxMemory`.
|
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultPostMaxMemory`.
|
||||||
PostValues(name string) []string
|
PostValues(name string) []string
|
||||||
// FormFile returns the first uploaded file that received from the client.
|
// FormFile returns the first uploaded file that received from the client.
|
||||||
//
|
//
|
||||||
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultMaxMemory`.
|
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultPostMaxMemory`.
|
||||||
FormFile(key string) (multipart.File, *multipart.FileHeader, error)
|
FormFile(key string) (multipart.File, *multipart.FileHeader, error)
|
||||||
|
|
||||||
// +------------------------------------------------------------+
|
// +------------------------------------------------------------+
|
||||||
|
@ -668,7 +668,6 @@ type Context interface {
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/
|
// Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/
|
||||||
ViewLayout(layoutTmplFile string)
|
ViewLayout(layoutTmplFile string)
|
||||||
|
|
||||||
// ViewData saves one or more key-value pair in order to be passed if and when .View
|
// ViewData saves one or more key-value pair in order to be passed if and when .View
|
||||||
// is being called afterwards, in the same request.
|
// is being called afterwards, in the same request.
|
||||||
// Useful when need to set or/and change template data from previous hanadlers in the chain.
|
// Useful when need to set or/and change template data from previous hanadlers in the chain.
|
||||||
|
@ -688,7 +687,6 @@ type Context interface {
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/
|
// Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/
|
||||||
ViewData(key string, value interface{})
|
ViewData(key string, value interface{})
|
||||||
|
|
||||||
// GetViewData returns the values registered by `context#ViewData`.
|
// GetViewData returns the values registered by `context#ViewData`.
|
||||||
// The return value is `map[string]interface{}`, this means that
|
// The return value is `map[string]interface{}`, this means that
|
||||||
// if a custom struct registered to ViewData then this function
|
// if a custom struct registered to ViewData then this function
|
||||||
|
@ -699,16 +697,20 @@ type Context interface {
|
||||||
// Similarly to `viewData := ctx.Values().Get("iris.viewData")` or
|
// Similarly to `viewData := ctx.Values().Get("iris.viewData")` or
|
||||||
// `viewData := ctx.Values().Get(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey())`.
|
// `viewData := ctx.Values().Get(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey())`.
|
||||||
GetViewData() map[string]interface{}
|
GetViewData() map[string]interface{}
|
||||||
|
// View renders a template based on the registered view engine(s).
|
||||||
// View renders templates based on the adapted view engines.
|
// First argument accepts the filename, relative to the view engine's Directory and Extension,
|
||||||
// First argument accepts the filename, relative to the view engine's Directory,
|
|
||||||
// i.e: if directory is "./templates" and want to render the "./templates/users/index.html"
|
// i.e: if directory is "./templates" and want to render the "./templates/users/index.html"
|
||||||
// then you pass the "users/index.html" as the filename argument.
|
// then you pass the "users/index.html" as the filename argument.
|
||||||
//
|
//
|
||||||
// Look: .ViewData and .ViewLayout too.
|
// The second optional argument can receive a single "view model"
|
||||||
|
// that will be binded to the view template if it's not nil,
|
||||||
|
// otherwise it will check for previous view data stored by the `ViewData`
|
||||||
|
// even if stored at any previous handler(middleware) for the same request.
|
||||||
//
|
//
|
||||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/view/
|
// Look .ViewData` and .ViewLayout too.
|
||||||
View(filename string) error
|
//
|
||||||
|
// Examples: https://github.com/kataras/iris/tree/master/_examples/view
|
||||||
|
View(filename string, optionalViewModel ...interface{}) error
|
||||||
|
|
||||||
// Binary writes out the raw bytes as binary data.
|
// Binary writes out the raw bytes as binary data.
|
||||||
Binary(data []byte) (int, error)
|
Binary(data []byte) (int, error)
|
||||||
|
@ -1600,7 +1602,7 @@ func (ctx *context) FormValue(name string) string {
|
||||||
// FormValues returns the parsed form data, including both the URL
|
// FormValues returns the parsed form data, including both the URL
|
||||||
// field's query parameters and the POST or PUT form data.
|
// field's query parameters and the POST or PUT form data.
|
||||||
//
|
//
|
||||||
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultMaxMemory`.
|
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultPostMaxMemory`.
|
||||||
//
|
//
|
||||||
// NOTE: A check for nil is necessary.
|
// NOTE: A check for nil is necessary.
|
||||||
func (ctx *context) FormValues() map[string][]string {
|
func (ctx *context) FormValues() map[string][]string {
|
||||||
|
@ -1624,7 +1626,7 @@ func (ctx *context) form() (form map[string][]string, found bool) {
|
||||||
// therefore we don't need to call it here, although it doesn't hurt.
|
// therefore we don't need to call it here, although it doesn't hurt.
|
||||||
// After one call to ParseMultipartForm or ParseForm,
|
// After one call to ParseMultipartForm or ParseForm,
|
||||||
// subsequent calls have no effect, are idempotent.
|
// subsequent calls have no effect, are idempotent.
|
||||||
ctx.request.ParseMultipartForm(DefaultMaxMemory)
|
ctx.request.ParseMultipartForm(ctx.Application().ConfigurationReadOnly().GetPostMaxMemory())
|
||||||
|
|
||||||
if form := ctx.request.Form; len(form) > 0 {
|
if form := ctx.request.Form; len(form) > 0 {
|
||||||
return form, true
|
return form, true
|
||||||
|
@ -1733,19 +1735,10 @@ func (ctx *context) PostValueBool(name string) (bool, error) {
|
||||||
return strconv.ParseBool(ctx.PostValue(name))
|
return strconv.ParseBool(ctx.PostValue(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
// DefaultMaxMemory is the default value
|
|
||||||
// for body max memory, defaults to
|
|
||||||
// 32MB.
|
|
||||||
// Can be also changed by the middleware `LimitRequestBodySize`
|
|
||||||
// or `context#SetMaxRequestBodySize`.
|
|
||||||
DefaultMaxMemory = 32 << 20 // 32 MB
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostValues returns all the parsed form data from POST, PATCH,
|
// PostValues returns all the parsed form data from POST, PATCH,
|
||||||
// or PUT body parameters based on a "name" as a string slice.
|
// or PUT body parameters based on a "name" as a string slice.
|
||||||
//
|
//
|
||||||
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultMaxMemory`.
|
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultPostMaxMemory`.
|
||||||
func (ctx *context) PostValues(name string) []string {
|
func (ctx *context) PostValues(name string) []string {
|
||||||
ctx.form()
|
ctx.form()
|
||||||
return ctx.request.PostForm[name]
|
return ctx.request.PostForm[name]
|
||||||
|
@ -1753,11 +1746,41 @@ func (ctx *context) PostValues(name string) []string {
|
||||||
|
|
||||||
// FormFile returns the first uploaded file that received from the client.
|
// FormFile returns the first uploaded file that received from the client.
|
||||||
//
|
//
|
||||||
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultMaxMemory`.
|
// The default form's memory maximum size is 32MB, it can be changed by the `context#DefaultPostMaxMemory`.
|
||||||
func (ctx *context) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
|
func (ctx *context) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
|
||||||
return ctx.request.FormFile(key)
|
return ctx.request.FormFile(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copiable is the interface which should be completed
|
||||||
|
// by files or not that intend to be used inside the `context#CopyFile`.
|
||||||
|
// This interface allows testing file uploads to your http test as well.
|
||||||
|
//
|
||||||
|
// See `CopyFile` for more.
|
||||||
|
type Copiable interface {
|
||||||
|
Open() (io.ReadCloser, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyFile copies a `context#Copiable` "file", that can be acquired by a `context.FormFile`
|
||||||
|
// as well, to the "dest".
|
||||||
|
//
|
||||||
|
// Returns the copied length as int64 and
|
||||||
|
// an error if file is not exist, or new file can't be created or closed at the end.
|
||||||
|
func CopyFile(file Copiable, dest string) (int64, error) {
|
||||||
|
src, err := file.Open()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
out, err := os.Create(dest)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
return io.Copy(out, src)
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect sends a redirect response to the client
|
// Redirect sends a redirect response to the client
|
||||||
// to a specific url or relative path.
|
// to a specific url or relative path.
|
||||||
// accepts 2 parameters string and an optional int
|
// accepts 2 parameters string and an optional int
|
||||||
|
@ -2163,20 +2186,32 @@ func (ctx *context) GetViewData() map[string]interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// View renders templates based on the adapted view engines.
|
// View renders a template based on the registered view engine(s).
|
||||||
// First argument accepts the filename, relative to the view engine's Directory,
|
// First argument accepts the filename, relative to the view engine's Directory and Extension,
|
||||||
// i.e: if directory is "./templates" and want to render the "./templates/users/index.html"
|
// i.e: if directory is "./templates" and want to render the "./templates/users/index.html"
|
||||||
// then you pass the "users/index.html" as the filename argument.
|
// then you pass the "users/index.html" as the filename argument.
|
||||||
//
|
//
|
||||||
// Look: .ViewData and .ViewLayout too.
|
// The second optional argument can receive a single "view model"
|
||||||
|
// that will be binded to the view template if it's not nil,
|
||||||
|
// otherwise it will check for previous view data stored by the `ViewData`
|
||||||
|
// even if stored at any previous handler(middleware) for the same request.
|
||||||
//
|
//
|
||||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/view/
|
// Look .ViewData and .ViewLayout too.
|
||||||
func (ctx *context) View(filename string) error {
|
//
|
||||||
|
// Examples: https://github.com/kataras/iris/tree/master/_examples/view
|
||||||
|
func (ctx *context) View(filename string, optionalViewModel ...interface{}) error {
|
||||||
ctx.ContentType(ContentHTMLHeaderValue)
|
ctx.ContentType(ContentHTMLHeaderValue)
|
||||||
cfg := ctx.Application().ConfigurationReadOnly()
|
cfg := ctx.Application().ConfigurationReadOnly()
|
||||||
|
|
||||||
layout := ctx.values.GetString(cfg.GetViewLayoutContextKey())
|
layout := ctx.values.GetString(cfg.GetViewLayoutContextKey())
|
||||||
bindingData := ctx.values.Get(cfg.GetViewDataContextKey())
|
|
||||||
|
var bindingData interface{}
|
||||||
|
if len(optionalViewModel) > 0 {
|
||||||
|
// a nil can override the existing data or model sent by `ViewData`.
|
||||||
|
bindingData = optionalViewModel[0]
|
||||||
|
} else {
|
||||||
|
bindingData = ctx.values.Get(cfg.GetViewDataContextKey())
|
||||||
|
}
|
||||||
|
|
||||||
err := ctx.Application().View(ctx.writer, filename, layout, bindingData)
|
err := ctx.Application().View(ctx.writer, filename, layout, bindingData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
2
doc.go
2
doc.go
|
@ -1569,7 +1569,7 @@ for this controller, uncomment these if you want:
|
||||||
func (c *ExampleController) Options() {}
|
func (c *ExampleController) Options() {}
|
||||||
func (c *ExampleController) Trace() {}
|
func (c *ExampleController) Trace() {}
|
||||||
*/
|
*/
|
||||||
|
//
|
||||||
/*
|
/*
|
||||||
func (c *ExampleController) All() {}
|
func (c *ExampleController) All() {}
|
||||||
// OR
|
// OR
|
||||||
|
|
6
iris.go
6
iris.go
|
@ -311,6 +311,12 @@ var (
|
||||||
//
|
//
|
||||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
|
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||||
StaticEmbeddedHandler = router.StaticEmbeddedHandler
|
StaticEmbeddedHandler = router.StaticEmbeddedHandler
|
||||||
|
// CopyFile copies a `context#Copiable` "file", that can be acquired by a `context.FormFile`
|
||||||
|
// as well, to the "dest".
|
||||||
|
//
|
||||||
|
// Returns the copied length as int64 and
|
||||||
|
// an error if file is not exist, or new file can't be created or closed at the end.
|
||||||
|
CopyFile = context.CopyFile
|
||||||
// Gzip is a middleware which enables writing
|
// Gzip is a middleware which enables writing
|
||||||
// using gzip compression, if client supports.
|
// using gzip compression, if client supports.
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue
Block a user