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]]