From 94f3a048a1519f692c086a706de62e36cb55585c Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Thu, 18 Jun 2020 09:47:07 +0300 Subject: [PATCH] configuration update --- Configuration.md | 496 ++++++--- Content-negotiation.md | 2 +- Installation.md | 4 +- Routing-context-methods.md | 2072 ++++++++++++++++++------------------ Routing-middleware.md | 16 - 5 files changed, 1373 insertions(+), 1217 deletions(-) diff --git a/Configuration.md b/Configuration.md index bab9b9b..bf47e51 100644 --- a/Configuration.md +++ b/Configuration.md @@ -22,6 +22,323 @@ config := iris.WithConfiguration(iris.Configuration { app.Listen(":8080", config) ``` +List of all available settings: + +```go +// Tunnel is the Tunnels field of the TunnelingConfiguration structure. +type Tunnel struct { + // Name is the only one required field, + // it is used to create and close tunnels, e.g. "MyApp". + // If this field is not empty then ngrok tunnels will be created + // when the iris app is up and running. + Name string `json:"name" yaml:"Name" toml:"Name"` + // Addr is basically optionally as it will be set through + // Iris built-in Runners, however, if `iris.Raw` is used + // then this field should be set of form 'hostname:port' + // because framework cannot be aware + // of the address you used to run the server on this custom runner. + Addr string `json:"addr,omitempty" yaml:"Addr" toml:"Addr"` +} + +// TunnelingConfiguration contains configuration +// for the optional tunneling through ngrok feature. +// Note that the ngrok should be already installed at the host machine. +type TunnelingConfiguration struct { + // AuthToken field is optionally and can be used + // to authenticate the ngrok access. + // ngrok authtoken + AuthToken string `json:"authToken,omitempty" yaml:"AuthToken" toml:"AuthToken"` + + // No... + // Config is optionally and can be used + // to load ngrok configuration from file system path. + // + // If you don't specify a location for a configuration file, + // ngrok tries to read one from the default location $HOME/.ngrok2/ngrok.yml. + // The configuration file is optional; no error is emitted if that path does not exist. + // Config string `json:"config,omitempty" yaml:"Config" toml:"Config"` + + // Bin is the system binary path of the ngrok executable file. + // If it's empty then the framework will try to find it through system env variables. + Bin string `json:"bin,omitempty" yaml:"Bin" toml:"Bin"` + + // WebUIAddr is the web interface address of an already-running ngrok instance. + // Iris will try to fetch the default web interface address(http://127.0.0.1:4040) + // to determinate if a ngrok instance is running before try to start it manually. + // However if a custom web interface address is used, + // this field must be set e.g. http://127.0.0.1:5050. + WebInterface string `json:"webInterface,omitempty" yaml:"WebInterface" toml:"WebInterface"` + + // Region is optionally, can be used to set the region which defaults to "us". + // Available values are: + // "us" for United States + // "eu" for Europe + // "ap" for Asia/Pacific + // "au" for Australia + // "sa" for South America + // "jp" forJapan + // "in" for India + Region string `json:"region,omitempty" yaml:"Region" toml:"Region"` + + // Tunnels the collection of the tunnels. + // One tunnel per Iris Host per Application, usually you only need one. + Tunnels []Tunnel `json:"tunnels" yaml:"Tunnels" toml:"Tunnels"` +} + +// Configuration holds the necessary settings for an Iris Application instance. +// All fields are optionally, the default values will work for a common web application. +// +// A Configuration value can be passed through `WithConfiguration` Configurator. +// Usage: +// conf := iris.Configuration{ ... } +// app := iris.New() +// app.Configure(iris.WithConfiguration(conf)) OR +// app.Run/Listen(..., iris.WithConfiguration(conf)). +type Configuration struct { + // LogLevel is the log level the application should use to output messages. + // Logger, by default, is mostly used on Build state but it is also possible + // that debug error messages could be thrown when the app is running, e.g. + // when malformed data structures try to be sent on Client (i.e Context.JSON/JSONP/XML...). + // + // Defaults to "info". Possible values are: + // * "disable" + // * "fatal" + // * "error" + // * "warn" + // * "info" + // * "debug" + LogLevel string `json:"logLevel" yaml:"LogLevel" toml:"LogLevel" env:"LOG_LEVEL"` + + // Tunneling can be optionally set to enable ngrok http(s) tunneling for this Iris app instance. + // See the `WithTunneling` Configurator too. + Tunneling TunnelingConfiguration `json:"tunneling,omitempty" yaml:"Tunneling" toml:"Tunneling"` + + // IgnoreServerErrors will cause to ignore the matched "errors" + // from the main application's `Run` function. + // This is a slice of string, not a slice of error + // users can register these errors using yaml or toml configuration file + // like the rest of the configuration fields. + // + // See `WithoutServerError(...)` function too. + // + // Example: https://github.com/kataras/iris/tree/master/_examples/http-server/listen-addr/omit-server-errors + // + // Defaults to an empty slice. + IgnoreServerErrors []string `json:"ignoreServerErrors,omitempty" yaml:"IgnoreServerErrors" toml:"IgnoreServerErrors"` + + // DisableStartupLog if set to true then it turns off the write banner on server startup. + // + // Defaults to false. + DisableStartupLog bool `json:"disableStartupLog,omitempty" yaml:"DisableStartupLog" toml:"DisableStartupLog"` + // DisableInterruptHandler if set to true then it disables the automatic graceful server shutdown + // when control/cmd+C pressed. + // Turn this to true if you're planning to handle this by your own via a custom host.Task. + // + // Defaults to false. + DisableInterruptHandler bool `json:"disableInterruptHandler,omitempty" yaml:"DisableInterruptHandler" toml:"DisableInterruptHandler"` + + // DisablePathCorrection disables the correcting + // and redirecting or executing directly the handler of + // the requested path to the registered path + // for example, if /home/ path is requested but no handler for this Route found, + // then the Router checks if /home handler exists, if yes, + // (permanent)redirects the client to the correct path /home. + // + // See `DisablePathCorrectionRedirection` to enable direct handler execution instead of redirection. + // + // Defaults to false. + DisablePathCorrection bool `json:"disablePathCorrection,omitempty" yaml:"DisablePathCorrection" toml:"DisablePathCorrection"` + // DisablePathCorrectionRedirection works whenever configuration.DisablePathCorrection is set to false + // and if DisablePathCorrectionRedirection set to true then it will fire the handler of the matching route without + // the trailing slash ("/") instead of send a redirection status. + // + // Defaults to false. + DisablePathCorrectionRedirection bool `json:"disablePathCorrectionRedirection,omitempty" yaml:"DisablePathCorrectionRedirection" toml:"DisablePathCorrectionRedirection"` + // EnablePathIntelligence if set to true, + // the router will redirect HTTP "GET" not found pages to the most closest one path(if any). For example + // you register a route at "/contact" path - + // a client tries to reach it by "/cont", the path will be automatic fixed + // and the client will be redirected to the "/contact" path + // instead of getting a 404 not found response back. + // + // Defaults to false. + EnablePathIntelligence bool `json:"enablePathIntelligence,omitempty" yaml:"EnablePathIntelligence" toml:"EnablePathIntelligence"` + // EnablePathEscape when is true then its escapes the path and the named parameters (if any). + // When do you need to Disable(false) it: + // accepts parameters with slash '/' + // Request: http://localhost:8080/details/Project%2FDelta + // ctx.Param("project") returns the raw named parameter: Project%2FDelta + // which you can escape it manually with net/url: + // projectName, _ := url.QueryUnescape(c.Param("project"). + // + // Defaults to false. + EnablePathEscape bool `json:"enablePathEscape,omitempty" yaml:"EnablePathEscape" toml:"EnablePathEscape"` + // ForceLowercaseRouting if enabled, converts all registered routes paths to lowercase + // and it does lowercase the request path too for matching. + // + // Defaults to false. + ForceLowercaseRouting bool `json:"forceLowercaseRouting,omitempty" yaml:"ForceLowercaseRouting" toml:"ForceLowercaseRouting"` + // FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and + // fires the 405 error instead of 404 + // Defaults to false. + FireMethodNotAllowed bool `json:"fireMethodNotAllowed,omitempty" yaml:"FireMethodNotAllowed" toml:"FireMethodNotAllowed"` + // DisableAutoFireStatusCode if true then it turns off the http error status code + // handler automatic execution on error code from a `Context.StatusCode` call. + // By-default a custom http error handler will be fired when "Context.StatusCode(errorCode)" called. + // + // Defaults to false. + DisableAutoFireStatusCode bool `json:"disableAutoFireStatusCode,omitempty" yaml:"DisableAutoFireStatusCode" toml:"DisableAutoFireStatusCode"` + // ResetOnFireErrorCode if true then any previously response body or headers through + // response recorder or gzip writer will be ignored and the router + // will fire the registered (or default) HTTP error handler instead. + // See `core/router/handler#FireErrorCode` and `Context.EndRequest` for more details. + // + // Read more at: https://github.com/kataras/iris/issues/1531 + // + // Defaults to false. + ResetOnFireErrorCode bool `json:"resetOnFireErrorCode,omitempty" yaml:"ResetOnFireErrorCode" toml:"ResetOnFireErrorCode"` + + // EnableOptimization when this field is true + // then the application tries to optimize for the best performance where is possible. + // + // Defaults to false. + EnableOptimizations bool `json:"enableOptimizations,omitempty" yaml:"EnableOptimizations" toml:"EnableOptimizations"` + // DisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders. + // If set 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 set 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 `json:"disableBodyConsumptionOnUnmarshal,omitempty" yaml:"DisableBodyConsumptionOnUnmarshal" toml:"DisableBodyConsumptionOnUnmarshal"` + // FireEmptyFormError returns if set to tue true then the `context.ReadBody/ReadForm` + // will return an `iris.ErrEmptyForm` on empty request form data. + FireEmptyFormError bool `json:"fireEmptyFormError,omitempty" yaml:"FireEmptyFormError" yaml:"FireEmptyFormError"` + + // TimeFormat time format for any kind of datetime parsing + // Defaults to "Mon, 02 Jan 2006 15:04:05 GMT". + TimeFormat string `json:"timeFormat,omitempty" yaml:"TimeFormat" toml:"TimeFormat"` + + // Charset character encoding for various rendering + // used for templates and the rest of the responses + // Defaults to "utf-8". + 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 values' keys for various features. + // + // LocaleContextKey is used by i18n to get the current request's locale, which contains a translate function too. + // + // Defaults to "iris.locale". + LocaleContextKey string `json:"localeContextKey,omitempty" yaml:"LocaleContextKey" toml:"LocaleContextKey"` + // LanguageContextKey is the context key which a language can be modified by a middleware. + // It has the highest priority over the rest and if it is empty then it is ignored, + // if it set to a static string of "default" or to the default language's code + // then the rest of the language extractors will not be called at all and + // the default language will be set instead. + // + // Use with `Context.SetLanguage("el-GR")`. + // + // See `i18n.ExtractFunc` for a more organised way of the same feature. + // Defaults to "iris.locale.language". + LanguageContextKey string `json:"languageContextKey,omitempty" yaml:"LanguageContextKey" toml:"LanguageContextKey"` + // VersionContextKey is the context key which an API Version can be modified + // via a middleware through `SetVersion` method, e.g. `ctx.SetVersion("1.0, 1.1")`. + // Defaults to "iris.api.version". + VersionContextKey string `json:"versionContextKey" yaml:"VersionContextKey" toml:"VersionContextKey"` + // GetViewLayoutContextKey is the key of the context's user values' key + // which is being used to set the template + // layout from a middleware or the main handler. + // Overrides the parent's or the configuration's. + // + // Defaults to "iris.ViewLayout" + ViewLayoutContextKey string `json:"viewLayoutContextKey,omitempty" yaml:"ViewLayoutContextKey" toml:"ViewLayoutContextKey"` + // GetViewDataContextKey is the key of the context's user values' key + // which is being used to set the template + // binding data from a middleware or the main handler. + // + // Defaults to "iris.viewData" + ViewDataContextKey string `json:"viewDataContextKey,omitempty" yaml:"ViewDataContextKey" toml:"ViewDataContextKey"` + // RemoteAddrHeaders are the allowed request headers names + // that can be valid to parse the client's IP based on. + // By-default no "X-" header is consired safe to be used for retrieving the + // client's IP address, because those headers can manually change by + // the client. But sometimes are useful e.g., when behind a proxy + // you want to enable the "X-Forwarded-For" or when cloudflare + // you want to enable the "CF-Connecting-IP", inneed you + // can allow the `ctx.RemoteAddr()` to use any header + // that the client may sent. + // + // Defaults to an empty map but an example usage is: + // RemoteAddrHeaders { + // "X-Real-Ip": true, + // "X-Forwarded-For": true, + // "CF-Connecting-IP": true, + // } + // + // Look `context.RemoteAddr()` for more. + RemoteAddrHeaders map[string]bool `json:"remoteAddrHeaders,omitempty" yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"` + // RemoteAddrPrivateSubnets defines the private sub-networks. + // They are used to be compared against + // IP Addresses fetched through `RemoteAddrHeaders` or `Context.Request.RemoteAddr`. + // For details please navigate through: https://github.com/kataras/iris/issues/1453 + // Defaults to: + // { + // Start: net.ParseIP("10.0.0.0"), + // End: net.ParseIP("10.255.255.255"), + // }, + // { + // Start: net.ParseIP("100.64.0.0"), + // End: net.ParseIP("100.127.255.255"), + // }, + // { + // Start: net.ParseIP("172.16.0.0"), + // End: net.ParseIP("172.31.255.255"), + // }, + // { + // Start: net.ParseIP("192.0.0.0"), + // End: net.ParseIP("192.0.0.255"), + // }, + // { + // Start: net.ParseIP("192.168.0.0"), + // End: net.ParseIP("192.168.255.255"), + // }, + // { + // Start: net.ParseIP("198.18.0.0"), + // End: net.ParseIP("198.19.255.255"), + // } + // + // Look `Context.RemoteAddr()` for more. + RemoteAddrPrivateSubnets []netutil.IPRange `json:"remoteAddrPrivateSubnets" yaml:"RemoteAddrPrivateSubnets" toml:"RemoteAddrPrivateSubnets"` + // SSLProxyHeaders defines the set of header key values + // that would indicate a valid https Request (look `Context.IsSSL()`). + // Example: `map[string]string{"X-Forwarded-Proto": "https"}`. + // + // Defaults to empty map. + SSLProxyHeaders map[string]string `json:"sslProxyHeaders" yaml:"SSLProxyHeaders" toml:"SSLProxyHeaders"` + // HostProxyHeaders defines the set of headers that may hold a proxied hostname value for the clients. + // Look `Context.Host()` for more. + // Defaults to empty map. + HostProxyHeaders map[string]bool `json:"hostProxyHeaders" yaml:"HostProxyHeaders" toml:"HostProxyHeaders"` + // Other are the custom, dynamic options, can be empty. + // This field used only by you to set any app's options you want. + // + // Defaults to empty map. + Other map[string]interface{} `json:"other,omitempty" yaml:"Other" toml:"Other"` +} +``` + ### Load from [YAML](https://yaml.org/) Using the `iris.YAML("path")`. @@ -88,173 +405,36 @@ configuration options without even a glitch to the documentation. List of functional options: ```go -// WithGlobalConfiguration will load the global yaml configuration file -// from the home directory and it will set/override the whole app's configuration -// to that file's contents. The global configuration file can be modified by user -// and be used by multiple iris instances. -// -// This is useful when we run multiple iris servers that share the same -// configuration, even with custom values at its "Other" field. -// -// Usage: `app.Configure(iris.WithGlobalConfiguration)` or `app.Run([iris.Runner], iris.WithGlobalConfiguration)`. -var WithGlobalConfiguration Configurator +var ( + WithGlobalConfiguration Configurator + WithoutStartupLog, WithoutBanner Configurator + WithoutInterruptHandler Configurator + WithoutPathCorrection Configurator + WithPathIntelligence Configurator + WithoutPathCorrectionRedirection Configurator + WithoutBodyConsumptionOnUnmarshal Configurator + WithEmptyFormError Configurator + WithPathEscape Configurator + WithLowercaseRouting Configurator + WithOptimizations Configurator + WithFireMethodNotAllowed Configurator + WithoutAutoFireStatusCode Configurator + WithResetOnFireErrorCode Configurator + WithTunneling Configurator +) -// WithLogLevel sets the `Configuration.LogLevel` field. func WithLogLevel(level string) Configurator - -// WithoutServerError will cause to ignore the matched "errors" -// from the main application's `Run/Listen` function. -// -// Usage: -// err := app.Listen(":8080", iris.WithoutServerError(iris.ErrServerClosed)) -// will return `nil` if the server's error was `http/iris#ErrServerClosed`. -// -// See `Configuration#IgnoreServerErrors []string` too. -// -// Example: https://github.com/kataras/iris/tree/master/_examples/http-server/listen-addr/omit-server-errors -func WithoutServerError(errors ...error)Configurator - -// WithoutStartupLog turns off the information send, once, to the terminal when the main server is open. -var WithoutStartupLog Configurator - -// WithoutBanner is a conversion for the `WithoutStartupLog` option. -// -// Turns off the information send, once, to the terminal when the main server is open. -var WithoutBanner = WithoutStartupLog - -// WithoutInterruptHandler disables the automatic graceful server shutdown -// when control/cmd+C pressed. -var WithoutInterruptHandler Configurator - -// WithoutPathCorrection disables the PathCorrection setting. -// -// See `Configuration`. -var WithoutPathCorrection Configurator - -// WithPathIntelligence enables the EnablePathIntelligence setting. -// -// See `Configuration`. -var WithPathIntelligence Configurator - -// WithoutPathCorrectionRedirection disables the PathCorrectionRedirection setting. -// -// See `Configuration`. -var WithoutPathCorrectionRedirection Configurator - -// WithoutBodyConsumptionOnUnmarshal disables BodyConsumptionOnUnmarshal setting. -// -// See `Configuration`. -var WithoutBodyConsumptionOnUnmarshal Configurator - -// WithEmptyFormError enables the setting `FireEmptyFormError`. -// -// See `Configuration`. -var WithEmptyFormError Configurator - -// WithoutAutoFireStatusCode disables the AutoFireStatusCode setting. -// -// See `Configuration`. -var WithoutAutoFireStatusCode Configurator - -// WithPathEscape sets the EnablePathEscape setting to true. -// -// See `Configuration`. -var WithPathEscape Configurator - -// WithLowercaseRouting enables for lowercase routing by -// setting the `ForceLowercaseRoutes` to true. -// -// See `Configuration`. -var WithLowercaseRouting Configurator - -// WithOptimizations can force the application to optimize for the best performance where is possible. -// -// See `Configuration`. -var WithOptimizations Configurator - -// WithFireMethodNotAllowed enables the FireMethodNotAllowed setting. -// -// See `Configuration`. -func WithFireMethodNotAllowed Configurator - -// WithTimeFormat sets the TimeFormat setting. -// -// See `Configuration`. +func WithoutServerError(errors ...error) Configurator func WithTimeFormat(timeformat string) Configurator - -// WithCharset sets the Charset setting. -// -// See `Configuration`. 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 or 32*iris.MB if you prefer. func WithPostMaxMemory(limit int64) Configurator - -// WithRemoteAddrHeader enables or adds a new or existing request header name -// that can be used to validate the client's real IP. -// -// By-default no "X-" header is consired safe to be used for retrieving the -// client's IP address, because those headers can manually change by -// the client. But sometimes are useful e.g., when behind a proxy -// you want to enable the "X-Forwarded-For" or when cloudflare -// you want to enable the "CF-Connecting-IP", inneed you -// can allow the `ctx.RemoteAddr()` to use any header -// that the client may sent. -// -// Defaults to an empty map but an example usage is: -// WithRemoteAddrHeader("X-Forwarded-For") -// -// Look `context.RemoteAddr()` for more. -func WithRemoteAddrHeader(headerName string) Configurator - -// WithoutRemoteAddrHeader disables an existing request header name -// that can be used to validate and parse the client's real IP. -// -// -// Keep note that RemoteAddrHeaders is already defaults to an empty map -// so you don't have to call this Configurator if you didn't -// add allowed headers via configuration or via `WithRemoteAddrHeader` before. -// -// Look `context.RemoteAddr()` for more. +func WithRemoteAddrHeader(header ...string) Configurator func WithoutRemoteAddrHeader(headerName string) Configurator - -// WithRemoteAddrPrivateSubnet adds a new private sub-net to be excluded from `context.RemoteAddr`. -// See `WithRemoteAddrHeader` too. func WithRemoteAddrPrivateSubnet(startIP, endIP string) Configurator - -// WithOtherValue adds a value based on a key to the Other setting. -// -// See `Configuration.Other`. +func WithSSLProxyHeader(headerKey, headerValue string) Configurator +func WithHostProxyHeader(headers ...string) Configurator func WithOtherValue(key string, val interface{}) Configurator - -// WithSitemap enables the sitemap generator. -// Use the Route's `SetLastMod`, `SetChangeFreq` and `SetPriority` to modify -// the sitemap's URL child element properties. -// -// It accepts a "startURL" input argument which -// is the prefix for the registered routes that will be included in the sitemap. -// -// If more than 50,000 static routes are registered then sitemaps will be splitted and a sitemap index will be served in -// /sitemap.xml. -// -// If `Application.I18n.Load/LoadAssets` is called then the sitemap will contain translated links for each static route. -// -// If the result does not complete your needs you can take control -// and use the github.com/kataras/sitemap package to generate a customized one instead. -// -// Example: https://github.com/kataras/iris/tree/master/_examples/sitemap. func WithSitemap(startURL string) Configurator - -// WithTunneling is the `iris.Configurator` for the `iris.Configuration.Tunneling` field. -// It's used to enable http tunneling for an Iris Application, per registered host -// -// Alternatively use the `iris.WithConfiguration(iris.Configuration{Tunneling: iris.TunnelingConfiguration{ ...}}}`. -var WithTunneling Configuartor ``` ## Custom values diff --git a/Content-negotiation.md b/Content-negotiation.md index 25d04b8..1951214 100644 --- a/Content-negotiation.md +++ b/Content-negotiation.md @@ -15,7 +15,7 @@ Based on: - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding Implemented on: -- https://github.com/kataras/iris/pull/1316/commits/8ee0de51c593fe0483fbea38117c3c88e065f2ef +- https://github.com/kataras/iris/pull/1316/commits/8ee0de51c593fe0483fbea38117c3c88e065f2ef#diff-15cce7299aae8810bcab9b0bf9a2fdb1 --------- diff --git a/Installation.md b/Installation.md index b8957e5..ccba4d4 100644 --- a/Installation.md +++ b/Installation.md @@ -17,10 +17,10 @@ Or edit your project's `go.mod` file. ```sh module your_project_name -go 1.13 +go 1.14 require ( - github.com/kataras/iris/v12 v12.1.8 + github.com/kataras/iris/v12 v12.2.0 ) ``` diff --git a/Routing-context-methods.md b/Routing-context-methods.md index 6a34801..512a3c3 100644 --- a/Routing-context-methods.md +++ b/Routing-context-methods.md @@ -4,1091 +4,1083 @@ Here is a full list of methods that the `iris.Context` provides. ```go type Context interface { - // BeginRequest is executing once for each request - // it should prepare the (new or acquired from pool) context's fields for the new request. - // Do NOT call it manually. Framework calls it automatically. - // - // Resets - // 1. handlers to nil. - // 2. values to empty. - // 3. the defer function. - // 4. response writer to the http.ResponseWriter. - // 5. request to the *http.Request. - BeginRequest(http.ResponseWriter, *http.Request) - // EndRequest is executing once after a response to the request was sent and this context is useless or released. - // Do NOT call it manually. Framework calls it automatically. - // - // 1. executes the Defer function (if any). - // 2. flushes the response writer's result or fire any error handler. - // 3. releases the response writer. - EndRequest() - // Defer executes a handler on this Context right before the request ends. - // The `StopExecution` does not effect the execution of this defer handler. - // The "h" runs before `FireErrorCode` (when response status code is not successful). - Defer(Handler) + // Defer executes a handler on this Context right before the request ends. + // The `StopExecution` does not effect the execution of this defer handler. + // The "h" runs before `FireErrorCode` (when response status code is not successful). + Defer(Handler) - // ResponseWriter returns an http.ResponseWriter compatible response writer, as expected. - ResponseWriter() ResponseWriter - // ResetResponseWriter should change or upgrade the Context's ResponseWriter. - ResetResponseWriter(ResponseWriter) + // ResponseWriter returns an http.ResponseWriter compatible response writer, as expected. + ResponseWriter() ResponseWriter + // ResetResponseWriter should change or upgrade the Context's ResponseWriter. + ResetResponseWriter(ResponseWriter) - // Request returns the original *http.Request, as expected. - Request() *http.Request - // ResetRequest sets the Context's Request, - // It is useful to store the new request created by a std *http.Request#WithContext() into Iris' Context. - // Use `ResetRequest` when for some reason you want to make a full - // override of the *http.Request. - // Note that: when you just want to change one of each fields you can use the Request() which returns a pointer to Request, - // so the changes will have affect without a full override. - // Usage: you use a native http handler which uses the standard "context" package - // to get values instead of the Iris' Context#Values(): - // r := ctx.Request() - // stdCtx := context.WithValue(r.Context(), key, val) - // ctx.ResetRequest(r.WithContext(stdCtx)). - ResetRequest(r *http.Request) + // Request returns the original *http.Request, as expected. + Request() *http.Request + // ResetRequest sets the Context's Request, + // It is useful to store the new request created by a std *http.Request#WithContext() into Iris' Context. + // Use `ResetRequest` when for some reason you want to make a full + // override of the *http.Request. + // Note that: when you just want to change one of each fields you can use the Request() which returns a pointer to Request, + // so the changes will have affect without a full override. + // Usage: you use a native http handler which uses the standard "context" package + // to get values instead of the Iris' Context#Values(): + // r := ctx.Request() + // stdCtx := context.WithValue(r.Context(), key, val) + // ctx.ResetRequest(r.WithContext(stdCtx)). + ResetRequest(r *http.Request) - // SetCurrentRoutes sets the route internally, - // See `GetCurrentRoute()` method too. - // It's being initialized by the Router. - // See `Exec` or `SetHandlers/AddHandler` methods to simulate a request. - SetCurrentRoute(route RouteReadOnly) - // GetCurrentRoute returns the current "read-only" route that - // was registered to this request's path. - GetCurrentRoute() RouteReadOnly + // SetCurrentRoutes sets the route internally, + // See `GetCurrentRoute()` method too. + // It's being initialized by the Router. + // See `Exec` or `SetHandlers/AddHandler` methods to simulate a request. + SetCurrentRoute(route RouteReadOnly) + // GetCurrentRoute returns the current "read-only" route that + // was registered to this request's path. + GetCurrentRoute() RouteReadOnly - // Do calls the SetHandlers(handlers) - // and executes the first handler, - // handlers should not be empty. - // - // It's used by the router, developers may use that - // to replace and execute handlers immediately. - Do(Handlers) + // Do calls the SetHandlers(handlers) + // and executes the first handler, + // handlers should not be empty. + // + // It's used by the router, developers may use that + // to replace and execute handlers immediately. + Do(Handlers) - // AddHandler can add handler(s) - // to the current request in serve-time, - // these handlers are not persistenced to the router. - // - // Router is calling this function to add the route's handler. - // If AddHandler called then the handlers will be inserted - // to the end of the already-defined route's handler. - AddHandler(...Handler) - // SetHandlers replaces all handlers with the new. - SetHandlers(Handlers) - // Handlers keeps tracking of the current handlers. - Handlers() Handlers + // AddHandler can add handler(s) + // to the current request in serve-time, + // these handlers are not persistenced to the router. + // + // Router is calling this function to add the route's handler. + // If AddHandler called then the handlers will be inserted + // to the end of the already-defined route's handler. + AddHandler(...Handler) + // SetHandlers replaces all handlers with the new. + SetHandlers(Handlers) + // Handlers keeps tracking of the current handlers. + Handlers() Handlers + // HandlerIndex sets the current index of the + // current context's handlers chain. + // If n < 0 or the current handlers length is 0 then it just returns the + // current handler index without change the current index. + // + // Look Handlers(), Next() and StopExecution() too. + HandlerIndex(n int) (currentIndex int) + // Proceed is an alternative way to check if a particular handler + // has been executed and called the `ctx.Next` function inside it. + // This is useful only when you run a handler inside + // another handler. It justs checks for before index and the after index. + // + // A usecase example is when you want to execute a middleware + // inside controller's `BeginRequest` that calls the `ctx.Next` inside it. + // The Controller looks the whole flow (BeginRequest, method handler, EndRequest) + // as one handler, so `ctx.Next` will not be reflected to the method handler + // if called from the `BeginRequest`. + // + // Although `BeginRequest` should NOT be used to call other handlers, + // the `BeginRequest` has been introduced to be able to set + // common data to all method handlers before their execution. + // Controllers can accept middleware(s) from the MVC's Application's Router as normally. + // + // That said let's see an example of `ctx.Proceed`: + // + // var authMiddleware = basicauth.New(basicauth.Config{ + // Users: map[string]string{ + // "admin": "password", + // }, + // }) + // + // func (c *UsersController) BeginRequest(ctx iris.Context) { + // if !ctx.Proceed(authMiddleware) { + // ctx.StopExecution() + // } + // } + // This Get() will be executed in the same handler as `BeginRequest`, + // internally controller checks for `ctx.StopExecution`. + // So it will not be fired if BeginRequest called the `StopExecution`. + // func(c *UsersController) Get() []models.User { + // return c.Service.GetAll() + //} + // Alternative way is `!ctx.IsStopped()` if middleware make use of the `ctx.StopExecution()` on failure. + Proceed(Handler) bool + // HandlerName returns the current handler's name, helpful for debugging. + HandlerName() string + // HandlerFileLine returns the current running handler's function source file and line information. + // Useful mostly when debugging. + HandlerFileLine() (file string, line int) + // RouteName returns the route name that this handler is running on. + // Note that it will return empty on not found handlers. + RouteName() string + // Next calls all the next handler from the handlers chain, + // it should be used inside a middleware. + // + // Note: Custom context should override this method in order to be able to pass its own context.Context implementation. + Next() + // NextOr checks if chain has a next handler, if so then it executes it + // otherwise it sets a new chain assigned to this Context based on the given handler(s) + // and executes its first handler. + // + // Returns true if next handler exists and executed, otherwise false. + // + // Note that if no next handler found and handlers are missing then + // it sends a Status Not Found (404) to the client and it stops the execution. + NextOr(handlers ...Handler) bool + // NextOrNotFound checks if chain has a next handler, if so then it executes it + // otherwise it sends a Status Not Found (404) to the client and stops the execution. + // + // Returns true if next handler exists and executed, otherwise false. + NextOrNotFound() bool + // NextHandler returns (it doesn't execute) the next handler from the handlers chain. + // + // Use .Skip() to skip this handler if needed to execute the next of this returning handler. + NextHandler() Handler + // Skip skips/ignores the next handler from the handlers chain, + // it should be used inside a middleware. + Skip() + // StopExecution stops the handlers chain of this request. + // Meaning that any following `Next` calls are ignored, + // as a result the next handlers in the chain will not be fire. + StopExecution() + // IsStopped reports whether the current position of the context's handlers is -1, + // means that the StopExecution() was called at least once. + IsStopped() bool + // StopWithStatus stops the handlers chain and writes the "statusCode". + // + // If the status code is a failure one then + // it will also fire the specified error code handler. + StopWithStatus(statusCode int) + // StopWithText stops the handlers chain and writes the "statusCode" + // among with a message "plainText". + // + // If the status code is a failure one then + // it will also fire the specified error code handler. + StopWithText(statusCode int, plainText string) + // StopWithError stops the handlers chain and writes the "statusCode" + // among with the error "err". + // + // If the status code is a failure one then + // it will also fire the specified error code handler. + StopWithError(statusCode int, err error) + // StopWithJSON stops the handlers chain, writes the status code + // and sends a JSON response. + // + // If the status code is a failure one then + // it will also fire the specified error code handler. + StopWithJSON(statusCode int, jsonObject interface{}) + // StopWithProblem stops the handlers chain, writes the status code + // and sends an application/problem+json response. + // See `iris.NewProblem` to build a "problem" value correctly. + // + // If the status code is a failure one then + // it will also fire the specified error code handler. + StopWithProblem(statusCode int, problem Problem) - // HandlerIndex sets the current index of the - // current context's handlers chain. - // If n < 0 or the current handlers length is 0 then it just returns the - // current handler index without change the current index. - // - // Look Handlers(), Next() and StopExecution() too. - HandlerIndex(n int) (currentIndex int) - // Proceed is an alternative way to check if a particular handler - // has been executed and called the `ctx.Next` function inside it. - // This is useful only when you run a handler inside - // another handler. It justs checks for before index and the after index. - // - // A usecase example is when you want to execute a middleware - // inside controller's `BeginRequest` that calls the `ctx.Next` inside it. - // The Controller looks the whole flow (BeginRequest, method handler, EndRequest) - // as one handler, so `ctx.Next` will not be reflected to the method handler - // if called from the `BeginRequest`. - // - // Although `BeginRequest` should NOT be used to call other handlers, - // the `BeginRequest` has been introduced to be able to set - // common data to all method handlers before their execution. - // Controllers can accept middleware(s) from the MVC's Application's Router as normally. - // - // That said let's see an example of `ctx.Proceed`: - // - // var authMiddleware = basicauth.New(basicauth.Config{ - // Users: map[string]string{ - // "admin": "password", - // }, - // }) - // - // func (c *UsersController) BeginRequest(ctx iris.Context) { - // if !ctx.Proceed(authMiddleware) { - // ctx.StopExecution() - // } - // } - // This Get() will be executed in the same handler as `BeginRequest`, - // internally controller checks for `ctx.StopExecution`. - // So it will not be fired if BeginRequest called the `StopExecution`. - // func(c *UsersController) Get() []models.User { - // return c.Service.GetAll() - //} - // Alternative way is `!ctx.IsStopped()` if middleware make use of the `ctx.StopExecution()` on failure. - Proceed(Handler) bool - // HandlerName returns the current handler's name, helpful for debugging. - HandlerName() string - // HandlerFileLine returns the current running handler's function source file and line information. - // Useful mostly when debugging. - HandlerFileLine() (file string, line int) - // RouteName returns the route name that this handler is running on. - // Note that it will return empty on not found handlers. - RouteName() string - // Next calls all the next handler from the handlers chain, - // it should be used inside a middleware. - // - // Note: Custom context should override this method in order to be able to pass its own context.Context implementation. - Next() - // NextOr checks if chain has a next handler, if so then it executes it - // otherwise it sets a new chain assigned to this Context based on the given handler(s) - // and executes its first handler. - // - // Returns true if next handler exists and executed, otherwise false. - // - // Note that if no next handler found and handlers are missing then - // it sends a Status Not Found (404) to the client and it stops the execution. - NextOr(handlers ...Handler) bool - // NextOrNotFound checks if chain has a next handler, if so then it executes it - // otherwise it sends a Status Not Found (404) to the client and stops the execution. - // - // Returns true if next handler exists and executed, otherwise false. - NextOrNotFound() bool - // NextHandler returns (it doesn't execute) the next handler from the handlers chain. - // - // Use .Skip() to skip this handler if needed to execute the next of this returning handler. - NextHandler() Handler - // Skip skips/ignores the next handler from the handlers chain, - // it should be used inside a middleware. - Skip() - // StopExecution stops the handlers chain of this request. - // Meaning that any following `Next` calls are ignored, - // as a result the next handlers in the chain will not be fire. - StopExecution() - // IsStopped reports whether the current position of the context's handlers is -1, - // means that the StopExecution() was called at least once. - IsStopped() bool - // StopWithStatus stops the handlers chain and writes the "statusCode". - // - // If the status code is a failure one then - // it will also fire the specified error code handler. - StopWithStatus(statusCode int) - // StopWithText stops the handlers chain and writes the "statusCode" - // among with a message "plainText". - // - // If the status code is a failure one then - // it will also fire the specified error code handler. - StopWithText(statusCode int, plainText string) - // StopWithError stops the handlers chain and writes the "statusCode" - // among with the error "err". - // - // If the status code is a failure one then - // it will also fire the specified error code handler. - StopWithError(statusCode int, err error) - // StopWithJSON stops the handlers chain, writes the status code - // and sends a JSON response. - // - // If the status code is a failure one then - // it will also fire the specified error code handler. - StopWithJSON(statusCode int, jsonObject interface{}) - // StopWithProblem stops the handlers chain, writes the status code - // and sends an application/problem+json response. - // See `iris.NewProblem` to build a "problem" value correctly. - // - // If the status code is a failure one then - // it will also fire the specified error code handler. - StopWithProblem(statusCode int, problem Problem) + // OnConnectionClose registers the "cb" function which will fire (on its own goroutine, no need to be registered goroutine by the end-dev) + // when the underlying connection has gone away. + // + // This mechanism can be used to cancel long operations on the server + // if the client has disconnected before the response is ready. + // + // It depends on the `http#CloseNotify`. + // CloseNotify may wait to notify until Request.Body has been + // fully read. + // + // After the main Handler has returned, there is no guarantee + // that the channel receives a value. + // + // Finally, it reports whether the protocol supports pipelines (HTTP/1.1 with pipelines disabled is not supported). + // The "cb" will not fire for sure if the output value is false. + // + // Note that you can register only one callback for the entire request handler chain/per route. + // + // Look the `ResponseWriter#CloseNotifier` for more. + OnConnectionClose(fnGoroutine func()) bool + // OnClose registers the callback function "cb" to the underline connection closing event using the `Context#OnConnectionClose` + // and also in the end of the request handler using the `ResponseWriter#SetBeforeFlush`. + // Note that you can register only one callback for the entire request handler chain/per route. + // Note that the "cb" will only be called once. + // + // Look the `Context#OnConnectionClose` and `ResponseWriter#SetBeforeFlush` for more. + OnClose(cb func()) - // OnConnectionClose registers the "cb" function which will fire (on its own goroutine, no need to be registered goroutine by the end-dev) - // when the underlying connection has gone away. - // - // This mechanism can be used to cancel long operations on the server - // if the client has disconnected before the response is ready. - // - // It depends on the `http#CloseNotify`. - // CloseNotify may wait to notify until Request.Body has been - // fully read. - // - // After the main Handler has returned, there is no guarantee - // that the channel receives a value. - // - // Finally, it reports whether the protocol supports pipelines (HTTP/1.1 with pipelines disabled is not supported). - // The "cb" will not fire for sure if the output value is false. - // - // Note that you can register only one callback for the entire request handler chain/per route. - // - // Look the `ResponseWriter#CloseNotifier` for more. - OnConnectionClose(fnGoroutine func()) bool - // OnClose registers the callback function "cb" to the underline connection closing event using the `Context#OnConnectionClose` - // and also in the end of the request handler using the `ResponseWriter#SetBeforeFlush`. - // Note that you can register only one callback for the entire request handler chain/per route. - // Note that the "cb" will only be called once. - // - // Look the `Context#OnConnectionClose` and `ResponseWriter#SetBeforeFlush` for more. - OnClose(cb func()) + // +------------------------------------------------------------+ + // | Current "user/request" storage | + // | and share information between the handlers - Values(). | + // | Save and get named path parameters - Params() | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Current "user/request" storage | - // | and share information between the handlers - Values(). | - // | Save and get named path parameters - Params() | - // +------------------------------------------------------------+ + // Params returns the current url's named parameters key-value storage. + // Named path parameters are being saved here. + // This storage, as the whole Context, is per-request lifetime. + Params() *RequestParams - // Params returns the current url's named parameters key-value storage. - // Named path parameters are being saved here. - // This storage, as the whole Context, is per-request lifetime. - Params() *RequestParams + // Values returns the current "user" storage. + // Named path parameters and any optional data can be saved here. + // This storage, as the whole Context, is per-request lifetime. + // + // You can use this function to Set and Get local values + // that can be used to share information between handlers and middleware. + Values() *memstore.Store - // Values returns the current "user" storage. - // Named path parameters and any optional data can be saved here. - // This storage, as the whole Context, is per-request lifetime. - // - // You can use this function to Set and Get local values - // that can be used to share information between handlers and middleware. - Values() *memstore.Store + // +------------------------------------------------------------+ + // | Path, Host, Subdomain, IP, Headers, Localization etc... | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Path, Host, Subdomain, IP, Headers, Localization etc... | - // +------------------------------------------------------------+ + // Method returns the request.Method, the client's http method to the server. + Method() string + // Path returns the full request path, + // escaped if EnablePathEscape config field is true. + Path() string + // RequestPath returns the full request path, + // based on the 'escape'. + RequestPath(escape bool) string + // Host returns the host part of the current url. + // This method makes use of the `Configuration.HostProxyHeaders` field too. + Host() string + // Subdomain returns the subdomain of this request, if any. + // Note that this is a fast method which does not cover all cases. + Subdomain() (subdomain string) + // FindClosest returns a list of "n" paths close to + // this request based on subdomain and request path. + // + // Order may change. + // Example: https://github.com/kataras/iris/tree/master/_examples/routing/intelligence/manual + FindClosest(n int) []string + // IsWWW returns true if the current subdomain (if any) is www. + IsWWW() bool + // FullRqeuestURI returns the full URI, + // including the scheme, the host and the relative requested path/resource. + FullRequestURI() string + // RemoteAddr tries to parse and return the real client's request IP. + // + // Based on allowed headers names that can be modified from Configuration.RemoteAddrHeaders. + // + // If parse based on these headers fail then it will return the Request's `RemoteAddr` field + // which is filled by the server before the HTTP handler. + // + // Look `Configuration.RemoteAddrHeaders`, + // `Configuration.WithRemoteAddrHeader(...)`, + // `Configuration.WithoutRemoteAddrHeader(...)`and + // `Configuration.RemoteAddrPrivateSubnets` for more. + RemoteAddr() string + // GetHeader returns the request header's value based on its name. + GetHeader(name string) string + // GetDomain resolves and returns the server's domain. + GetDomain() string + // IsAjax returns true if this request is an 'ajax request'( XMLHttpRequest) + // + // There is no a 100% way of knowing that a request was made via Ajax. + // You should never trust data coming from the client, they can be easily overcome by spoofing. + // + // Note that "X-Requested-With" Header can be modified by any client(because of "X-"), + // so don't rely on IsAjax for really serious stuff, + // try to find another way of detecting the type(i.e, content type), + // there are many blogs that describe these problems and provide different kind of solutions, + // it's always depending on the application you're building, + // this is the reason why this `IsAjax`` is simple enough for general purpose use. + // + // Read more at: https://developer.mozilla.org/en-US/docs/AJAX + // and https://xhr.spec.whatwg.org/ + IsAjax() bool + // IsMobile checks if client is using a mobile device(phone or tablet) to communicate with this server. + // If the return value is true that means that the http client using a mobile + // device to communicate with the server, otherwise false. + // + // Keep note that this checks the "User-Agent" request header. + IsMobile() bool + // IsScript reports whether a client is a script. + IsScript() bool + // IsSSL reports whether the client is running under HTTPS SSL. + // + // See `IsHTTP2` too. + IsSSL() bool + // IsHTTP2 reports whether the protocol version for incoming request was HTTP/2. + // The client code always uses either HTTP/1.1 or HTTP/2. + // + // See `IsSSL` too. + IsHTTP2() bool + // IsGRPC reports whether the request came from a gRPC client. + IsGRPC() bool + // GetReferrer extracts and returns the information from the "Referer" (or "Referrer") header + // and url query parameter as specified in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy. + GetReferrer() Referrer + // SetLanguage force-sets the language for i18n, can be used inside a middleare. + // It has the highest priority over the rest and if it is empty then it is ignored, + // if it set to a static string of "default" or to the default language's code + // then the rest of the language extractors will not be called at all and + // the default language will be set instead. + // + // See `app.I18n.ExtractFunc` for a more organised way of the same feature. + SetLanguage(langCode string) + // GetLocale returns the current request's `Locale` found by i18n middleware. + // See `Tr` too. + GetLocale() Locale + // Tr returns a i18n localized message based on format with optional arguments. + // See `GetLocale` too. + // Example: https://github.com/kataras/iris/tree/master/_examples/i18n + Tr(format string, args ...interface{}) string + // SetVersion force-sets the API Version integrated with the "iris/versioning" subpackage. + // It can be used inside a middleare. + SetVersion(constraint string) + // +------------------------------------------------------------+ + // | Headers helpers | + // +------------------------------------------------------------+ - // Method returns the request.Method, the client's http method to the server. - Method() string - // Path returns the full request path, - // escaped if EnablePathEscape config field is true. - Path() string - // RequestPath returns the full request path, - // based on the 'escape'. - RequestPath(escape bool) string - // Host returns the host part of the current url. - Host() string - // Subdomain returns the subdomain of this request, if any. - // Note that this is a fast method which does not cover all cases. - Subdomain() (subdomain string) - // FindClosest returns a list of "n" paths close to - // this request based on subdomain and request path. - // - // Order may change. - // Example: https://github.com/kataras/iris/tree/master/_examples/routing/intelligence/manual - FindClosest(n int) []string - // IsWWW returns true if the current subdomain (if any) is www. - IsWWW() bool - // FullRqeuestURI returns the full URI, - // including the scheme, the host and the relative requested path/resource. - FullRequestURI() string - // RemoteAddr tries to parse and return the real client's request IP. - // - // Based on allowed headers names that can be modified from Configuration.RemoteAddrHeaders. - // - // If parse based on these headers fail then it will return the Request's `RemoteAddr` field - // which is filled by the server before the HTTP handler. - // - // Look `Configuration.RemoteAddrHeaders`, - // `Configuration.WithRemoteAddrHeader(...)`, - // `Configuration.WithoutRemoteAddrHeader(...)`and - // `Configuration.RemoteAddrPrivateSubnets` for more. - RemoteAddr() string - // GetHeader returns the request header's value based on its name. - GetHeader(name string) string - // GetDomain resolves and returns the server's domain. - GetDomain() string - // IsAjax returns true if this request is an 'ajax request'( XMLHttpRequest) - // - // There is no a 100% way of knowing that a request was made via Ajax. - // You should never trust data coming from the client, they can be easily overcome by spoofing. - // - // Note that "X-Requested-With" Header can be modified by any client(because of "X-"), - // so don't rely on IsAjax for really serious stuff, - // try to find another way of detecting the type(i.e, content type), - // there are many blogs that describe these problems and provide different kind of solutions, - // it's always depending on the application you're building, - // this is the reason why this `IsAjax`` is simple enough for general purpose use. - // - // Read more at: https://developer.mozilla.org/en-US/docs/AJAX - // and https://xhr.spec.whatwg.org/ - IsAjax() bool - // IsMobile checks if client is using a mobile device(phone or tablet) to communicate with this server. - // If the return value is true that means that the http client using a mobile - // device to communicate with the server, otherwise false. - // - // Keep note that this checks the "User-Agent" request header. - IsMobile() bool - // IsScript reports whether a client is a script. - IsScript() bool - // IsHTTP2 reports whether the protocol version for incoming request was HTTP/2. - // The client code always uses either HTTP/1.1 or HTTP/2. - IsHTTP2() bool - // IsGRPC reports whether the request came from a gRPC client. - IsGRPC() bool - // GetReferrer extracts and returns the information from the "Referrer" header as specified - // in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - // or by the URL query parameter "referrer". - GetReferrer() Referrer - // SetLanguage force-sets the language for i18n, can be used inside a middleare. - // It has the highest priority over the rest and if it is empty then it is ignored, - // if it set to a static string of "default" or to the default language's code - // then the rest of the language extractors will not be called at all and - // the default language will be set instead. - // - // See `app.I18n.ExtractFunc` for a more organised way of the same feature. - SetLanguage(langCode string) - // GetLocale returns the current request's `Locale` found by i18n middleware. - // See `Tr` too. - GetLocale() Locale - // Tr returns a i18n localized message based on format with optional arguments. - // See `GetLocale` too. - // Example: https://github.com/kataras/iris/tree/master/_examples/i18n - Tr(format string, args ...interface{}) string - // SetVersion force-sets the API Version integrated with the "iris/versioning" subpackage. - // It can be used inside a middleare. - SetVersion(constraint string) - // +------------------------------------------------------------+ - // | Headers helpers | - // +------------------------------------------------------------+ + // Header adds a header to the response writer. + Header(name string, value string) - // Header adds a header to the response writer. - Header(name string, value string) + // ContentType sets the response writer's header key "Content-Type" to the 'cType'. + ContentType(cType string) + // GetContentType returns the response writer's header value of "Content-Type" + // which may, set before with the 'ContentType'. + GetContentType() string + // GetContentType returns the request's header value of "Content-Type". + GetContentTypeRequested() string - // ContentType sets the response writer's header key "Content-Type" to the 'cType'. - ContentType(cType string) - // GetContentType returns the response writer's header value of "Content-Type" - // which may, set before with the 'ContentType'. - GetContentType() string - // GetContentType returns the request's header value of "Content-Type". - GetContentTypeRequested() string + // GetContentLength returns the request's header value of "Content-Length". + // Returns 0 if header was unable to be found or its value was not a valid number. + GetContentLength() int64 - // GetContentLength returns the request's header value of "Content-Length". - // Returns 0 if header was unable to be found or its value was not a valid number. - GetContentLength() int64 + // StatusCode sets the status code header to the response. + // Look .`GetStatusCode` too. + StatusCode(statusCode int) + // GetStatusCode returns the current status code of the response. + // Look `StatusCode` too. + GetStatusCode() int - // StatusCode sets the status code header to the response. - // Look .`GetStatusCode` too. - StatusCode(statusCode int) - // GetStatusCode returns the current status code of the response. - // Look `StatusCode` too. - GetStatusCode() int + // AbsoluteURI parses the "s" and returns its absolute URI form. + AbsoluteURI(s string) string + // Redirect sends a redirect response to the client + // to a specific url or relative path. + // accepts 2 parameters string and an optional int + // first parameter is the url to redirect + // second parameter is the http status should send, + // default is 302 (StatusFound), + // you can set it to 301 (Permant redirect) + // or 303 (StatusSeeOther) if POST method, + // or StatusTemporaryRedirect(307) if that's nessecery. + Redirect(urlToRedirect string, statusHeader ...int) + // +------------------------------------------------------------+ + // | Various Request and Post Data | + // +------------------------------------------------------------+ - // AbsoluteURI parses the "s" and returns its absolute URI form. - AbsoluteURI(s string) string - // Redirect sends a redirect response to the client - // to a specific url or relative path. - // accepts 2 parameters string and an optional int - // first parameter is the url to redirect - // second parameter is the http status should send, - // default is 302 (StatusFound), - // you can set it to 301 (Permant redirect) - // or 303 (StatusSeeOther) if POST method, - // or StatusTemporaryRedirect(307) if that's nessecery. - Redirect(urlToRedirect string, statusHeader ...int) - // +------------------------------------------------------------+ - // | Various Request and Post Data | - // +------------------------------------------------------------+ + // URLParam returns true if the url parameter exists, otherwise false. + URLParamExists(name string) bool + // URLParamDefault returns the get parameter from a request, + // if not found then "def" is returned. + URLParamDefault(name string, def string) string + // URLParam returns the get parameter from a request, if any. + URLParam(name string) string + // URLParamTrim returns the url query parameter with trailing white spaces removed from a request. + URLParamTrim(name string) string + // URLParamEscape returns the escaped url query parameter from a request. + URLParamEscape(name string) string + // URLParamInt returns the url query parameter as int value from a request, + // returns -1 and an error if parse failed. + URLParamInt(name string) (int, error) + // URLParamIntDefault returns the url query parameter as int value from a request, + // if not found or parse failed then "def" is returned. + URLParamIntDefault(name string, def int) int + // URLParamInt32Default returns the url query parameter as int32 value from a request, + // if not found or parse failed then "def" is returned. + URLParamInt32Default(name string, def int32) int32 + // URLParamInt64 returns the url query parameter as int64 value from a request, + // returns -1 and an error if parse failed. + URLParamInt64(name string) (int64, error) + // URLParamInt64Default returns the url query parameter as int64 value from a request, + // if not found or parse failed then "def" is returned. + URLParamInt64Default(name string, def int64) int64 + // URLParamFloat64 returns the url query parameter as float64 value from a request, + // returns -1 and an error if parse failed. + URLParamFloat64(name string) (float64, error) + // URLParamFloat64Default returns the url query parameter as float64 value from a request, + // if not found or parse failed then "def" is returned. + URLParamFloat64Default(name string, def float64) float64 + // URLParamBool returns the url query parameter as boolean value from a request, + // returns an error if parse failed or not found. + URLParamBool(name string) (bool, error) + // URLParams returns a map of GET query parameters separated by comma if more than one + // it returns an empty map if nothing found. + URLParams() map[string]string - // URLParam returns true if the url parameter exists, otherwise false. - URLParamExists(name string) bool - // URLParamDefault returns the get parameter from a request, - // if not found then "def" is returned. - URLParamDefault(name string, def string) string - // URLParam returns the get parameter from a request, if any. - URLParam(name string) string - // URLParamTrim returns the url query parameter with trailing white spaces removed from a request. - URLParamTrim(name string) string - // URLParamEscape returns the escaped url query parameter from a request. - URLParamEscape(name string) string - // URLParamInt returns the url query parameter as int value from a request, - // returns -1 and an error if parse failed. - URLParamInt(name string) (int, error) - // URLParamIntDefault returns the url query parameter as int value from a request, - // if not found or parse failed then "def" is returned. - URLParamIntDefault(name string, def int) int - // URLParamInt32Default returns the url query parameter as int32 value from a request, - // if not found or parse failed then "def" is returned. - URLParamInt32Default(name string, def int32) int32 - // URLParamInt64 returns the url query parameter as int64 value from a request, - // returns -1 and an error if parse failed. - URLParamInt64(name string) (int64, error) - // URLParamInt64Default returns the url query parameter as int64 value from a request, - // if not found or parse failed then "def" is returned. - URLParamInt64Default(name string, def int64) int64 - // URLParamFloat64 returns the url query parameter as float64 value from a request, - // returns -1 and an error if parse failed. - URLParamFloat64(name string) (float64, error) - // URLParamFloat64Default returns the url query parameter as float64 value from a request, - // if not found or parse failed then "def" is returned. - URLParamFloat64Default(name string, def float64) float64 - // URLParamBool returns the url query parameter as boolean value from a request, - // returns an error if parse failed or not found. - URLParamBool(name string) (bool, error) - // URLParams returns a map of GET query parameters separated by comma if more than one - // it returns an empty map if nothing found. - URLParams() map[string]string + // FormValueDefault returns a single parsed form value by its "name", + // including both the URL field's query parameters and the POST or PUT form data. + // + // Returns the "def" if not found. + FormValueDefault(name string, def string) string + // FormValue returns a single parsed form value by its "name", + // including both the URL field's query parameters and the POST or PUT form data. + FormValue(name string) string + // FormValues returns the parsed form data, including both the URL + // 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 + // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. + // + // NOTE: A check for nil is necessary. + FormValues() map[string][]string - // FormValueDefault returns a single parsed form value by its "name", - // including both the URL field's query parameters and the POST or PUT form data. - // - // Returns the "def" if not found. - FormValueDefault(name string, def string) string - // FormValue returns a single parsed form value by its "name", - // including both the URL field's query parameters and the POST or PUT form data. - FormValue(name string) string - // FormValues returns the parsed form data, including both the URL - // 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 - // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. - // - // NOTE: A check for nil is necessary. - FormValues() map[string][]string + // PostValueDefault returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name". + // + // If not found then "def" is returned instead. + PostValueDefault(name string, def string) string + // PostValue returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name" + PostValue(name string) string + // PostValueTrim returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name", without trailing spaces. + PostValueTrim(name string) string + // PostValueInt returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name", as int. + // + // If not found returns -1 and a non-nil error. + PostValueInt(name string) (int, error) + // PostValueIntDefault returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name", as int. + // + // If not found returns or parse errors the "def". + PostValueIntDefault(name string, def int) int + // PostValueInt64 returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name", as float64. + // + // If not found returns -1 and a no-nil error. + PostValueInt64(name string) (int64, error) + // PostValueInt64Default returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name", as int64. + // + // If not found or parse errors returns the "def". + PostValueInt64Default(name string, def int64) int64 + // PostValueFloat64 returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name", as float64. + // + // If not found returns -1 and a non-nil error. + PostValueFloat64(name string) (float64, error) + // PostValueFloat64Default returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name", as float64. + // + // If not found or parse errors returns the "def". + PostValueFloat64Default(name string, def float64) float64 + // PostValueBool returns the parsed form data from POST, PATCH, + // or PUT body parameters based on a "name", as bool. + // + // If not found or value is false, then it returns false, otherwise true. + PostValueBool(name string) (bool, error) + // PostValues returns all the parsed form data from POST, PATCH, + // 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 + // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. + PostValues(name string) []string + // 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 + // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. + // + // Example: https://github.com/kataras/iris/tree/master/_examples/file-server/upload-file + FormFile(key string) (multipart.File, *multipart.FileHeader, error) + // UploadFormFiles uploads any received file(s) from the client + // to the system physical location "destDirectory". + // + // The second optional argument "before" gives caller the chance to + // modify the *miltipart.FileHeader before saving to the disk, + // it can be used to change a file's name based on the current request, + // all FileHeader's options can be changed. You can ignore it if + // you don't need to use this capability before saving a file to the disk. + // + // Note that it doesn't check if request body streamed. + // + // Returns the copied length as int64 and + // a not nil error if at least one new file + // can't be created due to the operating system's permissions or + // http.ErrMissingFile if no file received. + // + // If you want to receive & accept files and manage them manually you can use the `context#FormFile` + // instead and create a copy function that suits your needs, the below is for generic usage. + // + // The default form's memory maximum size is 32MB, it can be changed by the + // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. + // + // See `FormFile` to a more controlled to receive a file. + // + // + // Example: https://github.com/kataras/iris/tree/master/_examples/file-server/upload-files + UploadFormFiles(destDirectory string, before ...func(Context, *multipart.FileHeader)) (n int64, err error) - // PostValueDefault returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name". - // - // If not found then "def" is returned instead. - PostValueDefault(name string, def string) string - // PostValue returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name" - PostValue(name string) string - // PostValueTrim returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", without trailing spaces. - PostValueTrim(name string) string - // PostValueInt returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as int. - // - // If not found returns -1 and a non-nil error. - PostValueInt(name string) (int, error) - // PostValueIntDefault returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as int. - // - // If not found returns or parse errors the "def". - PostValueIntDefault(name string, def int) int - // PostValueInt64 returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as float64. - // - // If not found returns -1 and a no-nil error. - PostValueInt64(name string) (int64, error) - // PostValueInt64Default returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as int64. - // - // If not found or parse errors returns the "def". - PostValueInt64Default(name string, def int64) int64 - // PostValueFloat64 returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as float64. - // - // If not found returns -1 and a non-nil error. - PostValueFloat64(name string) (float64, error) - // PostValueFloat64Default returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as float64. - // - // If not found or parse errors returns the "def". - PostValueFloat64Default(name string, def float64) float64 - // PostValueBool returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as bool. - // - // If not found or value is false, then it returns false, otherwise true. - PostValueBool(name string) (bool, error) - // PostValues returns all the parsed form data from POST, PATCH, - // 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 - // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. - PostValues(name string) []string - // 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 - // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. - // - // Example: https://github.com/kataras/iris/tree/master/_examples/file-server/upload-file - FormFile(key string) (multipart.File, *multipart.FileHeader, error) - // UploadFormFiles uploads any received file(s) from the client - // to the system physical location "destDirectory". - // - // The second optional argument "before" gives caller the chance to - // modify the *miltipart.FileHeader before saving to the disk, - // it can be used to change a file's name based on the current request, - // all FileHeader's options can be changed. You can ignore it if - // you don't need to use this capability before saving a file to the disk. - // - // Note that it doesn't check if request body streamed. - // - // Returns the copied length as int64 and - // a not nil error if at least one new file - // can't be created due to the operating system's permissions or - // http.ErrMissingFile if no file received. - // - // If you want to receive & accept files and manage them manually you can use the `context#FormFile` - // instead and create a copy function that suits your needs, the below is for generic usage. - // - // The default form's memory maximum size is 32MB, it can be changed by the - // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. - // - // See `FormFile` to a more controlled to receive a file. - // - // - // Example: https://github.com/kataras/iris/tree/master/_examples/file-server/upload-files - UploadFormFiles(destDirectory string, before ...func(Context, *multipart.FileHeader)) (n int64, err error) + // +------------------------------------------------------------+ + // | Custom HTTP Errors | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Custom HTTP Errors | - // +------------------------------------------------------------+ + // NotFound emits an error 404 to the client, using the specific custom error error handler. + // Note that you may need to call ctx.StopExecution() if you don't want the next handlers + // to be executed. Next handlers are being executed on iris because you can alt the + // error code and change it to a more specific one, i.e + // users := app.Party("/users") + // users.Done(func(ctx context.Context){ if ctx.StatusCode() == 400 { /* custom error code for /users */ }}) + NotFound() - // NotFound emits an error 404 to the client, using the specific custom error error handler. - // Note that you may need to call ctx.StopExecution() if you don't want the next handlers - // to be executed. Next handlers are being executed on iris because you can alt the - // error code and change it to a more specific one, i.e - // users := app.Party("/users") - // users.Done(func(ctx context.Context){ if ctx.StatusCode() == 400 { /* custom error code for /users */ }}) - NotFound() + // +------------------------------------------------------------+ + // | Body Readers | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Body Readers | - // +------------------------------------------------------------+ + // SetMaxRequestBodySize sets a limit to the request body size + // should be called before reading the request body from the client. + SetMaxRequestBodySize(limitOverBytes int64) - // SetMaxRequestBodySize sets a limit to the request body size - // should be called before reading the request body from the client. - SetMaxRequestBodySize(limitOverBytes int64) + // GetBody reads and returns the request body. + // The default behavior for the http request reader is to consume the data readen + // but you can change that behavior by passing the `WithoutBodyConsumptionOnUnmarshal` iris option. + // + // However, whenever you can use the `ctx.Request().Body` instead. + GetBody() ([]byte, error) + // UnmarshalBody reads the request's body and binds it to a value or pointer of any type. + // Examples of usage: context.ReadJSON, context.ReadXML. + // + // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-custom-via-unmarshaler/main.go + // + // UnmarshalBody does not check about gzipped data. + // Do not rely on compressed data incoming to your server. The main reason is: https://en.wikipedia.org/wiki/Zip_bomb + // However you are still free to read the `ctx.Request().Body io.Reader` manually. + UnmarshalBody(outPtr interface{}, unmarshaler Unmarshaler) error + // ReadJSON reads JSON from request's body and binds it to a pointer of a value of any json-valid type. + // + // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-json/main.go + ReadJSON(jsonObjectPtr interface{}) error + // ReadXML reads XML from request's body and binds it to a pointer of a value of any xml-valid type. + // + // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-xml/main.go + ReadXML(xmlObjectPtr interface{}) error + // ReadYAML reads YAML from request's body and binds it to the "outPtr" value. + // + // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-yaml/main.go + ReadYAML(outPtr interface{}) error + // ReadForm binds the request body of a form to the "formObject". + // It supports any kind of type, including custom structs. + // It will return nothing if request data are empty. + // The struct field tag is "form". + // Note that it will return nil error on empty form data if `Configuration.FireEmptyFormError` + // is false (as defaulted) in this case the caller should check the pointer to + // see if something was actually binded. + // + // If a client sent an unknown field, this method will return an error, + // in order to ignore that error use the `err != nil && !iris.IsErrPath(err)`. + // + // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-form/main.go + ReadForm(formObject interface{}) error + // ReadQuery binds url query to "ptr". The struct field tag is "url". + // If a client sent an unknown field, this method will return an error, + // in order to ignore that error use the `err != nil && !iris.IsErrPath(err)`. + // + // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-query/main.go + ReadQuery(ptr interface{}) error + // ReadProtobuf binds the body to the "ptr" of a proto Message and returns any error. + ReadProtobuf(ptr proto.Message) error + // ReadMsgPack binds the request body of msgpack format to the "ptr" and returns any error. + ReadMsgPack(ptr interface{}) error + // ReadBody binds the request body to the "ptr" depending on the HTTP Method and the Request's Content-Type. + // If a GET method request then it reads from a form (or URL Query), otherwise + // it tries to match (depending on the request content-type) the data format e.g. + // JSON, Protobuf, MsgPack, XML, YAML, MultipartForm and binds the result to the "ptr". + ReadBody(ptr interface{}) error - // GetBody reads and returns the request body. - // The default behavior for the http request reader is to consume the data readen - // but you can change that behavior by passing the `WithoutBodyConsumptionOnUnmarshal` iris option. - // - // However, whenever you can use the `ctx.Request().Body` instead. - GetBody() ([]byte, error) - // UnmarshalBody reads the request's body and binds it to a value or pointer of any type. - // Examples of usage: context.ReadJSON, context.ReadXML. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-custom-via-unmarshaler/main.go - // - // UnmarshalBody does not check about gzipped data. - // Do not rely on compressed data incoming to your server. The main reason is: https://en.wikipedia.org/wiki/Zip_bomb - // However you are still free to read the `ctx.Request().Body io.Reader` manually. - UnmarshalBody(outPtr interface{}, unmarshaler Unmarshaler) error - // ReadJSON reads JSON from request's body and binds it to a pointer of a value of any json-valid type. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-json/main.go - ReadJSON(jsonObjectPtr interface{}) error - // ReadXML reads XML from request's body and binds it to a pointer of a value of any xml-valid type. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-xml/main.go - ReadXML(xmlObjectPtr interface{}) error - // ReadYAML reads YAML from request's body and binds it to the "outPtr" value. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-yaml/main.go - ReadYAML(outPtr interface{}) error - // ReadForm binds the request body of a form to the "formObject". - // It supports any kind of type, including custom structs. - // It will return nothing if request data are empty. - // The struct field tag is "form". - // Note that it will return nil error on empty form data if `Configuration.FireEmptyFormError` - // is false (as defaulted) in this case the caller should check the pointer to - // see if something was actually binded. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-form/main.go - ReadForm(formObject interface{}) error - // ReadQuery binds url query to "ptr". The struct field tag is "url". - // - // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-query/main.go - ReadQuery(ptr interface{}) error - // ReadProtobuf binds the body to the "ptr" of a proto Message and returns any error. - ReadProtobuf(ptr proto.Message) error - // ReadMsgPack binds the request body of msgpack format to the "ptr" and returns any error. - ReadMsgPack(ptr interface{}) error - // ReadBody binds the request body to the "ptr" depending on the HTTP Method and the Request's Content-Type. - // If a GET method request then it reads from a form (or URL Query), otherwise - // it tries to match (depending on the request content-type) the data format e.g. - // JSON, Protobuf, MsgPack, XML, YAML, MultipartForm and binds the result to the "ptr". - ReadBody(ptr interface{}) error + // +------------------------------------------------------------+ + // | Body (raw) Writers | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Body (raw) Writers | - // +------------------------------------------------------------+ + // Write writes the data to the connection as part of an HTTP reply. + // + // If WriteHeader has not yet been called, Write calls + // WriteHeader(http.StatusOK) before writing the data. If the Header + // does not contain a Content-Type line, Write adds a Content-Type set + // to the result of passing the initial 512 bytes of written data to + // DetectContentType. + // + // Depending on the HTTP protocol version and the client, calling + // Write or WriteHeader may prevent future reads on the + // Request.Body. For HTTP/1.x requests, handlers should read any + // needed request body data before writing the response. Once the + // headers have been flushed (due to either an explicit Flusher.Flush + // call or writing enough data to trigger a flush), the request body + // may be unavailable. For HTTP/2 requests, the Go HTTP server permits + // handlers to continue to read the request body while concurrently + // writing the response. However, such behavior may not be supported + // by all HTTP/2 clients. Handlers should read before writing if + // possible to maximize compatibility. + Write(body []byte) (int, error) + // Writef formats according to a format specifier and writes to the response. + // + // Returns the number of bytes written and any write error encountered. + Writef(format string, args ...interface{}) (int, error) + // WriteString writes a simple string to the response. + // + // Returns the number of bytes written and any write error encountered. + WriteString(body string) (int, error) - // Write writes the data to the connection as part of an HTTP reply. - // - // If WriteHeader has not yet been called, Write calls - // WriteHeader(http.StatusOK) before writing the data. If the Header - // does not contain a Content-Type line, Write adds a Content-Type set - // to the result of passing the initial 512 bytes of written data to - // DetectContentType. - // - // Depending on the HTTP protocol version and the client, calling - // Write or WriteHeader may prevent future reads on the - // Request.Body. For HTTP/1.x requests, handlers should read any - // needed request body data before writing the response. Once the - // headers have been flushed (due to either an explicit Flusher.Flush - // call or writing enough data to trigger a flush), the request body - // may be unavailable. For HTTP/2 requests, the Go HTTP server permits - // handlers to continue to read the request body while concurrently - // writing the response. However, such behavior may not be supported - // by all HTTP/2 clients. Handlers should read before writing if - // possible to maximize compatibility. - Write(body []byte) (int, error) - // Writef formats according to a format specifier and writes to the response. - // - // Returns the number of bytes written and any write error encountered. - Writef(format string, args ...interface{}) (int, error) - // WriteString writes a simple string to the response. - // - // Returns the number of bytes written and any write error encountered. - WriteString(body string) (int, error) + // SetLastModified sets the "Last-Modified" based on the "modtime" input. + // If "modtime" is zero then it does nothing. + // + // It's mostly internally on core/router and context packages. + // + // Note that modtime.UTC() is being used instead of just modtime, so + // you don't have to know the internals in order to make that works. + SetLastModified(modtime time.Time) + // CheckIfModifiedSince checks if the response is modified since the "modtime". + // Note that it has nothing to do with server-side caching. + // It does those checks by checking if the "If-Modified-Since" request header + // sent by client or a previous server response header + // (e.g with WriteWithExpiration or HandleDir or Favicon etc.) + // is a valid one and it's before the "modtime". + // + // A check for !modtime && err == nil is necessary to make sure that + // it's not modified since, because it may return false but without even + // had the chance to check the client-side (request) header due to some errors, + // like the HTTP Method is not "GET" or "HEAD" or if the "modtime" is zero + // or if parsing time from the header failed. + // + // It's mostly used internally, e.g. `context#WriteWithExpiration`. See `ErrPreconditionFailed` too. + // + // Note that modtime.UTC() is being used instead of just modtime, so + // you don't have to know the internals in order to make that works. + CheckIfModifiedSince(modtime time.Time) (bool, error) + // WriteNotModified sends a 304 "Not Modified" status code to the client, + // it makes sure that the content type, the content length headers + // and any "ETag" are removed before the response sent. + // + // It's mostly used internally on core/router/fs.go and context methods. + WriteNotModified() + // WriteWithExpiration works like `Write` but it will check if a resource is modified, + // based on the "modtime" input argument, + // otherwise sends a 304 status code in order to let the client-side render the cached content. + WriteWithExpiration(body []byte, modtime time.Time) (int, error) + // StreamWriter registers the given stream writer for populating + // response body. + // + // Access to context's and/or its' members is forbidden from writer. + // + // This function may be used in the following cases: + // + // * if response body is too big (more than iris.LimitRequestBodySize(if set)). + // * if response body is streamed from slow external sources. + // * if response body must be streamed to the client in chunks. + // (aka `http server push`). + // + // receives a function which receives the response writer + // and returns false when it should stop writing, otherwise true in order to continue + StreamWriter(writer func(w io.Writer) bool) - // SetLastModified sets the "Last-Modified" based on the "modtime" input. - // If "modtime" is zero then it does nothing. - // - // It's mostly internally on core/router and context packages. - // - // Note that modtime.UTC() is being used instead of just modtime, so - // you don't have to know the internals in order to make that works. - SetLastModified(modtime time.Time) - // CheckIfModifiedSince checks if the response is modified since the "modtime". - // Note that it has nothing to do with server-side caching. - // It does those checks by checking if the "If-Modified-Since" request header - // sent by client or a previous server response header - // (e.g with WriteWithExpiration or HandleDir or Favicon etc.) - // is a valid one and it's before the "modtime". - // - // A check for !modtime && err == nil is necessary to make sure that - // it's not modified since, because it may return false but without even - // had the chance to check the client-side (request) header due to some errors, - // like the HTTP Method is not "GET" or "HEAD" or if the "modtime" is zero - // or if parsing time from the header failed. - // - // It's mostly used internally, e.g. `context#WriteWithExpiration`. See `ErrPreconditionFailed` too. - // - // Note that modtime.UTC() is being used instead of just modtime, so - // you don't have to know the internals in order to make that works. - CheckIfModifiedSince(modtime time.Time) (bool, error) - // WriteNotModified sends a 304 "Not Modified" status code to the client, - // it makes sure that the content type, the content length headers - // and any "ETag" are removed before the response sent. - // - // It's mostly used internally on core/router/fs.go and context methods. - WriteNotModified() - // WriteWithExpiration works like `Write` but it will check if a resource is modified, - // based on the "modtime" input argument, - // otherwise sends a 304 status code in order to let the client-side render the cached content. - WriteWithExpiration(body []byte, modtime time.Time) (int, error) - // StreamWriter registers the given stream writer for populating - // response body. - // - // Access to context's and/or its' members is forbidden from writer. - // - // This function may be used in the following cases: - // - // * if response body is too big (more than iris.LimitRequestBodySize(if set)). - // * if response body is streamed from slow external sources. - // * if response body must be streamed to the client in chunks. - // (aka `http server push`). - // - // receives a function which receives the response writer - // and returns false when it should stop writing, otherwise true in order to continue - StreamWriter(writer func(w io.Writer) bool) + // +------------------------------------------------------------+ + // | Body Writers with compression | + // +------------------------------------------------------------+ + // ClientSupportsGzip retruns true if the client supports gzip compression. + ClientSupportsGzip() bool + // WriteGzip accepts bytes, which are compressed to gzip format and sent to the client. + // returns the number of bytes written and an error ( if the client doesn' supports gzip compression) + // You may re-use this function in the same handler + // to write more data many times without any troubles. + WriteGzip(b []byte) (int, error) + // TryWriteGzip accepts bytes, which are compressed to gzip format and sent to the client. + // If client does not supprots gzip then the contents are written as they are, uncompressed. + TryWriteGzip(b []byte) (int, error) + // GzipResponseWriter converts the current response writer into a response writer + // which when its .Write called it compress the data to gzip and writes them to the client. + // + // Can be also disabled with its .Disable and .ResetBody to rollback to the usual response writer. + GzipResponseWriter() *GzipResponseWriter + // Gzip enables or disables (if enabled before) the gzip response writer,if the client + // supports gzip compression, so the following response data will + // be sent as compressed gzip data to the client. + Gzip(enable bool) + // GzipReader accepts a boolean, which, if set to true + // it wraps the request body reader with a gzip reader one (decompress request data on read). + // If the "enable" input argument is false then the request body will reset to the default one. + // + // Useful when incoming request data are gzip compressed. + // All future calls of `ctx.GetBody/ReadXXX/UnmarshalBody` methods will respect this option. + // + // Usage: + // app.Use(func(ctx iris.Context){ + // ctx.GzipReader(true) + // ctx.Next() + // }) + // + // If a client request's body is not gzip compressed then + // it returns with a `ErrGzipNotSupported` error, which can be safety ignored. + // + // See `GzipReader` package-level middleware too. + GzipReader(enable bool) error - // +------------------------------------------------------------+ - // | Body Writers with compression | - // +------------------------------------------------------------+ - // ClientSupportsGzip retruns true if the client supports gzip compression. - ClientSupportsGzip() bool - // WriteGzip accepts bytes, which are compressed to gzip format and sent to the client. - // returns the number of bytes written and an error ( if the client doesn' supports gzip compression) - // You may re-use this function in the same handler - // to write more data many times without any troubles. - WriteGzip(b []byte) (int, error) - // TryWriteGzip accepts bytes, which are compressed to gzip format and sent to the client. - // If client does not supprots gzip then the contents are written as they are, uncompressed. - TryWriteGzip(b []byte) (int, error) - // GzipResponseWriter converts the current response writer into a response writer - // which when its .Write called it compress the data to gzip and writes them to the client. - // - // Can be also disabled with its .Disable and .ResetBody to rollback to the usual response writer. - GzipResponseWriter() *GzipResponseWriter - // Gzip enables or disables (if enabled before) the gzip response writer,if the client - // supports gzip compression, so the following response data will - // be sent as compressed gzip data to the client. - Gzip(enable bool) - // GzipReader accepts a boolean, which, if set to true - // it wraps the request body reader with a gzip reader one (decompress request data on read). - // If the "enable" input argument is false then the request body will reset to the default one. - // - // Useful when incoming request data are gzip compressed. - // All future calls of `ctx.GetBody/ReadXXX/UnmarshalBody` methods will respect this option. - // - // Usage: - // app.Use(func(ctx iris.Context){ - // ctx.GzipReader(true) - // ctx.Next() - // }) - // - // If a client request's body is not gzip compressed then - // it returns with a `ErrGzipNotSupported` error, which can be safety ignored. - // - // See `GzipReader` package-level middleware too. - GzipReader(enable bool) error + // +------------------------------------------------------------+ + // | Rich Body Content Writers/Renderers | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Rich Body Content Writers/Renderers | - // +------------------------------------------------------------+ + // ViewLayout sets the "layout" option if and when .View + // is being called afterwards, in the same request. + // Useful when need to set or/and change a layout based on the previous handlers in the chain. + // + // Note that the 'layoutTmplFile' argument can be set to iris.NoLayout || view.NoLayout + // to disable the layout for a specific view render action, + // it disables the engine's configuration's layout property. + // + // Look .ViewData and .View too. + // + // Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/ + ViewLayout(layoutTmplFile string) + // 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. + // Useful when need to set or/and change template data from previous hanadlers in the chain. + // + // If .View's "binding" argument is not nil and it's not a type of map + // then these data are being ignored, binding has the priority, so the main route's handler can still decide. + // If binding is a map or context.Map then these data are being added to the view data + // and passed to the template. + // + // After .View, the data are not destroyed, in order to be re-used if needed (again, in the same request as everything else), + // to clear the view data, developers can call: + // ctx.Set(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey(), nil) + // + // If 'key' is empty then the value is added as it's (struct or map) and developer is unable to add other value. + // + // Look .ViewLayout and .View too. + // + // Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/ + ViewData(key string, value interface{}) + // GetViewData returns the values registered by `context#ViewData`. + // The return value is `map[string]interface{}`, this means that + // if a custom struct registered to ViewData then this function + // will try to parse it to map, if failed then the return value is nil + // A check for nil is always a good practise if different + // kind of values or no data are registered via `ViewData`. + // + // Similarly to `viewData := ctx.Values().Get("iris.viewData")` or + // `viewData := ctx.Values().Get(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey())`. + GetViewData() map[string]interface{} + // View renders a template based on the registered view engine(s). + // 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" + // then you pass the "users/index.html" as the filename argument. + // + // 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. + // + // Look .ViewData` and .ViewLayout too. + // + // Examples: https://github.com/kataras/iris/tree/master/_examples/view + View(filename string, optionalViewModel ...interface{}) error - // ViewLayout sets the "layout" option if and when .View - // is being called afterwards, in the same request. - // Useful when need to set or/and change a layout based on the previous handlers in the chain. - // - // Note that the 'layoutTmplFile' argument can be set to iris.NoLayout || view.NoLayout - // to disable the layout for a specific view render action, - // it disables the engine's configuration's layout property. - // - // Look .ViewData and .View too. - // - // Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/ - ViewLayout(layoutTmplFile string) - // 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. - // Useful when need to set or/and change template data from previous hanadlers in the chain. - // - // If .View's "binding" argument is not nil and it's not a type of map - // then these data are being ignored, binding has the priority, so the main route's handler can still decide. - // If binding is a map or context.Map then these data are being added to the view data - // and passed to the template. - // - // After .View, the data are not destroyed, in order to be re-used if needed (again, in the same request as everything else), - // to clear the view data, developers can call: - // ctx.Set(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey(), nil) - // - // If 'key' is empty then the value is added as it's (struct or map) and developer is unable to add other value. - // - // Look .ViewLayout and .View too. - // - // Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/ - ViewData(key string, value interface{}) - // GetViewData returns the values registered by `context#ViewData`. - // The return value is `map[string]interface{}`, this means that - // if a custom struct registered to ViewData then this function - // will try to parse it to map, if failed then the return value is nil - // A check for nil is always a good practise if different - // kind of values or no data are registered via `ViewData`. - // - // Similarly to `viewData := ctx.Values().Get("iris.viewData")` or - // `viewData := ctx.Values().Get(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey())`. - GetViewData() map[string]interface{} - // View renders a template based on the registered view engine(s). - // 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" - // then you pass the "users/index.html" as the filename argument. - // - // 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. - // - // Look .ViewData` and .ViewLayout too. - // - // 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(data []byte) (int, error) + // Text writes out a string as plain text. + Text(format string, args ...interface{}) (int, error) + // HTML writes out a string as text/html. + HTML(format string, args ...interface{}) (int, error) + // JSON marshals the given interface object and writes the JSON response. + JSON(v interface{}, options ...JSON) (int, error) + // JSONP marshals the given interface object and writes the JSON response. + JSONP(v interface{}, options ...JSONP) (int, error) + // XML marshals the given interface object and writes the XML response. + // To render maps as XML see the `XMLMap` package-level function. + XML(v interface{}, options ...XML) (int, error) + // Problem writes a JSON or XML problem response. + // Order of Problem fields are not always rendered the same. + // + // Behaves exactly like `Context.JSON` + // but with default ProblemOptions.JSON indent of " " and + // a response content type of "application/problem+json" instead. + // + // Use the options.RenderXML and XML fields to change this behavior and + // send a response of content type "application/problem+xml" instead. + // + // Read more at: https://github.com/kataras/iris/wiki/Routing-error-handlers + Problem(v interface{}, opts ...ProblemOptions) (int, error) + // Markdown parses the markdown to html and renders its result to the client. + Markdown(markdownB []byte, options ...Markdown) (int, error) + // YAML parses the "v" using the yaml parser and renders its result to the client. + YAML(v interface{}) (int, error) + // Protobuf parses the "v" of proto Message and renders its result to the client. + Protobuf(v proto.Message) (int, error) + // MsgPack parses the "v" of msgpack format and renders its result to the client. + MsgPack(v interface{}) (int, error) - // Binary writes out the raw bytes as binary data. - Binary(data []byte) (int, error) - // Text writes out a string as plain text. - Text(format string, args ...interface{}) (int, error) - // HTML writes out a string as text/html. - HTML(format string, args ...interface{}) (int, error) - // JSON marshals the given interface object and writes the JSON response. - JSON(v interface{}, options ...JSON) (int, error) - // JSONP marshals the given interface object and writes the JSON response. - JSONP(v interface{}, options ...JSONP) (int, error) - // XML marshals the given interface object and writes the XML response. - // To render maps as XML see the `XMLMap` package-level function. - XML(v interface{}, options ...XML) (int, error) - // Problem writes a JSON or XML problem response. - // Order of Problem fields are not always rendered the same. - // - // Behaves exactly like `Context.JSON` - // but with default ProblemOptions.JSON indent of " " and - // a response content type of "application/problem+json" instead. - // - // Use the options.RenderXML and XML fields to change this behavior and - // send a response of content type "application/problem+xml" instead. - // - // Read more at: https://github.com/kataras/iris/wiki/Routing-error-handlers - Problem(v interface{}, opts ...ProblemOptions) (int, error) - // Markdown parses the markdown to html and renders its result to the client. - Markdown(markdownB []byte, options ...Markdown) (int, error) - // YAML parses the "v" using the yaml parser and renders its result to the client. - YAML(v interface{}) (int, error) - // Protobuf parses the "v" of proto Message and renders its result to the client. - Protobuf(v proto.Message) (int, error) - // MsgPack parses the "v" of msgpack format and renders its result to the client. - MsgPack(v interface{}) (int, error) + // +-----------------------------------------------------------------------+ + // | Content Νegotiation | + // | https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation | | + // +-----------------------------------------------------------------------+ - // +-----------------------------------------------------------------------+ - // | Content Νegotiation | - // | https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation | | - // +-----------------------------------------------------------------------+ + // Negotiation creates once and returns the negotiation builder + // to build server-side available content for specific mime type(s) + // and charset(s). + // + // See `Negotiate` method too. + Negotiation() *NegotiationBuilder + // Negotiate used for serving different representations of a resource at the same URI. + // + // The "v" can be a single `N` struct value. + // The "v" can be any value completes the `ContentSelector` interface. + // The "v" can be any value completes the `ContentNegotiator` interface. + // The "v" can be any value of struct(JSON, JSONP, XML, YAML) or + // string(TEXT, HTML) or []byte(Markdown, Binary) or []byte with any matched mime type. + // + // If the "v" is nil, the `Context.Negotitation()` builder's + // content will be used instead, otherwise "v" overrides builder's content + // (server mime types are still retrieved by its registered, supported, mime list) + // + // Set mime type priorities by `Negotiation().JSON().XML().HTML()...`. + // Set charset priorities by `Negotiation().Charset(...)`. + // Set encoding algorithm priorities by `Negotiation().Encoding(...)`. + // Modify the accepted by + // `Negotiation().Accept./Override()/.XML().JSON().Charset(...).Encoding(...)...`. + // + // It returns `ErrContentNotSupported` when not matched mime type(s). + // + // Resources: + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding + // + // Supports the above without quality values. + // + // Read more at: https://github.com/kataras/iris/wiki/Content-negotiation + Negotiate(v interface{}) (int, error) - // Negotiation creates once and returns the negotiation builder - // to build server-side available content for specific mime type(s) - // and charset(s). - // - // See `Negotiate` method too. - Negotiation() *NegotiationBuilder - // Negotiate used for serving different representations of a resource at the same URI. - // - // The "v" can be a single `N` struct value. - // The "v" can be any value completes the `ContentSelector` interface. - // The "v" can be any value completes the `ContentNegotiator` interface. - // The "v" can be any value of struct(JSON, JSONP, XML, YAML) or - // string(TEXT, HTML) or []byte(Markdown, Binary) or []byte with any matched mime type. - // - // If the "v" is nil, the `Context.Negotitation()` builder's - // content will be used instead, otherwise "v" overrides builder's content - // (server mime types are still retrieved by its registered, supported, mime list) - // - // Set mime type priorities by `Negotiation().JSON().XML().HTML()...`. - // Set charset priorities by `Negotiation().Charset(...)`. - // Set encoding algorithm priorities by `Negotiation().Encoding(...)`. - // Modify the accepted by - // `Negotiation().Accept./Override()/.XML().JSON().Charset(...).Encoding(...)...`. - // - // It returns `ErrContentNotSupported` when not matched mime type(s). - // - // Resources: - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding - // - // Supports the above without quality values. - // - // Read more at: https://github.com/kataras/iris/wiki/Content-negotiation - Negotiate(v interface{}) (int, error) + // +------------------------------------------------------------+ + // | Serve files | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Serve files | - // +------------------------------------------------------------+ + // ServeContent replies to the request using the content in the + // provided ReadSeeker. The main benefit of ServeContent over io.Copy + // is that it handles Range requests properly, sets the MIME type, and + // handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since, + // and If-Range requests. + // + // If the response's Content-Type header is not set, ServeContent + // first tries to deduce the type from name's file extension. + // + // The name is otherwise unused; in particular it can be empty and is + // never sent in the response. + // + // If modtime is not the zero time or Unix epoch, ServeContent + // includes it in a Last-Modified header in the response. If the + // request includes an If-Modified-Since header, ServeContent uses + // modtime to decide whether the content needs to be sent at all. + // + // The content's Seek method must work: ServeContent uses + // a seek to the end of the content to determine its size. + // + // If the caller has set w's ETag header formatted per RFC 7232, section 2.3, + // ServeContent uses it to handle requests using If-Match, If-None-Match, or If-Range. + // + // Note that *os.File implements the io.ReadSeeker interface. + // Note that gzip compression can be registered through `ctx.Gzip(true)` or `app.Use(iris.Gzip)`. + ServeContent(content io.ReadSeeker, filename string, modtime time.Time) + // ServeContentWithRate same as `ServeContent` but it can throttle the speed of reading + // and though writing the "content" to the client. + ServeContentWithRate(content io.ReadSeeker, filename string, modtime time.Time, limit float64, burst int) + // ServeFile replies to the request with the contents of the named + // file or directory. + // + // If the provided file or directory name is a relative path, it is + // interpreted relative to the current directory and may ascend to + // parent directories. If the provided name is constructed from user + // input, it should be sanitized before calling `ServeFile`. + // + // Use it when you want to serve assets like css and javascript files. + // If client should confirm and save the file use the `SendFile` instead. + // Note that gzip compression can be registered through `ctx.Gzip(true)` or `app.Use(iris.Gzip)`. + ServeFile(filename string) error + // ServeFileWithRate same as `ServeFile` but it can throttle the speed of reading + // and though writing the file to the client. + ServeFileWithRate(filename string, limit float64, burst int) error + // SendFile sends a file as an attachment, that is downloaded and saved locally from client. + // Note that gzip compression can be registered through `ctx.Gzip(true)` or `app.Use(iris.Gzip)`. + // Use `ServeFile` if a file should be served as a page asset instead. + SendFile(filename string, destinationName string) error + // SendFileWithRate same as `SendFile` but it can throttle the speed of reading + // and though writing the file to the client. + SendFileWithRate(src, destName string, limit float64, burst int) error - // ServeContent replies to the request using the content in the - // provided ReadSeeker. The main benefit of ServeContent over io.Copy - // is that it handles Range requests properly, sets the MIME type, and - // handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since, - // and If-Range requests. - // - // If the response's Content-Type header is not set, ServeContent - // first tries to deduce the type from name's file extension. - // - // The name is otherwise unused; in particular it can be empty and is - // never sent in the response. - // - // If modtime is not the zero time or Unix epoch, ServeContent - // includes it in a Last-Modified header in the response. If the - // request includes an If-Modified-Since header, ServeContent uses - // modtime to decide whether the content needs to be sent at all. - // - // The content's Seek method must work: ServeContent uses - // a seek to the end of the content to determine its size. - // - // If the caller has set w's ETag header formatted per RFC 7232, section 2.3, - // ServeContent uses it to handle requests using If-Match, If-None-Match, or If-Range. - // - // Note that *os.File implements the io.ReadSeeker interface. - // Note that gzip compression can be registered through `ctx.Gzip(true)` or `app.Use(iris.Gzip)`. - ServeContent(content io.ReadSeeker, filename string, modtime time.Time) - // ServeContentWithRate same as `ServeContent` but it can throttle the speed of reading - // and though writing the "content" to the client. - ServeContentWithRate(content io.ReadSeeker, filename string, modtime time.Time, limit float64, burst int) - // ServeFile replies to the request with the contents of the named - // file or directory. - // - // If the provided file or directory name is a relative path, it is - // interpreted relative to the current directory and may ascend to - // parent directories. If the provided name is constructed from user - // input, it should be sanitized before calling `ServeFile`. - // - // Use it when you want to serve assets like css and javascript files. - // If client should confirm and save the file use the `SendFile` instead. - // Note that gzip compression can be registered through `ctx.Gzip(true)` or `app.Use(iris.Gzip)`. - ServeFile(filename string) error - // ServeFileWithRate same as `ServeFile` but it can throttle the speed of reading - // and though writing the file to the client. - ServeFileWithRate(filename string, limit float64, burst int) error - // SendFile sends a file as an attachment, that is downloaded and saved locally from client. - // Note that gzip compression can be registered through `ctx.Gzip(true)` or `app.Use(iris.Gzip)`. - // Use `ServeFile` if a file should be served as a page asset instead. - SendFile(filename string, destinationName string) error - // SendFileWithRate same as `SendFile` but it can throttle the speed of reading - // and though writing the file to the client. - SendFileWithRate(src, destName string, limit float64, burst int) error + // +------------------------------------------------------------+ + // | Cookies | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Cookies | - // +------------------------------------------------------------+ + // AddCookieOptions adds cookie options for `SetCookie`, + // `SetCookieKV, UpsertCookie` and `RemoveCookie` methods + // for the current request. It can be called from a middleware before + // cookies sent or received from the next Handler in the chain. + // See `ClearCookieOptions` too. + // + // Available builtin Cookie options are: + // * CookieAllowReclaim + // * CookieAllowSubdomains + // * CookieSecure + // * CookieHTTPOnly + // * CookieSameSite + // * CookiePath + // * CookieCleanPath + // * CookieExpires + // * CookieEncoding + // + // Example at: https://github.com/kataras/iris/tree/master/_examples/cookies/securecookie + AddCookieOptions(options ...CookieOption) + // ClearCookieOptions clears any previously registered cookie options. + // See `AddCookieOptions` too. + ClearCookieOptions() + // SetCookie adds a cookie. + // Use of the "options" is not required, they can be used to amend the "cookie". + // + // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic + SetCookie(cookie *http.Cookie, options ...CookieOption) + // UpsertCookie adds a cookie to the response like `SetCookie` does + // but it will also perform a replacement of the cookie + // if already set by a previous `SetCookie` call. + // It reports whether the cookie is new (true) or an existing one was updated (false). + UpsertCookie(cookie *http.Cookie, options ...CookieOption) bool + // SetCookieKV adds a cookie, requires the name(string) and the value(string). + // + // By default it expires at 2 hours and it's added to the root path, + // use the `CookieExpires` and `CookiePath` to modify them. + // Alternatively: ctx.SetCookie(&http.Cookie{...}) + // + // If you want to set custom the path: + // ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored")) + // + // If you want to be visible only to current request path: + // ctx.SetCookieKV(name, value, iris.CookieCleanPath/iris.CookiePath("")) + // More: + // iris.CookieExpires(time.Duration) + // iris.CookieHTTPOnly(false) + // + // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic + SetCookieKV(name, value string, options ...CookieOption) + // GetCookie returns cookie's value by its name + // returns empty string if nothing was found. + // + // If you want more than the value then: + // cookie, err := ctx.Request().Cookie("name") + // + // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic + GetCookie(name string, options ...CookieOption) string + // RemoveCookie deletes a cookie by its name and path = "/". + // Tip: change the cookie's path to the current one by: RemoveCookie("name", iris.CookieCleanPath) + // + // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic + RemoveCookie(name string, options ...CookieOption) + // VisitAllCookies accepts a visitor function which is called + // on each (request's) cookies' name and value. + VisitAllCookies(visitor func(name string, value string)) - // AddCookieOptions adds cookie options for `SetCookie`, - // `SetCookieKV, UpsertCookie` and `RemoveCookie` methods - // for the current request. It can be called from a middleware before - // cookies sent or received from the next Handler in the chain. - // See `ClearCookieOptions` too. - // - // Available builtin Cookie options are: - // * CookieAllowReclaim - // * CookieAllowSubdomains - // * CookieSecure - // * CookieHTTPOnly - // * CookieSameSite - // * CookiePath - // * CookieCleanPath - // * CookieExpires - // * CookieEncoding - // - // Example at: https://github.com/kataras/iris/tree/master/_examples/cookies/securecookie - AddCookieOptions(options ...CookieOption) - // ClearCookieOptions clears any previously registered cookie options. - // See `AddCookieOptions` too. - ClearCookieOptions() - // SetCookie adds a cookie. - // Use of the "options" is not required, they can be used to amend the "cookie". - // - // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic - SetCookie(cookie *http.Cookie, options ...CookieOption) - // UpsertCookie adds a cookie to the response like `SetCookie` does - // but it will also perform a replacement of the cookie - // if already set by a previous `SetCookie` call. - // It reports whether the cookie is new (true) or an existing one was updated (false). - UpsertCookie(cookie *http.Cookie, options ...CookieOption) bool - // SetCookieKV adds a cookie, requires the name(string) and the value(string). - // - // By default it expires at 2 hours and it's added to the root path, - // use the `CookieExpires` and `CookiePath` to modify them. - // Alternatively: ctx.SetCookie(&http.Cookie{...}) - // - // If you want to set custom the path: - // ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored")) - // - // If you want to be visible only to current request path: - // ctx.SetCookieKV(name, value, iris.CookieCleanPath/iris.CookiePath("")) - // More: - // iris.CookieExpires(time.Duration) - // iris.CookieHTTPOnly(false) - // - // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic - SetCookieKV(name, value string, options ...CookieOption) - // GetCookie returns cookie's value by its name - // returns empty string if nothing was found. - // - // If you want more than the value then: - // cookie, err := ctx.Request().Cookie("name") - // - // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic - GetCookie(name string, options ...CookieOption) string - // RemoveCookie deletes a cookie by its name and path = "/". - // Tip: change the cookie's path to the current one by: RemoveCookie("name", iris.CookieCleanPath) - // - // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic - RemoveCookie(name string, options ...CookieOption) - // VisitAllCookies accepts a visitor function which is called - // on each (request's) cookies' name and value. - VisitAllCookies(visitor func(name string, value string)) + // MaxAge returns the "cache-control" request header's value + // seconds as int64 + // if header not found or parse failed then it returns -1. + MaxAge() int64 - // MaxAge returns the "cache-control" request header's value - // seconds as int64 - // if header not found or parse failed then it returns -1. - MaxAge() int64 + // +------------------------------------------------------------+ + // | Advanced: Response Recorder and Transactions | + // +------------------------------------------------------------+ - // +------------------------------------------------------------+ - // | Advanced: Response Recorder and Transactions | - // +------------------------------------------------------------+ + // Record transforms the context's basic and direct responseWriter to a ResponseRecorder + // which can be used to reset the body, reset headers, get the body, + // get & set the status code at any time and more. + Record() + // Recorder returns the context's ResponseRecorder + // if not recording then it starts recording and returns the new context's ResponseRecorder + Recorder() *ResponseRecorder + // IsRecording returns the response recorder and a true value + // when the response writer is recording the status code, body, headers and so on, + // else returns nil and false. + IsRecording() (*ResponseRecorder, bool) - // Record transforms the context's basic and direct responseWriter to a ResponseRecorder - // which can be used to reset the body, reset headers, get the body, - // get & set the status code at any time and more. - Record() - // Recorder returns the context's ResponseRecorder - // if not recording then it starts recording and returns the new context's ResponseRecorder - Recorder() *ResponseRecorder - // IsRecording returns the response recorder and a true value - // when the response writer is recording the status code, body, headers and so on, - // else returns nil and false. - IsRecording() (*ResponseRecorder, bool) + // BeginTransaction starts a scoped transaction. + // + // You can search third-party articles or books on how Business Transaction works (it's quite simple, especially here). + // + // Note that this is unique and new + // (=I haver never seen any other examples or code in Golang on this subject, so far, as with the most of iris features...) + // it's not covers all paths, + // such as databases, this should be managed by the libraries you use to make your database connection, + // this transaction scope is only for context's response. + // Transactions have their own middleware ecosystem also, look iris.go:UseTransaction. + // + // See https://github.com/kataras/iris/tree/master/_examples/ for more + BeginTransaction(pipe func(t *Transaction)) + // SkipTransactions if called then skip the rest of the transactions + // or all of them if called before the first transaction + SkipTransactions() + // TransactionsSkipped returns true if the transactions skipped or canceled at all. + TransactionsSkipped() bool - // BeginTransaction starts a scoped transaction. - // - // You can search third-party articles or books on how Business Transaction works (it's quite simple, especially here). - // - // Note that this is unique and new - // (=I haver never seen any other examples or code in Golang on this subject, so far, as with the most of iris features...) - // it's not covers all paths, - // such as databases, this should be managed by the libraries you use to make your database connection, - // this transaction scope is only for context's response. - // Transactions have their own middleware ecosystem also, look iris.go:UseTransaction. - // - // See https://github.com/kataras/iris/tree/master/_examples/ for more - BeginTransaction(pipe func(t *Transaction)) - // SkipTransactions if called then skip the rest of the transactions - // or all of them if called before the first transaction - SkipTransactions() - // TransactionsSkipped returns true if the transactions skipped or canceled at all. - TransactionsSkipped() bool + // Exec calls the `context/Application#ServeCtx` + // based on this context but with a changed method and path + // like it was requested by the user, but it is not. + // + // Offline means that the route is registered to the iris and have all features that a normal route has + // BUT it isn't available by browsing, its handlers executed only when other handler's context call them + // it can validate paths, has sessions, path parameters and all. + // + // You can find the Route by app.GetRoute("theRouteName") + // you can set a route name as: myRoute := app.Get("/mypath", handler)("theRouteName") + // that will set a name to the route and returns its RouteInfo instance for further usage. + // + // It doesn't changes the global state, if a route was "offline" it remains offline. + // + // app.None(...) and app.GetRoutes().Offline(route)/.Online(route, method) + // + // Example: https://github.com/kataras/iris/tree/master/_examples/routing/route-state + // + // User can get the response by simple using rec := ctx.Recorder(); rec.Body()/rec.StatusCode()/rec.Header(). + // + // Context's Values and the Session are kept in order to be able to communicate via the result route. + // + // It's for extreme use cases, 99% of the times will never be useful for you. + Exec(method, path string) - // Exec calls the `context/Application#ServeCtx` - // based on this context but with a changed method and path - // like it was requested by the user, but it is not. - // - // Offline means that the route is registered to the iris and have all features that a normal route has - // BUT it isn't available by browsing, its handlers executed only when other handler's context call them - // it can validate paths, has sessions, path parameters and all. - // - // You can find the Route by app.GetRoute("theRouteName") - // you can set a route name as: myRoute := app.Get("/mypath", handler)("theRouteName") - // that will set a name to the route and returns its RouteInfo instance for further usage. - // - // It doesn't changes the global state, if a route was "offline" it remains offline. - // - // app.None(...) and app.GetRoutes().Offline(route)/.Online(route, method) - // - // Example: https://github.com/kataras/iris/tree/master/_examples/routing/route-state - // - // User can get the response by simple using rec := ctx.Recorder(); rec.Body()/rec.StatusCode()/rec.Header(). - // - // Context's Values and the Session are kept in order to be able to communicate via the result route. - // - // It's for extreme use cases, 99% of the times will never be useful for you. - Exec(method, path string) + // RouteExists reports whether a particular route exists + // It will search from the current subdomain of context's host, if not inside the root domain. + RouteExists(method, path string) bool - // RouteExists reports whether a particular route exists - // It will search from the current subdomain of context's host, if not inside the root domain. - RouteExists(method, path string) bool + // ReflectValue caches and returns a []reflect.Value{reflect.ValueOf(ctx)}. + // It's just a helper to maintain variable inside the context itself. + ReflectValue() []reflect.Value + // Controller returns a reflect Value of the custom Controller from which this handler executed. + // It will return a Kind() == reflect.Invalid if the handler was not executed from within a controller. + Controller() reflect.Value + // RegisterDependency registers a struct dependency at serve-time + // for the next handler in the chain. One value per type. + // Note that it's highly recommended to register + // your dependencies before server ran + // through APIContainer(app.ConfigureContainer) or MVC(mvc.New) + // in sake of minimum performance cost. + // + // See `UnregisterDependency` too. + RegisterDependency(v interface{}) + // UnregisterDependency removes a dependency based on its type. + // Reports whether a dependency with that type was found and removed successfully. + // + // See `RegisterDependency` too. + UnregisterDependency(typ reflect.Type) bool - // ReflectValue caches and returns a []reflect.Value{reflect.ValueOf(ctx)}. - // It's just a helper to maintain variable inside the context itself. - ReflectValue() []reflect.Value - // Controller returns a reflect Value of the custom Controller from which this handler executed. - // It will return a Kind() == reflect.Invalid if the handler was not executed from within a controller. - Controller() reflect.Value - // RegisterDependency registers a struct dependency at serve-time - // for the next handler in the chain. One value per type. - // Note that it's highly recommended to register - // your dependencies before server ran - // through APIContainer(app.ConfigureContainer) or MVC(mvc.New) - // in sake of minimum performance cost. - // - // See `UnRegisterDependency` too. - RegisterDependency(v interface{}) - // UnRegisterDependency removes a dependency based on its type. - // Reports whether a dependency with that type was found and removed successfully. - // - // See `RegisterDependency` too. - UnRegisterDependency(typ reflect.Type) bool + // Application returns the iris app instance which belongs to this context. + // Worth to notice that this function returns an interface + // of the Application, which contains methods that are safe + // to be executed at serve-time. The full app's fields + // and methods are not available here for the developer's safety. + Application() Application - // Application returns the iris app instance which belongs to this context. - // Worth to notice that this function returns an interface - // of the Application, which contains methods that are safe - // to be executed at serve-time. The full app's fields - // and methods are not available here for the developer's safety. - Application() Application - - // SetID sets an ID, any value, to the Request Context. - // If possible the "id" should implement a `String() string` method - // so it can be rendered on `Context.String` method. - // - // See `GetID` and `middleware/requestid` too. - SetID(id interface{}) - // GetID returns the Request Context's ID. - // It returns nil if not given by a prior `SetID` call. - // See `middleware/requestid` too. - GetID() interface{} - // String returns the string representation of this request. - // - // It returns the Context's ID given by a `SetID`call, - // followed by the client's IP and the method:uri. - String() string + // SetID sets an ID, any value, to the Request Context. + // If possible the "id" should implement a `String() string` method + // so it can be rendered on `Context.String` method. + // + // See `GetID` and `middleware/requestid` too. + SetID(id interface{}) + // GetID returns the Request Context's ID. + // It returns nil if not given by a prior `SetID` call. + // See `middleware/requestid` too. + GetID() interface{} + // String returns the string representation of this request. + // + // It returns the Context's ID given by a `SetID`call, + // followed by the client's IP and the method:uri. + String() string } ``` diff --git a/Routing-middleware.md b/Routing-middleware.md index 6c94fe5..5573f24 100644 --- a/Routing-middleware.md +++ b/Routing-middleware.md @@ -166,19 +166,3 @@ Here is a list of some handlers made specifically for Iris: ## Third-Party Iris has its own middleware form of `func(ctx iris.Context)` but it's also compatible with all `net/http` middleware forms. See [here](https://github.com/kataras/iris/tree/master/_examples/convert-handlers). - -Here's a small list of useful third-party handlers: - -| Middleware | Description | -| -----------|-------------| -| [goth](https://github.com/markbates/goth) | OAuth, OAuth2 authentication. [Example](https://github.com/kataras/iris/tree/master/_examples/auth/goth) | -| [permissions2](https://github.com/xyproto/permissions2) | Cookies, users and permissions. [Example](https://github.com/kataras/iris/tree/master/_examples/auth/permissions) | -| [csp](https://github.com/awakenetworks/csp) | [Content Security Policy](https://www.w3.org/TR/CSP2/) (CSP) support | -| [delay](https://github.com/jeffbmartinez/delay) | Add delays/latency to endpoints. Useful when testing effects of high latency | -| [onthefly](https://github.com/xyproto/onthefly) | Generate TinySVG, HTML and CSS on the fly | -| [RestGate](https://github.com/pjebs/restgate) | Secure authentication for REST API endpoints | -| [stats](https://github.com/thoas/stats) | Store information about your web application (response time, etc.) | -| [VanGoH](https://github.com/auroratechnologies/vangoh) | Configurable [AWS-Style](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) HMAC authentication middleware | -| [digits](https://github.com/bamarni/digits) | Middleware that handles [Twitter Digits](https://get.digits.com/) authentication | - -> Feel free to put up your own middleware in this list! \ No newline at end of file