diff --git a/Home.md b/Home.md
index 7223508..72a3b62 100644
--- a/Home.md
+++ b/Home.md
@@ -40,6 +40,8 @@ This wiki is the main source of documentation for **developers** working with (o
* [[Websockets]]
* [[Dependency Injection|Dependency-Injection]]
* [[MVC]]
+* [[Sitemap]]
+* [[Localization]]
* [[Testing]]
* [➲ Examples](https://github.com/kataras/iris/tree/master/_examples)
* [[Starter Kits]]
diff --git a/Installation.md b/Installation.md
index 3352fbd..2e62941 100644
--- a/Installation.md
+++ b/Installation.md
@@ -21,19 +21,19 @@ module your_project_name
go 1.13
require (
- github.com/kataras/iris/v12 v12.0.1
+ github.com/kataras/iris/v12 v12.1.0
)
```
> `$ go build`
-## How to update
+
## Troubleshooting
diff --git a/Localization.md b/Localization.md
new file mode 100644
index 0000000..864ec92
--- /dev/null
+++ b/Localization.md
@@ -0,0 +1,283 @@
+## Introduction
+
+Localization features provide a convenient way to retrieve strings in various languages, allowing you to easily support multiple languages within your application. Language strings are stored in files within the `./locales` directory. Within this directory there should be a subdirectory for each language supported by the application:
+
+```sh
+│ main.go
+└───locales
+ ├───el-GR
+ │ home.yml
+ ├───en-US
+ │ home.yml
+ └───zh-CN
+ home.yml
+```
+
+The default language for your application is the first registered language.
+
+```go
+app := iris.New()
+
+// First parameter: Glob filpath patern,
+// Second variadic parameter: Optional language tags,
+// the first one is the default/fallback one.
+app.I18n.Load("./locales/*/*", "en-US", "el-GR", "zh-CN")
+```
+
+Or if you load all languages by:
+
+```go
+app.I18n.Load("./locales/*/*")
+```
+
+Then set the default language using:
+
+```go
+app.I18n.SetDefault("en-US")
+```
+
+### Load embedded locales
+
+You may want to embed locales with a go-bindata tool within your application executable.
+
+1. install a go-bindata tool, e.g.
+ `$ go get -u github.com/go-bindata/go-bindata/...`
+2. embed local files to your application
+ `$ go-bindata -o locales.go ./locales/...`
+3. use the `LoadAssets` method to initialize and load the languages
+ ^ The `AssetNames` and `Asset` functions are generated by `go-bindata`
+
+```go
+ap.I18n.LoadAssets(AssetNames, Asset, "en-US", "el-GR", "zh-CN")
+```
+
+## Defining Translations
+
+Each file should contain keys with translated text or template values.
+
+### Fmt Style
+
+```yaml
+hi: "Hi %s"
+```
+
+### Templates Style
+
+```yaml
+hi: "Hi {{ .Name }}"
+# Template functions are supported too
+# hi: "Hi {{sayHi .Name}}
+```
+
+### INI Sections
+
+```ini
+[cart]
+checkout = ολοκλήρωση παραγγελίας - {{.Param}}
+```
+> YAML, TOML, JSON, INI files.
+
+## Determining The Current Locale
+
+You may use the `context.GetLocale` method to determine the current locale or check if the locale is a given value:
+
+```go
+func(ctx iris.Context) {
+ locale := ctx.GetLocale()
+ // [...]
+}
+```
+
+The **Locale** interface looks like this.
+
+```go
+// Locale is the interface which returns from a `Localizer.GetLocale` metod.
+// It serves the transltions based on "key" or format. See `GetMessage`.
+type Locale interface {
+ // Index returns the current locale index from the languages list.
+ Index() int
+ // Tag returns the full language Tag attached tothis Locale,
+ // it should be uniue across different Locales.
+ Tag() *language.Tag
+ // Language should return the exact languagecode of this `Locale`
+ //that the user provided on `New` function.
+ //
+ // Same as `Tag().String()` but it's static.
+ Language() string
+ // GetMessage should return translated text based n the given "key".
+ GetMessage(key string, args ...interface{}) string
+}
+```
+
+## Retrieving Translation
+
+Use of `context.Tr` method as a shortcut to get a translated text for this request.
+
+```go
+func(ctx iris.Context) {
+ text := ctx.Tr("hi", "name")
+ // [...]
+}
+```
+
+### INI Sections
+
+INI Sections are separated by dot `"."`. The second optional value can be a `map` or a `struct` as the template value like the rest file formats.
+
+```go
+func(ctx iris.Context) {
+ text := ctx.Tr("cart.checkout", iris.Map{"Param": "a value"})
+ // [...]
+}
+```
+
+## Inside Views
+
+```go
+func(ctx iris.Context) {
+ ctx.View("index.html", iris.Map{
+ "tr": ctx.Tr,
+ })
+}
+```
+
+```html
+{{ call .tr "hi" "John Doe" }}
+```
+
+## [Example](https://github.com/kataras/iris/tree/master/_examples/i18n)
+
+```go
+package main
+
+import "github.com/kataras/iris/v12"
+
+func newApp() *iris.Application {
+ app := iris.New()
+
+ // Configure i18n.
+ // First parameter: Glob filpath patern,
+ // Second variadic parameter: Optional language tags,
+ // the first one is the default/fallback one.
+ app.I18n.Load("./locales/*/*.ini", "en-US", "el-GR", "zh-CN")
+ // app.I18n.LoadAssets for go-bindata.
+
+ // Default values:
+ // app.I18n.URLParameter = "lang"
+ // app.I18n.Subdomain = true
+ //
+ // Set to false to disallow path (local) redirects,
+ // see https://github.com/kataras/iris/issues/1369.
+ // app.I18n.PathRedirect = true
+
+ app.Get("/", func(ctx iris.Context) {
+ hi := ctx.Tr("hi", "iris")
+
+ locale := ctx.GetLocale()
+
+ ctx.Writef("From the language %s translated output: %s", locale.Language(), hi)
+ })
+
+ app.Get("/some-path", func(ctx iris.Context) {
+ ctx.Writef("%s", ctx.Tr("hi", "iris"))
+ })
+
+ app.Get("/multi", func(ctx iris.Context) {
+ language := ctx.GetLocale().Language()
+
+ fromFirstFileValue := ctx.Tr("key1")
+ fromSecondFileValue := ctx.Tr("key2")
+ ctx.Writef("From the language: %s,
+ translated output:\n%s=%s\n%s=%s",
+ language, "key1", fromFirstFileValue,
+ "key2", fromSecondFileValue)
+ })
+
+ // using in inside your views:
+ view := iris.HTML("./views", ".html")
+ app.RegisterView(view)
+
+ app.Get("/templates", func(ctx iris.Context) {
+ ctx.View("index.html", iris.Map{
+ "tr": ctx.Tr, // word, arguments... {call .tr "hi" "iris"}}
+ })
+
+ // Note that,
+ // Iris automatically adds a "tr" global
+ // template function as well,
+ // the only differene is the way you call
+ // it inside your templates and
+ // that it accepts a language code as
+ // its first argument: {{ tr "el-GR" "hi" "iris"}}
+ })
+ //
+
+ return app
+}
+
+func main() {
+ app := newApp()
+
+ // go to http://localhost:8080/el-gr/some-path
+ // ^ (by path prefix)
+ //
+ // or http://el.mydomain.com8080/some-path
+ // ^ (by subdomain - test locally with the hosts file)
+ //
+ // or http://localhost:8080/zh-CN/templates
+ // ^ (by path prefix with uppercase)
+ //
+ // or http://localhost:8080/some-path?lang=el-GR
+ // ^ (by url parameter)
+ //
+ // or http://localhost:8080 (default is en-US)
+ // or http://localhost:8080/?lang=zh-CN
+ //
+ // go to http://localhost:8080/multi?lang=el-GR
+ // or http://localhost:8080/multi (default is en-US)
+ // or http://localhost:8080/multi?lang=en-US
+ //
+ // or use cookies to set the language.
+ app.Run(iris.Addr(":8080"), iris.WithSitemap("http://localhost:8080"))
+}
+```
+
+## Sitemap
+
+[[Sitemap]] translations are automatically set to each route by path prefix if `app.I18n.PathRedirect` is true or by subdomain if `app.I18n.Subdomain` is true or by URL query parameter if `app.I18n.URLParameter` is not empty.
+
+Read more at: https://support.google.com/webmasters/answer/189077?hl=en
+
+```sh
+GET http://localhost:8080/sitemap.xml
+```
+
+```xml
+
+
+
+ http://localhost:8080/
+
+
+
+
+
+ http://localhost:8080/some-path
+
+
+
+
+
+ http://localhost:8080/multi
+
+
+
+
+
+ http://localhost:8080/templates
+
+
+
+
+
+```
\ No newline at end of file
diff --git a/Publications.md b/Publications.md
index 9a7aaec..45010d0 100644
--- a/Publications.md
+++ b/Publications.md
@@ -13,7 +13,6 @@ Prepare a cup of coffee or tea, whatever pleases you the most, and read some art
* [Iris Go Framework + MongoDB](https://bit.ly/2WDOsZF)
* [How to build a file upload form using DropzoneJS and Go](https://bit.ly/2ygMMqn)
* [How to display existing files on server using DropzoneJS and Go](https://bit.ly/2yjrckQ)
-* [Iris, a modular web framework](https://bit.ly/2KHm6q0)
* [Go vs .NET Core in terms of HTTP performance](https://bit.ly/2Kh7ezl)
* [Iris Go vs .NET Core Kestrel in terms of HTTP performance](https://bit.ly/2yo2v6J)
* [How to Turn an Android Device into a Web Server](https://bit.ly/2Icl5EM)
diff --git a/Routing-context-methods.md b/Routing-context-methods.md
index d7f6874..1ea266a 100644
--- a/Routing-context-methods.md
+++ b/Routing-context-methods.md
@@ -3,902 +3,900 @@
Here is a full list of methods that the `iris.Context` provides.
```go
-type (
- // BodyDecoder is an interface which any struct can implement in order to customize the decode action
- // from ReadJSON and ReadXML
- //
- // Trivial example of this could be:
- // type User struct { Username string }
- //
- // func (u *User) Decode(data []byte) error {
- // return json.Unmarshal(data, u)
- // }
- //
- // the 'context.ReadJSON/ReadXML(&User{})' will call the User's
- // Decode option to decode the request body
- //
- // Note: This is totally optionally, the default decoders
- // for ReadJSON is the encoding/json and for ReadXML is the encoding/xml.
- BodyDecoder interface {
- Decode(data []byte) error
- }
-
- // Unmarshaler is the interface implemented by types that can unmarshal any raw data.
- // TIP INFO: Any pointer to a value which implements the BodyDecoder can be override the unmarshaler.
- Unmarshaler interface {
- Unmarshal(data []byte, outPtr interface{}) error
- }
-
- // UnmarshalerFunc a shortcut for the Unmarshaler interface
- //
- // See 'Unmarshaler' and 'BodyDecoder' for more.
- UnmarshalerFunc func(data []byte, outPtr interface{}) error
-)
-
-// Unmarshal parses the X-encoded data and stores the result in the value pointed to by v.
-// Unmarshal uses the inverse of the encodings that Marshal uses, allocating maps,
-// slices, and pointers as necessary.
-func (u UnmarshalerFunc) Unmarshal(data []byte, v interface{}) error {
- return u(data, v)
-}
-
-// Context is the midle-man server's "object" for the clients.
-//
-// A New context is being acquired from a sync.Pool on each connection.
-// The Context is the most important thing on the iris's http flow.
-//
-// Developers send responses to the client's request through a Context.
-// Developers get request information from the client's request a Context.
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.
- //
- // To follow the iris' flow, developer should:
- // 1. reset handlers to nil
- // 2. reset values to empty
- // 3. reset sessions to nil
- // 4. reset response writer to the http.ResponseWriter
- // 5. reset request to the *http.Request
- // and any other optional steps, depends on dev's application type.
- BeginRequest(http.ResponseWriter, *http.Request)
- // EndRequest is executing once after a response to the request was sent and this context is useless or released.
- //
- // To follow the iris' flow, developer should:
- // 1. flush the response writer's result
- // 2. release the response writer
- // and any other optional steps, depends on dev's application type.
- EndRequest()
+ // 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)
+ // SetCurrentRouteName sets the route's name internally,
+ // in order to be able to find the correct current "read-only" Route when
+ // end-developer calls the `GetCurrentRoute()` function.
+ // It's being initialized by the Router, if you change that name
+ // manually nothing really happens except that you'll get other
+ // route via `GetCurrentRoute()`.
+ // Instead, to execute a different path
+ // from this context you should use the `Exec` function
+ // or change the handlers via `SetHandlers/AddHandler` functions.
+ SetCurrentRouteName(currentRouteName string)
+ // GetCurrentRoute returns the current registered "read-only" route that
+ // was being registered to this request's path.
+ GetCurrentRoute() RouteReadOnly
- // SetCurrentRouteName sets the route's name internally,
- // in order to be able to find the correct current "read-only" Route when
- // end-developer calls the `GetCurrentRoute()` function.
- // It's being initialized by the Router, if you change that name
- // manually nothing really happens except that you'll get other
- // route via `GetCurrentRoute()`.
- // Instead, to execute a different path
- // from this context you should use the `Exec` function
- // or change the handlers via `SetHandlers/AddHandler` functions.
- SetCurrentRouteName(currentRouteName string)
- // GetCurrentRoute returns the current registered "read-only" route that
- // was being 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 -1 passed 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 if called then the following .Next calls are ignored,
+ // as a result the next handlers in the chain will not be fire.
+ StopExecution()
+ // IsStopped checks and returns true if the current position of the Context is 255,
+ // means that the StopExecution() was called.
+ IsStopped() bool
+ // 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.
+ //
+ // Look the `Context#OnConnectionClose` and `ResponseWriter#SetBeforeFlush` for more.
+ OnClose(cb func())
- // HandlerIndex sets the current index of the
- // current context's handlers chain.
- // If -1 passed 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 iris.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 if called then the following .Next calls are ignored,
- // as a result the next handlers in the chain will not be fire.
- StopExecution()
- // IsStopped checks and returns true if the current position of the Context is 255,
- // means that the StopExecution() was called.
- IsStopped() bool
- // 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.
- //
- // 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
- // Translate is the i18n (localization) middleware's function,
- // it calls the Values().Get(ctx.Application().ConfigurationReadOnly().GetTranslateFunctionContextKey())
- // to execute the translate function and return the localized text value.
- //
- // Example: https://github.com/kataras/iris/tree/master/_examples/miscellaneous/i18n
- Translate(format string, args ...interface{}) string
+ // +------------------------------------------------------------+
+ // | Path, Host, Subdomain, IP, Headers, Localization etc... |
+ // +------------------------------------------------------------+
- // +------------------------------------------------------------+
- // | Path, Host, Subdomain, IP, Headers 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.
+ 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)
+ // 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(...)` for more.
+ RemoteAddr() string
+ // GetHeader returns the request header's value based on its name.
+ GetHeader(name string) 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
+ // GetReferrer extracts and returns the information from the "Referer" header as specified
+ // in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
+ // or by the URL query parameter "referer".
+ GetReferrer() Referrer
+ // 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
- // 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)
- // 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(...)` for more.
- RemoteAddr() string
- // GetHeader returns the request header's value based on its name.
- GetHeader(name string) 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
- // GetReferrer extracts and returns the information from the "Referer" header as specified
- // in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
- // or by the URL query parameter "referer".
- GetReferrer() Referrer
- // +------------------------------------------------------------+
- // | Headers helpers |
- // +------------------------------------------------------------+
+ // +------------------------------------------------------------+
+ // | 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
- // 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)
+ // 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 |
+ // +------------------------------------------------------------+
- // +------------------------------------------------------------+
- // | 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
- // URLParamTrim 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
+ // PostValueInt64Default 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)
+ // PostValueInt64Default 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
+ // PostValueInt64Default 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/http_request/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/http_request/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
- // PostValueInt64Default 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)
- // PostValueInt64Default 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
- // PostValueInt64Default 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/http_request/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/http_request/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 iris.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/http_request/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/http_request/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/http_request/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/http_request/read-yaml/main.go
+ ReadYAML(outPtr interface{}) error
+ // ReadForm binds the formObject with the form data
+ // it supports any kind of type, including custom structs.
+ // It will return nothing if request data are empty.
+ // The struct field tag is "form".
+ //
+ // Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-form/main.go
+ ReadForm(formObject interface{}) error
+ // ReadQuery binds the "ptr" with the url query string. The struct field tag is "url".
+ //
+ // Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-query/main.go
+ ReadQuery(ptr interface{}) error
+ // +------------------------------------------------------------+
+ // | Body (raw) Writers |
+ // +------------------------------------------------------------+
- // 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/http_request/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/http_request/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/http_request/read-xml/main.go
- ReadXML(xmlObjectPtr interface{}) error
- // ReadForm binds the formObject with the form data
- // it supports any kind of type, including custom structs.
- // It will return nothing if request data are empty.
- // The struct field tag is "form".
- //
- // Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-form/main.go
- ReadForm(formObject interface{}) error
- // ReadQuery binds the "ptr" with the url query string. The struct field tag is "url".
- //
- // Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-query/main.go
- ReadQuery(ptr interface{}) error
- // +------------------------------------------------------------+
- // | 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`.
- //
- // 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)
- // +------------------------------------------------------------+
- // | 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)
+ // +------------------------------------------------------------+
+ // | 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)
- // 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.
- XML(v interface{}, options ...XML) (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)
- // +------------------------------------------------------------+
- // | Serve files |
- // +------------------------------------------------------------+
+ // +-----------------------------------------------------------------------+
+ // | Content Νegotiation |
+ // | https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation | |
+ // +-----------------------------------------------------------------------+
- // ServeContent serves content, headers are autoset
- // receives three parameters, it's low-level function, instead you can use .ServeFile(string,bool)/SendFile(string,string)
- //
- //
- // You can define your own "Content-Type" with `context#ContentType`, before this function call.
- //
- // This function doesn't support resuming (by range),
- // use ctx.SendFile or router's `HandleDir` instead.
- ServeContent(content io.ReadSeeker, filename string, modtime time.Time, gzipCompression bool) error
- // ServeFile serves a file (to send a file, a zip for example to the client you should use the `SendFile` instead)
- // receives two parameters
- // filename/path (string)
- // gzipCompression (bool)
- //
- // You can define your own "Content-Type" with `context#ContentType`, before this function call.
- //
- // This function doesn't support resuming (by range),
- // use ctx.SendFile or router's `HandleDir` instead.
- //
- // Use it when you want to serve dynamic files to the client.
- ServeFile(filename string, gzipCompression bool) error
- // SendFile sends file for force-download to the client
- //
- // Use this instead of ServeFile to 'force-download' bigger files to the client.
- SendFile(filename string, destinationName string) 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)
- // +------------------------------------------------------------+
- // | Cookies |
- // +------------------------------------------------------------+
+ // +------------------------------------------------------------+
+ // | Serve files |
+ // +------------------------------------------------------------+
- // 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)
- // 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))
+ // ServeContent serves content, headers are autoset
+ // receives three parameters, it's low-level function, instead you can use .ServeFile(string,bool)/SendFile(string,string)
+ //
+ //
+ // You can define your own "Content-Type" with `context#ContentType`, before this function call.
+ //
+ // This function doesn't support resuming (by range),
+ // use ctx.SendFile or router's `HandleDir` instead.
+ ServeContent(content io.ReadSeeker, filename string, modtime time.Time, gzipCompression bool) error
+ // ServeFile serves a file (to send a file, a zip for example to the client you should use the `SendFile` instead)
+ // receives two parameters
+ // filename/path (string)
+ // gzipCompression (bool)
+ //
+ // You can define your own "Content-Type" with `context#ContentType`, before this function call.
+ //
+ // This function doesn't support resuming (by range),
+ // use ctx.SendFile or router's `HandleDir` instead.
+ //
+ // Use it when you want to serve dynamic files to the client.
+ ServeFile(filename string, gzipCompression bool) error
+ // SendFile sends file for force-download to the client
+ //
+ // Use this instead of ServeFile to 'force-download' bigger files to the client.
+ SendFile(filename string, destinationName string) error
- // 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
+ // +------------------------------------------------------------+
+ // | Cookies |
+ // +------------------------------------------------------------+
- // +------------------------------------------------------------+
- // | Advanced: Response Recorder and Transactions |
- // +------------------------------------------------------------+
+ // 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)
+ // 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))
- // 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)
+ // 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
- // 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
+ // +------------------------------------------------------------+
+ // | Advanced: Response Recorder and Transactions |
+ // +------------------------------------------------------------+
- // 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)
+ // 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)
- // 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
+ // 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
- // 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
+ // 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)
- // String returns the string representation of this request.
- // Each context has a unique string representation.
- // It can be used for simple debugging scenarios, i.e print context as string.
- //
- // What it returns? A number which declares the length of the
- // total `String` calls per executable application, followed
- // by the remote IP (the client) and finally the method:url.
- String() 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
+
+ // 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
+
+ // String returns the string representation of this request.
+ // Each context has a unique string representation.
+ // It can be used for simple debugging scenarios, i.e print context as string.
+ //
+ // What it returns? A number which declares the length of the
+ // total `String` calls per executable application, followed
+ // by the remote IP (the client) and finally the method:url.
+ String() string
}
```
diff --git a/Routing-middleware.md b/Routing-middleware.md
index b3ce6e7..9cf527c 100644
--- a/Routing-middleware.md
+++ b/Routing-middleware.md
@@ -136,7 +136,6 @@ Here is a list of some handlers made specifically for Iris:
| Middleware | Example |
| -----------|-------------|
| [basic authentication](https://github.com/kataras/iris/tree/master/middleware/basicauth) | [iris/_examples/authentication/basicauth](https://github.com/kataras/iris/tree/master/_examples/authentication/basicauth) |
-| [localization and internationalization](https://github.com/kataras/iris/tree/master/middleware/i18n) | [iris/_examples/miscellaneous/i81n](https://github.com/kataras/iris/tree/master/_examples/miscellaneous/i18n) |
| [request logger](https://github.com/kataras/iris/tree/master/middleware/logger) | [iris/_examples/http_request/request-logger](https://github.com/kataras/iris/tree/master/_examples/http_request/request-logger) |
| [HTTP method override](https://github.com/kataras/iris/tree/master/middleware/methodoverride) | [iris/middleware/methodoverride/methodoverride_test.go](https://github.com/kataras/iris/blob/master/middleware/methodoverride/methodoverride_test.go) |
| [profiling (pprof)](https://github.com/kataras/iris/tree/master/middleware/pprof) | [iris/_examples/miscellaneous/pprof](https://github.com/kataras/iris/tree/master/_examples/miscellaneous/pprof) |
diff --git a/Sitemap.md b/Sitemap.md
new file mode 100644
index 0000000..807aff8
--- /dev/null
+++ b/Sitemap.md
@@ -0,0 +1,24 @@
+Iris provides extensive support for the Sitemap Protocol which automatically generates [sitemap index](https://www.sitemaps.org/protocol.html#index) "/sitemap.xml" too.
+
+To enable sitemaps on your web application you should use the `iris.WithSitemap` Configurator. This function accepts the full scheme and domain of the exposed application.
+
+```go
+app := iris.New()
+// [...]
+
+app.Run(iris.Addr(":8080"), iris.WithSitemap("http://localhost:8080"))
+```
+
+The application will loop through registered _static_ routes and it will add each one of them to the sitemap file. By default only the `` XML element will be filled unless the route's fields `LastMod`, `ChangeFreq` or/and `Priority`[*](https://www.sitemaps.org/protocol.html) are set.
+
+```go
+app.Get("/home", handler).SetLastMod(time.Now()).SetChangeFreq("hourly").SetPriority(0.8)
+```
+
+> A static route is exposed on GET HTTP Method and its path does not contain a dynamic parameter. e.g. /home, /about but not /user/{id:uint64} and e.t.c.
+
+See it in action, download and run the **example** from: https://github.com/kataras/iris/tree/master/_examples/sitemap
+
+If the application **is localized** then `iris.WithSitemap` will add `xhtml:link` XML elements to the sitemap file for each translation language as recommended at: https://support.google.com/webmasters/answer/189077?hl=en. Read more about it at the [[Localization]] section.
+
+
diff --git a/View.md b/View.md
index 45e4c58..169a7ce 100644
--- a/View.md
+++ b/View.md
@@ -9,7 +9,7 @@ Let's see the list of the built-in view engines:
| Engine | Declaration | Underline Template Parser
| -----------|-------------|-------------|
| std template/html | `iris.HTML(...)` | [html/template](https://golang.org/pkg/html/template/) package |
-| django | `iris.Django(...)` | [flosch/pongo2](https://github.com/flosch/pongo2) package |
+| django | `iris.Django(...)` | [iris-contrib/pongo2](https://github.com/iris-contrib/pongo2) package |
| handlebars | `iris.Handlebars(...)` | [Joker/jade](https://github.com/Joker/jade) package |
| amber | `iris.Amber(...)` | [aymerick/raymond](https://github.com/aymerick/raymond) package |
| pug(jade) | `iris.Pug(...)` | [eknkc/amber](https://github.com/eknkc/amber) package |
diff --git a/_Sidebar.md b/_Sidebar.md
index 2b47942..82753c2 100644
--- a/_Sidebar.md
+++ b/_Sidebar.md
@@ -35,6 +35,8 @@
* [[Websockets]]
* [[Dependency Injection|Dependency-Injection]]
* [[MVC]]
+* [[Sitemap]]
+* [[Localization]]
* [[Testing]]
* [Examples](https://github.com/kataras/iris/tree/master/_examples)
* [[Starter Kits]]