-
-What The Community Says
+Iris developers around the world
-----------
[](https://www.youtube.com/watch?v=jGx0LkuUs4A)
[](https://www.youtube.com/watch?v=jGx0LkuUs4A)
-> [navigate here](https://www.youtube.com/watch?v=jGx0LkuUs4A) to view all Go Community's reactions.
+> [https://www.youtube.com/watch?v=jGx0LkuUs4A](https://www.youtube.com/watch?v=jGx0LkuUs4A)
-
-Feature Overview
+Installation
-----------
-- Focus on high performance
-- Highly customizable
-- HTTP/2 full support
-- Change the default Router's behavior
-- Hot Reload on source code changes
-- Compatible with all net/http handlers
-- Automatically install and serve certificates from https://letsencrypt.org
-- Robust routing and middleware ecosystem
-- Build RESTful APIs
-- Context Scoped Transactions
-- Group API's and subdomains with wildcard support
-- Body binding for JSON, XML, Forms, can be extended to use your own custom binders
-- More than 50 handy functions to send HTTP responses
-- View system: supporting more than 6+ template engines, with prerenders. You can still use your favorite
-- Define virtual hosts and (wildcard) subdomains with path level routing
-- Graceful shutdown
-- Limit request body
-- Localization i18N
-- Serve static files, directories and streams
-- Fast Cache System
-- Customizable format and output for the logger
-- Customizable HTTP errors
-- Compression (Gzip)
-- Authentication
- - OAuth, OAuth2 supporting 27+ popular websites
- - JWT
- - Basic Authentication
- - HTTP Sessions and flash messages
-- Add / Remove trailing slash from the URL with option to redirect
-- Redirect any request
-- Highly scalable rich content render (Markdown, JSON, JSONP, XML...)
-- Websocket API similar to socket.io
-- Typescript integration + Web IDE
-- Optional updater
-- Feels like you used iris forever, thanks to its Fluent API
-- And more...
-
-Quick Start
------------
+The only requirement is the [Go Programming Language](https://golang.org/dl/), at least v1.7.
```bash
-go get -u github.com/kataras/iris/iris
+$ go get -u github.com/kataras/iris/iris
```
-```sh
-cat hellojson.go
-```
-
-```go
-package main
-
-import "github.com/kataras/iris"
-
-func main(){
-
- // http://localhost:5700/api/user/42
- // Method: "GET"
- iris.Get("/api/user/:id", func(ctx *iris.Context){
-
- // take the :id from the path, parse to integer
- // and set it to the new userID local variable.
- userID,_ := ctx.ParamInt("id")
-
- // userRepo, imaginary database service <- your only job.
- user := userRepo.GetByID(userID)
-
- // send back a response to the client,
- // .JSON: content type as application/json; charset="utf-8"
- // iris.StatusOK: with 200 http status code.
- //
- // send user as it is or make use of any json valid golang type,
- // like the iris.Map{"username" : user.Username}.
- ctx.JSON(iris.StatusOK, user)
-
- })
-
- iris.Listen(":6000")
-}
-
-```
-
-```sh
-$ go run hellojson.go
-```
-> TIP: $ iris run main.go to enable hot-reload on .go source code changes.
-
-> TIP: iris.Config.IsDevelopment = true to monitor the changes you make in the templates.
-
-> TIP: Want to change the default Router's behavior to something else like Gorilla's Mux?
-Go [there](https://github.com/iris-contrib/examples/tree/master/plugin_gorillamux) to learn how.
-
-Open your browser or any other http client at http://localhost:6000/api/user/42.
-
-
-### New
-
-```go
-// New with default configuration
-app := iris.New()
-
-app.Listen(....)
-
-// New with configuration struct
-app := iris.New(iris.Configuration{ IsDevelopment: true})
-
-app.Listen(...)
-
-// Default station
-iris.Listen(...)
-
-// Default station with custom configuration
-// view the whole configuration at: ./configuration.go
-iris.Config.IsDevelopment = true
-iris.Config.Charset = "UTF-8"
-
-iris.Listen(...)
-```
-
-### Listening
-`Serve(ln net.Listener) error`
-```go
-ln, err := net.Listen("tcp4", ":8080")
-if err := iris.Serve(ln); err != nil {
- panic(err)
-}
-```
-`Listen(addr string)`
-```go
-iris.Listen(":8080")
-```
-`ListenTLS(addr string, certFile, keyFile string)`
-```go
-iris.ListenTLS(":8080", "./ssl/mycert.cert", "./ssl/mykey.key")
-```
-`ListenLETSENCRYPT(addr string, cacheFileOptional ...string)`
-```go
-iris.ListenLETSENCRYPT("mydomain.com")
-```
-```go
-iris.Serve(iris.LETSENCRYPTPROD("myproductionwebsite.com"))
-```
-
-And
-
-```go
-ListenUNIX(addr string, mode os.FileMode)
-Close() error
-Reserve() error
-IsRunning() bool
-```
-
-### Routing
-
-```go
-iris.Get("/products/:id", getProduct)
-iris.Post("/products", saveProduct)
-iris.Put("products/:id", editProduct)
-iris.Delete("/products/:id", deleteProduct)
-```
-
-And
-
-```go
-iris.Patch("", ...)
-iris.Connect("", ...)
-iris.Options("", ...)
-iris.Trace("", ...)
-```
-
-### Path Parameters
-
-```go
-func getProduct(ctx *iris.Context){
- // Get id from path '/products/:id'
- id := ctx.Param("id")
-}
-
-```
-
-### Query Parameters
-
-`/details?color=blue&weight=20`
-
-```go
-func details(ctx *iris.Context){
- color := ctx.URLParam("color")
- weight,_ := ctx.URLParamInt("weight")
-}
-
-```
-
-### Form `application/x-www-form-urlencoded`
-
-`METHOD: POST | PATH: /save`
-
-name | value
-:--- | :---
-name | Gerasimos Maropoulos
-email | kataras2006@homail.com
-
-
-```go
-func save(ctx *iris.Context) {
- // Get name and email
- name := ctx.FormValue("name")
- email := ctx.FormValue("email")
-}
-```
-
-### Form `multipart/form-data`
-
-`POST` `/save`
-
-name | value
-:--- | :---
-name | Gerasimos Maropoulos
-email | kataras2006@hotmail.com
-avatar | avatar
-
-```go
-func save(ctx *iris.Context) {
- // Get name and email
- name := ctx.FormValue("name")
- email := ctx.FormValue("email")
- // Get avatar
- avatar, info, err := ctx.FormFile("avatar")
- if err != nil {
- ctx.EmitError(iris.StatusInternalServerError)
- return
- }
-
- defer avatar.Close()
-
- // Destination
- dst, err := os.Create(avatar.Filename)
- if err != nil {
- ctx.EmitError(iris.StatusInternalServerError)
- return
- }
- defer dst.Close()
-
- // Copy
- if _, err = io.Copy(dst, avatar); err != nil {
- ctx.EmitError(iris.StatusInternalServerError)
- return
- }
-
- ctx.HTML(iris.StatusOK, "Thanks!")
-}
-```
-
-### Handling Request
-
-
-- Bind `JSON` or `XML` or `form` payload into Go struct based on `Content-Type` request header.
-- Render response as `JSON` or `XML` with status code.
-
-```go
-type User struct {
- Name string `json:"name" xml:"name" form:"name"`
- Email string `json:"email" xml:"email" form:"email"`
-}
-
-iris.Post("/users", func(ctx *iris.Context) {
- u := new(User)
- if err := ctx.ReadJSON(u); err != nil {
- ctx.EmitError(iris.StatusInternalServerError)
- return
- }
- ctx.JSON(iris.StatusCreated, u)
- // or
- // ctx.XML(iris.StatusCreated, u)
- // ctx.JSONP(...)
- // ctx.HTML(iris.StatusCreated, "Hi "+u.Name+"")
- // ctx.Markdown(iris.StatusCreated, "## Name: "+u.Name)
-})
-```
-
-
-| Name | Description | Usage |
-| ------------------|:---------------------:|-------:|
-| [JSON ](https://github.com/kataras/go-serializer/tree/master/json) | JSON Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/json_1/main.go),[example 2](https://github.com/iris-contrib/examples/blob/master/serialize_engines/json_2/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
-| [JSONP ](https://github.com/kataras/go-serializer/tree/master/jsonp) | JSONP Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/jsonp_1/main.go),[example 2](https://github.com/iris-contrib/examples/blob/master/serialize_engines/jsonp_2/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
-| [XML ](https://github.com/kataras/go-serializer/tree/master/xml) | XML Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/xml_1/main.go),[example 2](https://github.com/iris-contrib/examples/blob/master/serialize_engines/xml_2/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
-| [Markdown ](https://github.com/kataras/go-serializer/tree/master/markdown) | Markdown Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/markdown_1/main.go),[example 2](https://github.com/iris-contrib/examples/blob/master/serialize_engines/markdown_2/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
-| [Text](https://github.com/kataras/go-serializer/tree/master/text) | Text Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/text_1/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
-| [Binary Data ](https://github.com/kataras/go-serializer/tree/master/data) | Binary Data Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/data_1/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
-
-
-### HTTP Errors
-
-You can define your own handlers when http error occurs.
-
-```go
-package main
-
-import (
- "github.com/kataras/iris"
-)
-
-func main() {
-
- iris.OnError(iris.StatusInternalServerError, func(ctx *iris.Context) {
- ctx.Writef("CUSTOM 500 INTERNAL SERVER ERROR PAGE")
- // or ctx.Render, ctx.HTML any render method you want
- ctx.Log("http status: 500 happened!")
- })
-
- iris.OnError(iris.StatusNotFound, func(ctx *iris.Context) {
- ctx.Writef("CUSTOM 404 NOT FOUND ERROR PAGE")
- ctx.Log("http status: 404 happened!")
- })
-
- // emit the errors to test them
- iris.Get("/500", func(ctx *iris.Context) {
- ctx.EmitError(iris.StatusInternalServerError) // ctx.Panic()
- })
-
- iris.Get("/404", func(ctx *iris.Context) {
- ctx.EmitError(iris.StatusNotFound) // ctx.NotFound()
- })
-
- iris.Listen(":80")
-
-}
-
-
-```
-
-### Static Content
-
-Serve files or directories, use the correct for your case, if you don't know which one, just use the `StaticWeb(reqPath string, systemPath string)`.
-
-```go
-// Favicon serves static favicon
-// accepts 2 parameters, second is optional
-// favPath (string), declare the system directory path of the __.ico
-// requestPath (string), it's the route's path, by default this is the "/favicon.ico" because some browsers tries to get this by default first,
-// you can declare your own path if you have more than one favicon (desktop, mobile and so on)
-//
-// this func will add a route for you which will static serve the /yuorpath/yourfile.ico to the /yourfile.ico (nothing special that you can't handle by yourself)
-// Note that you have to call it on every favicon you have to serve automatically (desktop, mobile and so on)
-//
-// panics on error
-Favicon(favPath string, requestPath ...string) RouteNameFunc
-
-// StaticHandler returns a new Handler which serves static files
-StaticHandler(reqPath string, systemPath string, showList bool, enableGzip bool) HandlerFunc
-
-// StaticWeb same as Static but if index.html e
-// xists and request uri is '/' then display the index.html's contents
-// accepts three parameters
-// first parameter is the request url path (string)
-// second parameter is the system directory (string)
-StaticWeb(reqPath string, systemPath string) RouteNameFunc
-
-// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
-// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
-// Second parameter is the (virtual) directory path, for example "./assets"
-// Third parameter is the Asset function
-// Forth parameter is the AssetNames function
-//
-// For more take a look at the
-// example: https://github.com/iris-contrib/examples/tree/master/static_files_embedded
-StaticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) RouteNameFunc
-
-// StaticContent serves bytes, memory cached, on the reqPath
-// a good example of this is how the websocket server uses that to auto-register the /iris-ws.js
-StaticContent(reqPath string, cType string, content []byte) RouteNameFunc
-
-// StaticServe serves a directory as web resource
-// it's the simpliest form of the Static* functions
-// Almost same usage as StaticWeb
-// accepts only one required parameter which is the systemPath
-// (the same path will be used to register the GET&HEAD routes)
-// if the second parameter is empty, otherwise the requestPath is the second parameter
-// it uses gzip compression (compression on each request, no file cache)
-StaticServe(systemPath string, requestPath ...string)
-
-```
-
-```go
-iris.StaticWeb("/public", "./static/assets/")
-//-> /public/assets/favicon.ico
-```
-
-```go
-iris.StaticWeb("/","./my_static_html_website")
-```
-
-```go
-context.StaticServe(systemPath string, requestPath ...string)
-```
-
-#### Manual static file serving
-
-```go
-// ServeFile serves a view file, to send a file
-// to the client you should use the SendFile(serverfilename,clientfilename)
-// receives two parameters
-// filename/path (string)
-// gzipCompression (bool)
-//
-// You can define your own "Content-Type" header also, after this function call
-context.ServeFile(filename string, gzipCompression bool) error
-```
-
-Serve static individual file
-
-```go
-
-iris.Get("/txt", func(ctx *iris.Context) {
- ctx.ServeFile("./myfolder/staticfile.txt", false)
-}
-```
-
-### Templates
-
-**HTML Template Engine, defaulted**
-
-
-```html
-
-
-
-
-Hi Iris
-
-
-
Hi {{.Name}}
-
-
-```
-
-```go
-// file ./main.go
-package main
-
-import "github.com/kataras/iris"
-
-func main() {
- iris.Config.IsDevelopment = true // this will reload the templates on each request
- iris.Get("/hi", hi)
- iris.Listen(":8080")
-}
-
-func hi(ctx *iris.Context) {
- ctx.MustRender("hi.html", struct{ Name string }{Name: "iris"})
-}
-
-```
-
-| Name | Description | Usage |
-| ------------------|:---------------------:|-------:|
-| [HTML/Default Engine ](https://github.com/kataras/go-template/tree/master/html) | HTML Template Engine (Default) |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_html_0/main.go), [book section](https://docs.iris-go.com/template-engines.html)
-| [Django Engine ](https://github.com/kataras/go-template/tree/master/django) | Django Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_django_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
-| [Pug/Jade Engine ](https://github.com/kataras/go-template/tree/master/pug) | Pug Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_pug_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
-| [Handlebars Engine ](https://github.com/kataras/go-template/tree/master/handlebars) | Handlebars Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_handlebars_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
-| [Amber Engine ](https://github.com/kataras/go-template/tree/master/amber) | Amber Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_amber_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
-| [Markdown Engine ](https://github.com/kataras/go-template/tree/master/markdown) | Markdown Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_markdown_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
-
-> Each section of the README has its own - more advanced - subject on the book, so be sure to check book for any further research
-
-[Read more](https://docs.iris-go.com/template-engines.html)
-
-### Middleware ecosystem
-
-
-```go
-
-import (
- "github.com/iris-contrib/middleware/logger"
- "github.com/iris-contrib/middleware/cors"
- "github.com/iris-contrib/middleware/basicauth"
-)
-// Root level middleware
-iris.Use(logger.New())
-iris.Use(cors.Default())
-
-// Group level middleware
-authConfig := basicauth.Config{
- Users: map[string]string{"myusername": "mypassword", "mySecondusername": "mySecondpassword"},
- Realm: "Authorization Required", // if you don't set it it's "Authorization Required"
- ContextKey: "mycustomkey", // if you don't set it it's "user"
- Expires: time.Duration(30) * time.Minute,
-}
-
-authentication := basicauth.New(authConfig)
-
-g := iris.Party("/admin")
-g.Use(authentication)
-
-// Route level middleware
-logme := func(ctx *iris.Context) {
- println("request to /products")
- ctx.Next()
-}
-iris.Get("/products", logme, func(ctx *iris.Context) {
- ctx.Text(iris.StatusOK, "/products")
-})
-```
-
-
-| Name | Description | Usage |
-| ------------------|:---------------------:|-------:|
-| [Basicauth Middleware ](https://github.com/iris-contrib/middleware/tree/master/basicauth) | HTTP Basic authentication |[example 1](https://github.com/iris-contrib/examples/blob/master/middleware_basicauth_1/main.go), [example 2](https://github.com/iris-contrib/examples/blob/master/middleware_basicauth_2/main.go), [book section](https://docs.iris-go.com/basic-authentication.html) |
-| [JWT Middleware ](https://github.com/iris-contrib/middleware/tree/master/jwt) | JSON Web Tokens |[example ](https://github.com/iris-contrib/examples/blob/master/middleware_jwt/main.go), [book section](https://docs.iris-go.com/jwt.html) |
-| [Cors Middleware ](https://github.com/iris-contrib/middleware/tree/master/cors) | Cross Origin Resource Sharing W3 specification | [how to use ](https://github.com/iris-contrib/middleware/tree/master/cors#how-to-use) |
-| [Secure Middleware ](https://github.com/iris-contrib/middleware/tree/master/secure) | Facilitates some quick security wins | [example](https://github.com/iris-contrib/examples/blob/master/middleware_secure/main.go) |
-| [I18n Middleware ](https://github.com/iris-contrib/middleware/tree/master/i18n) | Simple internationalization | [example](https://github.com/iris-contrib/examples/tree/master/middleware_internationalization_i18n), [book section](https://docs.iris-go.com/middleware-internationalization-and-localization.html) |
-| [Recovery Middleware ](https://github.com/iris-contrib/middleware/tree/master/recovery) | Safety recover the station from panic | [example](https://github.com/iris-contrib/examples/blob/master/middleware_recovery/main.go) |
-| [Logger Middleware ](https://github.com/iris-contrib/middleware/tree/master/logger) | Logs every request | [example](https://github.com/iris-contrib/examples/blob/master/middleware_logger/main.go), [book section](https://docs.iris-go.com/logger.html) |
-| [LoggerZap Middleware ](https://github.com/iris-contrib/middleware/tree/master/loggerzap) | Logs every request using zap | [example](https://github.com/iris-contrib/examples/blob/master/middleware_logger/main.go), [book section](https://docs.iris-go.com/logger.html) |
-| [Profile Middleware ](https://github.com/iris-contrib/middleware/tree/master/pprof) | Http profiling for debugging | [example](https://github.com/iris-contrib/examples/blob/master/middleware_pprof/main.go) |
-| [Editor Plugin](https://github.com/iris-contrib/plugin/tree/master/editor) | Alm-tools, a typescript online IDE/Editor | [book section](https://docs.iris-go.com/plugin-editor.html) |
-| [Typescript Plugin](https://github.com/iris-contrib/plugin/tree/master/typescript) | Auto-compile client-side typescript files | [book section](https://docs.iris-go.com/plugin-typescript.html) |
-| [OAuth,OAuth2 Plugin](https://github.com/iris-contrib/plugin/tree/master/oauth) | User Authentication was never be easier, supports >27 providers | [example](https://github.com/iris-contrib/examples/tree/master/plugin_oauth_oauth2), [book section](https://docs.iris-go.com/plugin-oauth.html) |
-| [Iris control Plugin](https://github.com/iris-contrib/plugin/tree/master/iriscontrol) | Basic (browser-based) control over your Iris station | [example](https://github.com/iris-contrib/examples/blob/master/plugin_iriscontrol/main.go), [book section](https://docs.iris-go.com/plugin-iriscontrol.html) |
-
-> NOTE: All net/http handlers and middleware that already created by other go developers are also compatible with Iris, even if they are not be documented here, read more [here](https://github.com/iris-contrib/middleware#can-i-use-standard-nethttp-handler-with-iris).
-
-
-### Sessions
-If you notice a bug or issue [post it here](https://github.com/kataras/go-sessions).
-
-
-- Cleans the temp memory when a session is idle, and re-allocates it to the temp memory when it's necessary.
-The most used sessions are optimized to be in the front of the memory's list.
-
-- Supports any type of database, currently only [Redis](https://github.com/kataras/go-sessions/tree/master/sessiondb/redis) and [LevelDB](https://github.com/kataras/go-sessions/tree/master/sessiondb/leveldb).
-
-
-**A session can be defined as a server-side storage of information that is desired to persist throughout the user's interaction with the web application**.
-
-Instead of storing large and constantly changing data via cookies in the user's browser (i.e. CookieStore),
-**only a unique identifier is stored on the client side** called a "session id".
-This session id is passed to the web server on every request.
-The web application uses the session id as the key for retrieving the stored data from the database/memory. The session data is then available inside the iris.Context.
-
-```go
-iris.Get("/", func(ctx *iris.Context) {
- ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
- })
-
- iris.Get("/set", func(ctx *iris.Context) {
-
- //set session values
- ctx.Session().Set("name", "iris")
-
- //test if setted here
- ctx.Writef("All ok session setted to: %s", ctx.Session().GetString("name"))
- })
-
- iris.Get("/get", func(ctx *iris.Context) {
- // get a specific key as a string.
- // returns an empty string if the key was not found.
- name := ctx.Session().GetString("name")
-
- ctx.Writef("The name on the /set was: %s", name)
- })
-
- iris.Get("/delete", func(ctx *iris.Context) {
- // delete a specific key
- ctx.Session().Delete("name")
- })
-
- iris.Get("/clear", func(ctx *iris.Context) {
- // removes all entries
- ctx.Session().Clear()
- })
-
- iris.Get("/destroy", func(ctx *iris.Context) {
- // destroy/removes the entire session and cookie
- ctx.SessionDestroy()
- ctx.Log("You have to refresh the page to completely remove the session (on browsers), so the name should NOT be empty NOW, is it?\n ame: %s\n\nAlso check your cookies in your browser's cookies, should be no field for localhost/127.0.0.1 (or whatever you use)", ctx.Session().GetString("name"))
- ctx.Writef("You have to refresh the page to completely remove the session (on browsers), so the name should NOT be empty NOW, is it?\nName: %s\n\nAlso check your cookies in your browser's cookies, should be no field for localhost/127.0.0.1 (or whatever you use)", ctx.Session().GetString("name"))
- })
-
- iris.Listen(":8080")
-
-```
-
-- `iris.DestroySessionByID(string)`
-
-```go
-// DestroySessionByID removes the session entry
-// from the server-side memory (and database if registered).
-// Client's session cookie will still exist but it will be reseted on the next request.
-//
-// It's safe to use it even if you are not sure if a session with that id exists.
-DestroySessionByID(string)
-```
-
-- `iris.DestroyAllSessions()`
-
-```go
-// DestroyAllSessions removes all sessions
-// from the server-side memory (and database if registered).
-// Client's session cookie will still exist but it will be reseted on the next request.
-DestroyAllSessions()
-```
-
-> Each section of the README has its own - more advanced - subject on the book, so be sure to check book for any further research
-
-[Read more](https://docs.iris-go.com/package-sessions.html)
-
-### Websockets
-
-Server configuration
-
-```go
-iris.Config.Websocket{
- // WriteTimeout time allowed to write a message to the connection.
- // Default value is 15 * time.Second
- WriteTimeout time.Duration
- // PongTimeout allowed to read the next pong message from the connection
- // Default value is 60 * time.Second
- PongTimeout time.Duration
- // PingPeriod send ping messages to the connection with this period. Must be less than PongTimeout
- // Default value is (PongTimeout * 9) / 10
- PingPeriod time.Duration
- // MaxMessageSize max message size allowed from connection
- // Default value is 1024
- MaxMessageSize int64
- // BinaryMessages set it to true in order to denotes binary data messages instead of utf-8 text
- // see https://github.com/kataras/iris/issues/387#issuecomment-243006022 for more
- // Defaults to false
- BinaryMessages bool
- // Endpoint is the path which the websocket server will listen for clients/connections
- // Default value is empty string, if you don't set it the Websocket server is disabled.
- Endpoint string
- // ReadBufferSize is the buffer size for the underline reader
- ReadBufferSize int
- // WriteBufferSize is the buffer size for the underline writer
- WriteBufferSize int
- // Error specifies the function for generating HTTP error responses.
- //
- // The default behavior is to store the reason in the context (ctx.Set(reason)) and fire any custom error (ctx.EmitError(status))
- Error func(ctx *Context, status int, reason error)
- // CheckOrigin returns true if the request Origin header is acceptable. If
- // CheckOrigin is nil, the host in the Origin header must not be set or
- // must match the host of the request.
- //
- // The default behavior is to allow all origins
- // you can change this behavior by setting the iris.Config.Websocket.CheckOrigin = iris.WebsocketCheckSameOrigin
- CheckOrigin func(r *http.Request) bool
- // IDGenerator used to create (and later on, set)
- // an ID for each incoming websocket connections (clients).
- // If empty then the ID is generated by the result of 64
- // random combined characters
- IDGenerator func(r *http.Request) string
-}
-
-```
-
-Connection's methods
-
-```go
-ID() string
-
-Request() *http.Request
-
-// Receive from the client
-On("anyCustomEvent", func(message string) {})
-On("anyCustomEvent", func(message int){})
-On("anyCustomEvent", func(message bool){})
-On("anyCustomEvent", func(message anyCustomType){})
-On("anyCustomEvent", func(){})
-
-// Receive a native websocket message from the client
-// compatible without need of import the iris-ws.js to the .html
-OnMessage(func(message []byte){})
-
-// Send to the client
-Emit("anyCustomEvent", string)
-Emit("anyCustomEvent", int)
-Emit("anyCustomEvent", bool)
-Emit("anyCustomEvent", anyCustomType)
-
-// Send native websocket messages
-// with config.BinaryMessages = true
-// useful when you use proto or something like this.
-EmitMessage([]byte("anyMessage"))
-
-// Send to specific client(s)
-To("otherConnectionId").Emit/EmitMessage...
-To("anyCustomRoom").Emit/EmitMessage...
-
-// Send to all opened connections/clients
-To(websocket.All).Emit/EmitMessage...
-
-// Send to all opened connections/clients EXCEPT this client
-To(websocket.Broadcast).Emit/EmitMessage...
-
-// Rooms, group of connections/clients
-Join("anyCustomRoom")
-Leave("anyCustomRoom")
-
-
-// Fired when the connection is closed
-OnDisconnect(func(){})
-
-// Force-disconnect the client from the server-side
-Disconnect() error
-```
-
-```go
-// file ./main.go
-package main
-
-import (
- "fmt"
- "github.com/kataras/iris"
-)
-
-type clientPage struct {
- Title string
- Host string
-}
-
-func main() {
- iris.Static("/js", "./static/js", 1)
-
- iris.Get("/", func(ctx *iris.Context) {
- ctx.Render("client.html", clientPage{"Client Page", ctx.Host()})
- })
-
- // the path at which the websocket client should register itself to
- iris.Config.Websocket.Endpoint = "/my_endpoint"
-
- var myChatRoom = "room1"
- iris.Websocket.OnConnection(func(c iris.WebsocketConnection) {
-
- c.Join(myChatRoom)
-
- c.On("chat", func(message string) {
- // to all except this connection ->
- //c.To(iris.Broadcast).Emit("chat", "Message from: "+c.ID()+"-> "+message)
-
- // to the client ->
- //c.Emit("chat", "Message from myself: "+message)
-
- // send the message to the whole room,
- // all connections which are inside this room will receive this message
- c.To(myChatRoom).Emit("chat", "From: "+c.ID()+": "+message)
- })
-
- c.OnDisconnect(func() {
- fmt.Printf("\nConnection with ID: %s has been disconnected!", c.ID())
- })
- })
-
- iris.Listen(":8080")
-}
-
-```
-
-```js
-// file js/chat.js
-var messageTxt;
-var messages;
-
-$(function () {
-
- messageTxt = $("#messageTxt");
- messages = $("#messages");
-
-
- ws = new Ws("ws://" + HOST + "/my_endpoint");
- ws.OnConnect(function () {
- console.log("Websocket connection enstablished");
- });
-
- ws.OnDisconnect(function () {
- appendMessage($("
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-View a working example by navigating [here](https://github.com/iris-contrib/examples/tree/master/websocket) and if you need more than one websocket server [click here](https://github.com/iris-contrib/examples/tree/master/websocket_unlimited_servers).
-
-> Each section of the README has its own - more advanced - subject on the book, so be sure to check book for any further research
-
-[Read more](https://docs.iris-go.com/package-websocket.html)
-
-### Need help?
+Documentation
+-----------
- The most important is to read [the practical guide](https://docs.iris-go.com/).
- - Explore & download the [examples](https://github.com/iris-contrib/examples).
+ - Navigate through [examples](https://github.com/iris-contrib/examples).
- [HISTORY.md](https://github.com//kataras/iris/tree/master/HISTORY.md) file is your best friend.
-#### FAQ
-Explore [these questions](https://github.com/kataras/iris/issues?q=label%3Aquestion) or navigate to the [community chat][Chat].
-
-
-Support
+Testing
------------
-Hi, my name is Gerasimos Maropoulos and I'm the author of this project, let me put a few words about me.
+You can find RESTFUL test examples by navigating to the following links:
-I started to design iris the night of the 13 March 2016, some weeks later, iris started to became famous and I have to fix many issues and implement new features, but I didn't have time to work on Iris because I had a part time job and the (software engineering) colleague which I studied.
+- [gavv/_examples/iris_test.go](https://github.com/gavv/httpexpect/blob/master/_examples/iris_test.go).
+- [./http_test.go](https://github.com/kataras/iris/blob/master/http_test.go).
+- [./context_test.go](https://github.com/kataras/iris/blob/master/context_test.go).
-I wanted to make iris' users proud of the framework they're using, so I decided to interrupt my studies and colleague, two days later I left from my part time job also.
-Today I spend all my days and nights coding for Iris, and I'm happy about this, therefore I have zero incoming value.
-
-- :star: the project
-- [Donate](https://github.com/kataras/iris/blob/master/DONATIONS.md)
-- :earth_americas: spread the word
-- [Contribute](#contributing) to the project
+FAQ
+-----------
+Explore [these questions](https://github.com/kataras/iris/issues?q=label%3Aquestion) and join to our [community chat][Chat]!
Philosophy
@@ -924,70 +89,33 @@ Philosophy
The Iris philosophy is to provide robust tooling for HTTP, making it a great solution for single page applications, web sites, hybrids, or public HTTP APIs. Keep note that, today, iris is faster than nginx itself.
-Iris does not force you to use any specific ORM or template engine. With support for the most used template engines, you can quickly craft the perfect application.
+Iris does not force you to use any specific ORM or template engine. With support for the most used template engines (6+), you can quickly craft the perfect application.
-
-Benchmarks v5
-------------
-
-
-This Benchmark test aims to compare the whole HTTP request processing between Go web frameworks.
-
-
-
-
-**The results have been updated on July 21, 2016**
-
-
-Testing
-------------
-
-I recommend testing your API using this new library, [httpexpect](https://github.com/gavv/httpexpect). You can find Iris examples [here](https://github.com/gavv/httpexpect/blob/master/_examples/iris_test.go), [here](https://github.com/kataras/iris/blob/master/http_test.go) and [here](https://github.com/kataras/iris/blob/master/context_test.go).
-
-Versioning
-------------
-
-Current: **v6.1.2**
-
-Old: **[v5/fasthttp](https://github.com/kataras/iris/tree/5.0.0)**
-
-
-Iris is a **Community-Driven** Project, waiting for your suggestions and [feature requests](https://github.com/kataras/iris/issues?utf8=%E2%9C%93&q=label%3A%22feature%20request%22)!
-
-People
+People & Support
------------
The author of Iris is [@kataras](https://github.com/kataras).
-If **you**'re willing to donate and you can afford the cost, feel **free** to navigate to the [DONATIONS PAGE](https://github.com/kataras/iris/blob/master/DONATIONS.md).
+The Success of Iris belongs to YOU with your bug reports and feature requests that made this Framework so Unique.
+#### Who is kataras?
-Contributing
-------------
+Hi, my name is Gerasimos Maropoulos and I'm the author of this project, let me put a few words about me.
-Iris is the work of hundreds of the community's [feature requests](https://github.com/kataras/iris/issues?utf8=%E2%9C%93&q=%20label%3A%22feature%20request%22%20) and [reports](https://github.com/kataras/iris/issues?utf8=%E2%9C%93&q=label%3Abug). I appreciate your help!
+I started to design Iris the night of the 13 March 2016, some weeks later, iris started to became famous and I have to fix many issues and implement new features, but I didn't have time to work on Iris because I had a part time job and the (software engineering) colleague which I studied.
+
+I wanted to make iris' users proud of the framework they're using, so I decided to interrupt my studies and colleague, two days later I left from my part time job also.
+
+Today I spend all my days and nights coding for Iris, and I'm happy about this, therefore I have zero incoming value.
+
+- Star the project, will help you to follow the upcoming features.
+- [Donate](https://github.com/kataras/iris/blob/master/DONATIONS.md), if you can afford any cost.
+- Write an article about Iris or even post a Tweet.
If you are interested in contributing to the Iris project, please see the document [CONTRIBUTING](https://github.com/kataras/iris/blob/master/.github/CONTRIBUTING.md).
-Depends on:
-
-- http protocol layer comes from [net/http](https://github.com/golang/go/tree/master/src/net/http), by Go Authors.
-- rich and encoded responses support comes from [kataras/go-serializer](https://github.com/kataras/go-serializer/tree/0.0.4), by me.
-- template support comes from [kataras/go-template](https://github.com/kataras/go-template/tree/0.0.3), by me.
-- gzip support comes from [kataras/go-fs](https://github.com/kataras/go-fs/tree/0.0.5) and the super-fast compression library [klauspost/compress/gzip](https://github.com/klauspost/compress/tree/master/gzip), by me & Klaus Post.
-- websockets support comes from [kataras/go-websocket](https://github.com/kataras/go-websocket/tree/0.0.2), by me.
-- Base of the parameterized routing algorithm comes from [julienschmidt/httprouter](https://github.com/julienschmidt/httprouter), by Julien Schmidt, with some relative to performance edits by me.
-- sessions support comes from [kataras/go-sessions](https://github.com/kataras/go-sessions/tree/0.0.6), by me.
-- caching support comes from [geekypanda/httpcache](https://github.com/geekypanda/httpcache/tree/0.0.1), by me and GeekyPanda.
-- end-to-end http test APIs comes from [gavv/httpexpect](https://github.com/gavv/httpexpect), by Victor Gaydov.
-- hot-reload on source code changes comes from [kataras/rizla](https://github.com/kataras/rizla), by me.
-- auto-updater (via github) comes from [kataras/go-fs](https://github.com/kataras/go-fs), by me.
-- request body form binder is an [edited version](https://github.com/iris-contrib/formBinder) of the [monoculum/formam](https://github.com/monoculum/formam) library, by Monoculum Organisation.
-- all other packages comes from the [Iris Contrib Organisation](https://github.com/iris-contrib) and the [Go standard library](https://github.com/golang/go), by me & The Go Authors.
-
-
Contact
------------
@@ -999,11 +127,19 @@ Besides the fact that we have a [community chat][Chat] for questions or reports
- [Youtube + Gplus](https://www.youtube.com/user/PrimesocialNetworks)
- [Medium](https://medium.com/@kataras)
+
+Versioning
+------------
+
+Current: **v6.1.2**
+
+v5: https://github.com/kataras/iris/tree/5.0.0
+
+
License
------------
-Unless otherwise noted, the `iris` source files are distributed
+Unless otherwise noted, the source files are distributed
under the MIT License found in the [LICENSE file](LICENSE).
-
[Chat]: https://kataras.rocket.chat/channel/iris
diff --git a/docs/QUICK_START.md b/docs/QUICK_START.md
new file mode 100644
index 00000000..6a3ccb09
--- /dev/null
+++ b/docs/QUICK_START.md
@@ -0,0 +1,829 @@
+Quick Start
+-----------
+
+```bash
+go get -u github.com/kataras/iris/iris
+```
+
+```sh
+cat hellojson.go
+```
+
+```go
+package main
+
+import "github.com/kataras/iris"
+
+func main(){
+
+ // http://localhost:5700/api/user/42
+ // Method: "GET"
+ iris.Get("/api/user/:id", func(ctx *iris.Context){
+
+ // take the :id from the path, parse to integer
+ // and set it to the new userID local variable.
+ userID,_ := ctx.ParamInt("id")
+
+ // userRepo, imaginary database service <- your only job.
+ user := userRepo.GetByID(userID)
+
+ // send back a response to the client,
+ // .JSON: content type as application/json; charset="utf-8"
+ // iris.StatusOK: with 200 http status code.
+ //
+ // send user as it is or make use of any json valid golang type,
+ // like the iris.Map{"username" : user.Username}.
+ ctx.JSON(iris.StatusOK, user)
+
+ })
+
+ iris.Listen(":6000")
+}
+
+```
+
+```sh
+$ go run hellojson.go
+```
+> TIP: $ iris run main.go to enable hot-reload on .go source code changes.
+
+> TIP: iris.Config.IsDevelopment = true to monitor the changes you make in the templates.
+
+> TIP: Want to change the default Router's behavior to something else like Gorilla's Mux?
+Go [there](https://github.com/iris-contrib/examples/tree/master/plugin_gorillamux) to learn how.
+
+Open your browser or any other http client at http://localhost:6000/api/user/42.
+
+
+### New
+
+```go
+// New with default configuration
+app := iris.New()
+
+app.Listen(....)
+
+// New with configuration struct
+app := iris.New(iris.Configuration{ IsDevelopment: true})
+
+app.Listen(...)
+
+// Default station
+iris.Listen(...)
+
+// Default station with custom configuration
+// view the whole configuration at: ./configuration.go
+iris.Config.IsDevelopment = true
+iris.Config.Charset = "UTF-8"
+
+iris.Listen(...)
+```
+
+### Listening
+`Serve(ln net.Listener) error`
+```go
+ln, err := net.Listen("tcp4", ":8080")
+if err := iris.Serve(ln); err != nil {
+ panic(err)
+}
+```
+`Listen(addr string)`
+```go
+iris.Listen(":8080")
+```
+`ListenTLS(addr string, certFile, keyFile string)`
+```go
+iris.ListenTLS(":8080", "./ssl/mycert.cert", "./ssl/mykey.key")
+```
+`ListenLETSENCRYPT(addr string, cacheFileOptional ...string)`
+```go
+iris.ListenLETSENCRYPT("mydomain.com")
+```
+```go
+iris.Serve(iris.LETSENCRYPTPROD("myproductionwebsite.com"))
+```
+
+And
+
+```go
+ListenUNIX(addr string, mode os.FileMode)
+Close() error
+Reserve() error
+IsRunning() bool
+```
+
+### Routing
+
+```go
+iris.Get("/products/:id", getProduct)
+iris.Post("/products", saveProduct)
+iris.Put("products/:id", editProduct)
+iris.Delete("/products/:id", deleteProduct)
+```
+
+And
+
+```go
+iris.Patch("", ...)
+iris.Connect("", ...)
+iris.Options("", ...)
+iris.Trace("", ...)
+```
+
+### Path Parameters
+
+```go
+func getProduct(ctx *iris.Context){
+ // Get id from path '/products/:id'
+ id := ctx.Param("id")
+}
+
+```
+
+### Query Parameters
+
+`/details?color=blue&weight=20`
+
+```go
+func details(ctx *iris.Context){
+ color := ctx.URLParam("color")
+ weight,_ := ctx.URLParamInt("weight")
+}
+
+```
+
+### Form `application/x-www-form-urlencoded`
+
+`METHOD: POST | PATH: /save`
+
+name | value
+:--- | :---
+name | Gerasimos Maropoulos
+email | kataras2006@homail.com
+
+
+```go
+func save(ctx *iris.Context) {
+ // Get name and email
+ name := ctx.FormValue("name")
+ email := ctx.FormValue("email")
+}
+```
+
+### Form `multipart/form-data`
+
+`POST` `/save`
+
+name | value
+:--- | :---
+name | Gerasimos Maropoulos
+email | kataras2006@hotmail.com
+avatar | avatar
+
+```go
+func save(ctx *iris.Context) {
+ // Get name and email
+ name := ctx.FormValue("name")
+ email := ctx.FormValue("email")
+ // Get avatar
+ avatar, info, err := ctx.FormFile("avatar")
+ if err != nil {
+ ctx.EmitError(iris.StatusInternalServerError)
+ return
+ }
+
+ defer avatar.Close()
+
+ // Destination
+ dst, err := os.Create(avatar.Filename)
+ if err != nil {
+ ctx.EmitError(iris.StatusInternalServerError)
+ return
+ }
+ defer dst.Close()
+
+ // Copy
+ if _, err = io.Copy(dst, avatar); err != nil {
+ ctx.EmitError(iris.StatusInternalServerError)
+ return
+ }
+
+ ctx.HTML(iris.StatusOK, "Thanks!")
+}
+```
+
+### Handling Request
+
+
+- Bind `JSON` or `XML` or `form` payload into Go struct based on `Content-Type` request header.
+- Render response as `JSON` or `XML` with status code.
+
+```go
+type User struct {
+ Name string `json:"name" xml:"name" form:"name"`
+ Email string `json:"email" xml:"email" form:"email"`
+}
+
+iris.Post("/users", func(ctx *iris.Context) {
+ u := new(User)
+ if err := ctx.ReadJSON(u); err != nil {
+ ctx.EmitError(iris.StatusInternalServerError)
+ return
+ }
+ ctx.JSON(iris.StatusCreated, u)
+ // or
+ // ctx.XML(iris.StatusCreated, u)
+ // ctx.JSONP(...)
+ // ctx.HTML(iris.StatusCreated, "Hi "+u.Name+"")
+ // ctx.Markdown(iris.StatusCreated, "## Name: "+u.Name)
+})
+```
+
+
+| Name | Description | Usage |
+| ------------------|:---------------------:|-------:|
+| [JSON ](https://github.com/kataras/go-serializer/tree/master/json) | JSON Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/json_1/main.go),[example 2](https://github.com/iris-contrib/examples/blob/master/serialize_engines/json_2/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
+| [JSONP ](https://github.com/kataras/go-serializer/tree/master/jsonp) | JSONP Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/jsonp_1/main.go),[example 2](https://github.com/iris-contrib/examples/blob/master/serialize_engines/jsonp_2/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
+| [XML ](https://github.com/kataras/go-serializer/tree/master/xml) | XML Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/xml_1/main.go),[example 2](https://github.com/iris-contrib/examples/blob/master/serialize_engines/xml_2/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
+| [Markdown ](https://github.com/kataras/go-serializer/tree/master/markdown) | Markdown Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/markdown_1/main.go),[example 2](https://github.com/iris-contrib/examples/blob/master/serialize_engines/markdown_2/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
+| [Text](https://github.com/kataras/go-serializer/tree/master/text) | Text Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/text_1/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
+| [Binary Data ](https://github.com/kataras/go-serializer/tree/master/data) | Binary Data Serializer (Default) |[example 1](https://github.com/iris-contrib/examples/blob/master/serialize_engines/data_1/main.go), [book section](https://docs.iris-go.com/serialize-engines.html)
+
+
+### HTTP Errors
+
+You can define your own handlers when http error occurs.
+
+```go
+package main
+
+import (
+ "github.com/kataras/iris"
+)
+
+func main() {
+
+ iris.OnError(iris.StatusInternalServerError, func(ctx *iris.Context) {
+ ctx.Writef("CUSTOM 500 INTERNAL SERVER ERROR PAGE")
+ // or ctx.Render, ctx.HTML any render method you want
+ ctx.Log("http status: 500 happened!")
+ })
+
+ iris.OnError(iris.StatusNotFound, func(ctx *iris.Context) {
+ ctx.Writef("CUSTOM 404 NOT FOUND ERROR PAGE")
+ ctx.Log("http status: 404 happened!")
+ })
+
+ // emit the errors to test them
+ iris.Get("/500", func(ctx *iris.Context) {
+ ctx.EmitError(iris.StatusInternalServerError) // ctx.Panic()
+ })
+
+ iris.Get("/404", func(ctx *iris.Context) {
+ ctx.EmitError(iris.StatusNotFound) // ctx.NotFound()
+ })
+
+ iris.Listen(":80")
+
+}
+
+
+```
+
+### Static Content
+
+Serve files or directories, use the correct for your case, if you don't know which one, just use the `StaticWeb(reqPath string, systemPath string)`.
+
+```go
+// Favicon serves static favicon
+// accepts 2 parameters, second is optional
+// favPath (string), declare the system directory path of the __.ico
+// requestPath (string), it's the route's path, by default this is the "/favicon.ico" because some browsers tries to get this by default first,
+// you can declare your own path if you have more than one favicon (desktop, mobile and so on)
+//
+// this func will add a route for you which will static serve the /yuorpath/yourfile.ico to the /yourfile.ico (nothing special that you can't handle by yourself)
+// Note that you have to call it on every favicon you have to serve automatically (desktop, mobile and so on)
+//
+// panics on error
+Favicon(favPath string, requestPath ...string) RouteNameFunc
+
+// StaticHandler returns a new Handler which serves static files
+StaticHandler(reqPath string, systemPath string, showList bool, enableGzip bool) HandlerFunc
+
+// StaticWeb same as Static but if index.html e
+// xists and request uri is '/' then display the index.html's contents
+// accepts three parameters
+// first parameter is the request url path (string)
+// second parameter is the system directory (string)
+StaticWeb(reqPath string, systemPath string) RouteNameFunc
+
+// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
+// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
+// Second parameter is the (virtual) directory path, for example "./assets"
+// Third parameter is the Asset function
+// Forth parameter is the AssetNames function
+//
+// For more take a look at the
+// example: https://github.com/iris-contrib/examples/tree/master/static_files_embedded
+StaticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) RouteNameFunc
+
+// StaticContent serves bytes, memory cached, on the reqPath
+// a good example of this is how the websocket server uses that to auto-register the /iris-ws.js
+StaticContent(reqPath string, cType string, content []byte) RouteNameFunc
+
+// StaticServe serves a directory as web resource
+// it's the simpliest form of the Static* functions
+// Almost same usage as StaticWeb
+// accepts only one required parameter which is the systemPath
+// (the same path will be used to register the GET&HEAD routes)
+// if the second parameter is empty, otherwise the requestPath is the second parameter
+// it uses gzip compression (compression on each request, no file cache)
+StaticServe(systemPath string, requestPath ...string)
+
+```
+
+```go
+iris.StaticWeb("/public", "./static/assets/")
+//-> /public/assets/favicon.ico
+```
+
+```go
+iris.StaticWeb("/","./my_static_html_website")
+```
+
+```go
+context.StaticServe(systemPath string, requestPath ...string)
+```
+
+#### Manual static file serving
+
+```go
+// ServeFile serves a view file, to send a file
+// to the client you should use the SendFile(serverfilename,clientfilename)
+// receives two parameters
+// filename/path (string)
+// gzipCompression (bool)
+//
+// You can define your own "Content-Type" header also, after this function call
+context.ServeFile(filename string, gzipCompression bool) error
+```
+
+Serve static individual file
+
+```go
+
+iris.Get("/txt", func(ctx *iris.Context) {
+ ctx.ServeFile("./myfolder/staticfile.txt", false)
+}
+```
+
+### Templates
+
+**HTML Template Engine, defaulted**
+
+
+```html
+
+
+
+
+Hi Iris
+
+
+
Hi {{.Name}}
+
+
+```
+
+```go
+// file ./main.go
+package main
+
+import "github.com/kataras/iris"
+
+func main() {
+ iris.Config.IsDevelopment = true // this will reload the templates on each request
+ iris.Get("/hi", hi)
+ iris.Listen(":8080")
+}
+
+func hi(ctx *iris.Context) {
+ ctx.MustRender("hi.html", struct{ Name string }{Name: "iris"})
+}
+
+```
+
+| Name | Description | Usage |
+| ------------------|:---------------------:|-------:|
+| [HTML/Default Engine ](https://github.com/kataras/go-template/tree/master/html) | HTML Template Engine (Default) |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_html_0/main.go), [book section](https://docs.iris-go.com/template-engines.html)
+| [Django Engine ](https://github.com/kataras/go-template/tree/master/django) | Django Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_django_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
+| [Pug/Jade Engine ](https://github.com/kataras/go-template/tree/master/pug) | Pug Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_pug_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
+| [Handlebars Engine ](https://github.com/kataras/go-template/tree/master/handlebars) | Handlebars Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_handlebars_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
+| [Amber Engine ](https://github.com/kataras/go-template/tree/master/amber) | Amber Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_amber_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
+| [Markdown Engine ](https://github.com/kataras/go-template/tree/master/markdown) | Markdown Template Engine |[example ](https://github.com/iris-contrib/examples/blob/master/template_engines/template_markdown_1/main.go), [book section](https://docs.iris-go.com/template-engines.html)
+
+> Each section of the README has its own - more advanced - subject on the book, so be sure to check book for any further research
+
+[Read more](https://docs.iris-go.com/template-engines.html)
+
+### Middleware ecosystem
+
+
+```go
+
+import (
+ "github.com/iris-contrib/middleware/logger"
+ "github.com/iris-contrib/middleware/cors"
+ "github.com/iris-contrib/middleware/basicauth"
+)
+// Root level middleware
+iris.Use(logger.New())
+iris.Use(cors.Default())
+
+// Group level middleware
+authConfig := basicauth.Config{
+ Users: map[string]string{"myusername": "mypassword", "mySecondusername": "mySecondpassword"},
+ Realm: "Authorization Required", // if you don't set it it's "Authorization Required"
+ ContextKey: "mycustomkey", // if you don't set it it's "user"
+ Expires: time.Duration(30) * time.Minute,
+}
+
+authentication := basicauth.New(authConfig)
+
+g := iris.Party("/admin")
+g.Use(authentication)
+
+// Route level middleware
+logme := func(ctx *iris.Context) {
+ println("request to /products")
+ ctx.Next()
+}
+iris.Get("/products", logme, func(ctx *iris.Context) {
+ ctx.Text(iris.StatusOK, "/products")
+})
+```
+
+
+| Name | Description | Usage |
+| ------------------|:---------------------:|-------:|
+| [Basicauth Middleware ](https://github.com/iris-contrib/middleware/tree/master/basicauth) | HTTP Basic authentication |[example 1](https://github.com/iris-contrib/examples/blob/master/middleware_basicauth_1/main.go), [example 2](https://github.com/iris-contrib/examples/blob/master/middleware_basicauth_2/main.go), [book section](https://docs.iris-go.com/basic-authentication.html) |
+| [JWT Middleware ](https://github.com/iris-contrib/middleware/tree/master/jwt) | JSON Web Tokens |[example ](https://github.com/iris-contrib/examples/blob/master/middleware_jwt/main.go), [book section](https://docs.iris-go.com/jwt.html) |
+| [Cors Middleware ](https://github.com/iris-contrib/middleware/tree/master/cors) | Cross Origin Resource Sharing W3 specification | [how to use ](https://github.com/iris-contrib/middleware/tree/master/cors#how-to-use) |
+| [Secure Middleware ](https://github.com/iris-contrib/middleware/tree/master/secure) | Facilitates some quick security wins | [example](https://github.com/iris-contrib/examples/blob/master/middleware_secure/main.go) |
+| [I18n Middleware ](https://github.com/iris-contrib/middleware/tree/master/i18n) | Simple internationalization | [example](https://github.com/iris-contrib/examples/tree/master/middleware_internationalization_i18n), [book section](https://docs.iris-go.com/middleware-internationalization-and-localization.html) |
+| [Recovery Middleware ](https://github.com/iris-contrib/middleware/tree/master/recovery) | Safety recover the station from panic | [example](https://github.com/iris-contrib/examples/blob/master/middleware_recovery/main.go) |
+| [Logger Middleware ](https://github.com/iris-contrib/middleware/tree/master/logger) | Logs every request | [example](https://github.com/iris-contrib/examples/blob/master/middleware_logger/main.go), [book section](https://docs.iris-go.com/logger.html) |
+| [LoggerZap Middleware ](https://github.com/iris-contrib/middleware/tree/master/loggerzap) | Logs every request using zap | [example](https://github.com/iris-contrib/examples/blob/master/middleware_logger/main.go), [book section](https://docs.iris-go.com/logger.html) |
+| [Profile Middleware ](https://github.com/iris-contrib/middleware/tree/master/pprof) | Http profiling for debugging | [example](https://github.com/iris-contrib/examples/blob/master/middleware_pprof/main.go) |
+| [Editor Plugin](https://github.com/iris-contrib/plugin/tree/master/editor) | Alm-tools, a typescript online IDE/Editor | [book section](https://docs.iris-go.com/plugin-editor.html) |
+| [Typescript Plugin](https://github.com/iris-contrib/plugin/tree/master/typescript) | Auto-compile client-side typescript files | [book section](https://docs.iris-go.com/plugin-typescript.html) |
+| [OAuth,OAuth2 Plugin](https://github.com/iris-contrib/plugin/tree/master/oauth) | User Authentication was never be easier, supports >27 providers | [example](https://github.com/iris-contrib/examples/tree/master/plugin_oauth_oauth2), [book section](https://docs.iris-go.com/plugin-oauth.html) |
+| [Iris control Plugin](https://github.com/iris-contrib/plugin/tree/master/iriscontrol) | Basic (browser-based) control over your Iris station | [example](https://github.com/iris-contrib/examples/blob/master/plugin_iriscontrol/main.go), [book section](https://docs.iris-go.com/plugin-iriscontrol.html) |
+
+> NOTE: All net/http handlers and middleware that already created by other go developers are also compatible with Iris, even if they are not be documented here, read more [here](https://github.com/iris-contrib/middleware#can-i-use-standard-nethttp-handler-with-iris).
+
+
+### Sessions
+If you notice a bug or issue [post it here](https://github.com/kataras/go-sessions).
+
+
+- Cleans the temp memory when a session is idle, and re-allocates it to the temp memory when it's necessary.
+The most used sessions are optimized to be in the front of the memory's list.
+
+- Supports any type of database, currently only [Redis](https://github.com/kataras/go-sessions/tree/master/sessiondb/redis) and [LevelDB](https://github.com/kataras/go-sessions/tree/master/sessiondb/leveldb).
+
+
+**A session can be defined as a server-side storage of information that is desired to persist throughout the user's interaction with the web application**.
+
+Instead of storing large and constantly changing data via cookies in the user's browser (i.e. CookieStore),
+**only a unique identifier is stored on the client side** called a "session id".
+This session id is passed to the web server on every request.
+The web application uses the session id as the key for retrieving the stored data from the database/memory. The session data is then available inside the iris.Context.
+
+```go
+iris.Get("/", func(ctx *iris.Context) {
+ ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
+ })
+
+ iris.Get("/set", func(ctx *iris.Context) {
+
+ //set session values
+ ctx.Session().Set("name", "iris")
+
+ //test if setted here
+ ctx.Writef("All ok session setted to: %s", ctx.Session().GetString("name"))
+ })
+
+ iris.Get("/get", func(ctx *iris.Context) {
+ // get a specific key as a string.
+ // returns an empty string if the key was not found.
+ name := ctx.Session().GetString("name")
+
+ ctx.Writef("The name on the /set was: %s", name)
+ })
+
+ iris.Get("/delete", func(ctx *iris.Context) {
+ // delete a specific key
+ ctx.Session().Delete("name")
+ })
+
+ iris.Get("/clear", func(ctx *iris.Context) {
+ // removes all entries
+ ctx.Session().Clear()
+ })
+
+ iris.Get("/destroy", func(ctx *iris.Context) {
+ // destroy/removes the entire session and cookie
+ ctx.SessionDestroy()
+ ctx.Log("You have to refresh the page to completely remove the session (on browsers), so the name should NOT be empty NOW, is it?\n ame: %s\n\nAlso check your cookies in your browser's cookies, should be no field for localhost/127.0.0.1 (or whatever you use)", ctx.Session().GetString("name"))
+ ctx.Writef("You have to refresh the page to completely remove the session (on browsers), so the name should NOT be empty NOW, is it?\nName: %s\n\nAlso check your cookies in your browser's cookies, should be no field for localhost/127.0.0.1 (or whatever you use)", ctx.Session().GetString("name"))
+ })
+
+ iris.Listen(":8080")
+
+```
+
+- `iris.DestroySessionByID(string)`
+
+```go
+// DestroySessionByID removes the session entry
+// from the server-side memory (and database if registered).
+// Client's session cookie will still exist but it will be reseted on the next request.
+//
+// It's safe to use it even if you are not sure if a session with that id exists.
+DestroySessionByID(string)
+```
+
+- `iris.DestroyAllSessions()`
+
+```go
+// DestroyAllSessions removes all sessions
+// from the server-side memory (and database if registered).
+// Client's session cookie will still exist but it will be reseted on the next request.
+DestroyAllSessions()
+```
+
+> Each section of the README has its own - more advanced - subject on the book, so be sure to check book for any further research
+
+[Read more](https://docs.iris-go.com/package-sessions.html)
+
+### Websockets
+
+Server configuration
+
+```go
+iris.Config.Websocket{
+ // WriteTimeout time allowed to write a message to the connection.
+ // Default value is 15 * time.Second
+ WriteTimeout time.Duration
+ // PongTimeout allowed to read the next pong message from the connection
+ // Default value is 60 * time.Second
+ PongTimeout time.Duration
+ // PingPeriod send ping messages to the connection with this period. Must be less than PongTimeout
+ // Default value is (PongTimeout * 9) / 10
+ PingPeriod time.Duration
+ // MaxMessageSize max message size allowed from connection
+ // Default value is 1024
+ MaxMessageSize int64
+ // BinaryMessages set it to true in order to denotes binary data messages instead of utf-8 text
+ // see https://github.com/kataras/iris/issues/387#issuecomment-243006022 for more
+ // Defaults to false
+ BinaryMessages bool
+ // Endpoint is the path which the websocket server will listen for clients/connections
+ // Default value is empty string, if you don't set it the Websocket server is disabled.
+ Endpoint string
+ // ReadBufferSize is the buffer size for the underline reader
+ ReadBufferSize int
+ // WriteBufferSize is the buffer size for the underline writer
+ WriteBufferSize int
+ // Error specifies the function for generating HTTP error responses.
+ //
+ // The default behavior is to store the reason in the context (ctx.Set(reason)) and fire any custom error (ctx.EmitError(status))
+ Error func(ctx *Context, status int, reason error)
+ // CheckOrigin returns true if the request Origin header is acceptable. If
+ // CheckOrigin is nil, the host in the Origin header must not be set or
+ // must match the host of the request.
+ //
+ // The default behavior is to allow all origins
+ // you can change this behavior by setting the iris.Config.Websocket.CheckOrigin = iris.WebsocketCheckSameOrigin
+ CheckOrigin func(r *http.Request) bool
+ // IDGenerator used to create (and later on, set)
+ // an ID for each incoming websocket connections (clients).
+ // If empty then the ID is generated by the result of 64
+ // random combined characters
+ IDGenerator func(r *http.Request) string
+}
+
+```
+
+Connection's methods
+
+```go
+ID() string
+
+Request() *http.Request
+
+// Receive from the client
+On("anyCustomEvent", func(message string) {})
+On("anyCustomEvent", func(message int){})
+On("anyCustomEvent", func(message bool){})
+On("anyCustomEvent", func(message anyCustomType){})
+On("anyCustomEvent", func(){})
+
+// Receive a native websocket message from the client
+// compatible without need of import the iris-ws.js to the .html
+OnMessage(func(message []byte){})
+
+// Send to the client
+Emit("anyCustomEvent", string)
+Emit("anyCustomEvent", int)
+Emit("anyCustomEvent", bool)
+Emit("anyCustomEvent", anyCustomType)
+
+// Send native websocket messages
+// with config.BinaryMessages = true
+// useful when you use proto or something like this.
+EmitMessage([]byte("anyMessage"))
+
+// Send to specific client(s)
+To("otherConnectionId").Emit/EmitMessage...
+To("anyCustomRoom").Emit/EmitMessage...
+
+// Send to all opened connections/clients
+To(websocket.All).Emit/EmitMessage...
+
+// Send to all opened connections/clients EXCEPT this client
+To(websocket.Broadcast).Emit/EmitMessage...
+
+// Rooms, group of connections/clients
+Join("anyCustomRoom")
+Leave("anyCustomRoom")
+
+
+// Fired when the connection is closed
+OnDisconnect(func(){})
+
+// Force-disconnect the client from the server-side
+Disconnect() error
+```
+
+```go
+// file ./main.go
+package main
+
+import (
+ "fmt"
+ "github.com/kataras/iris"
+)
+
+type clientPage struct {
+ Title string
+ Host string
+}
+
+func main() {
+ iris.Static("/js", "./static/js", 1)
+
+ iris.Get("/", func(ctx *iris.Context) {
+ ctx.Render("client.html", clientPage{"Client Page", ctx.Host()})
+ })
+
+ // the path at which the websocket client should register itself to
+ iris.Config.Websocket.Endpoint = "/my_endpoint"
+
+ var myChatRoom = "room1"
+ iris.Websocket.OnConnection(func(c iris.WebsocketConnection) {
+
+ c.Join(myChatRoom)
+
+ c.On("chat", func(message string) {
+ // to all except this connection ->
+ //c.To(iris.Broadcast).Emit("chat", "Message from: "+c.ID()+"-> "+message)
+
+ // to the client ->
+ //c.Emit("chat", "Message from myself: "+message)
+
+ // send the message to the whole room,
+ // all connections which are inside this room will receive this message
+ c.To(myChatRoom).Emit("chat", "From: "+c.ID()+": "+message)
+ })
+
+ c.OnDisconnect(func() {
+ fmt.Printf("\nConnection with ID: %s has been disconnected!", c.ID())
+ })
+ })
+
+ iris.Listen(":8080")
+}
+
+```
+
+```js
+// file js/chat.js
+var messageTxt;
+var messages;
+
+$(function () {
+
+ messageTxt = $("#messageTxt");
+ messages = $("#messages");
+
+
+ ws = new Ws("ws://" + HOST + "/my_endpoint");
+ ws.OnConnect(function () {
+ console.log("Websocket connection enstablished");
+ });
+
+ ws.OnDisconnect(function () {
+ appendMessage($("
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+View a working example by navigating [here](https://github.com/iris-contrib/examples/tree/master/websocket) and if you need more than one websocket server [click here](https://github.com/iris-contrib/examples/tree/master/websocket_unlimited_servers).
+
+> Each section of the README has its own - more advanced - subject on the book, so be sure to check book for any further research
+
+[Read more](https://docs.iris-go.com/package-websocket.html)
+
+
+
+Benchmarks
+------------
+
+These benchmarks are for the previous Iris version(1month ago), new benchmarks are coming after the release of the Go version 1.8 in order to include the `Push` feature inside the tests.
+
+
+This Benchmark test aims to compare the whole HTTP request processing between Go web frameworks.
+
+
+
+
+**The results have been updated on July 21, 2016**
+
+
+
+Depends on:
+
+- http protocol layer comes from [net/http](https://github.com/golang/go/tree/master/src/net/http), by Go Authors.
+- rich and encoded responses support comes from [kataras/go-serializer](https://github.com/kataras/go-serializer/tree/0.0.4), by me.
+- template support comes from [kataras/go-template](https://github.com/kataras/go-template/tree/0.0.3), by me.
+- gzip support comes from [kataras/go-fs](https://github.com/kataras/go-fs/tree/0.0.5) and the super-fast compression library [klauspost/compress/gzip](https://github.com/klauspost/compress/tree/master/gzip), by me & Klaus Post.
+- websockets support comes from [kataras/go-websocket](https://github.com/kataras/go-websocket/tree/0.0.2), by me.
+- Base of the parameterized routing algorithm comes from [julienschmidt/httprouter](https://github.com/julienschmidt/httprouter), by Julien Schmidt, with some relative to performance edits by me.
+- sessions support comes from [kataras/go-sessions](https://github.com/kataras/go-sessions/tree/0.0.6), by me.
+- caching support comes from [geekypanda/httpcache](https://github.com/geekypanda/httpcache/tree/0.0.1), by me and GeekyPanda.
+- end-to-end http test APIs comes from [gavv/httpexpect](https://github.com/gavv/httpexpect), by Victor Gaydov.
+- hot-reload on source code changes comes from [kataras/rizla](https://github.com/kataras/rizla), by me.
+- auto-updater (via github) comes from [kataras/go-fs](https://github.com/kataras/go-fs), by me.
+- request body form binder is an [edited version](https://github.com/iris-contrib/formBinder) of the [monoculum/formam](https://github.com/monoculum/formam) library, by Monoculum Organisation.
+- all other packages comes from the [Iris Contrib Organisation](https://github.com/iris-contrib) and the [Go standard library](https://github.com/golang/go), by me & The Go Authors.
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..29c4c60c
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,12 @@
+# Documentation
+
+Navigate through [https://docs.iris-go.com/](https://docs.iris-go.com/) website to read the docs.
+
+
+## Contributing
+
+You can contribute to the documentation via PR to its public repository, [iris-contrib/gitbook](https://github.com/iris-contrib/gitbook). Any code-fix or even a grammar-fix is acceptable and welcomed!
+
+## Examples?
+
+Navigate through examples by clicking [here](https://github.com/iris-contrib/examples) & [run](https://github.com/kataras/iris/blob/master/examples/README.md) them.
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 00000000..97553180
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,16 @@
+# Examples
+
+Navigate through [iris-contrib/examples](https://github.com/iris-contrib/examples) repository to view all available examples.
+
+> These examples are small but practical, they do NOT cover all Iris' and Go's stdlib features.
+
+
+## Run
+
+1. Download the [Go Programming Language](https://golang.org/dl/).
+2. Download the [LiteIDE](https://sourceforge.net/projects/liteide/files/X30.3/), a cross-platform Go IDE.
+3. Click [here](https://github.com/iris-contrib/examples/archive/master.zip) to download all examples.
+4. **Unzip** the contents of your `examples-master.zip` you just downloaded.
+5. Open the LiteIDE, click on the `File -> Open Folder...` menu item (top-left corner)
+and select the folder which contains the contents you just unzipped.
+6. Open an example folder, select its `main.go` and `run` it by pressing `Ctrl/CMD +R`.
diff --git a/iris.go b/iris.go
index fc0eb4b3..a402e93a 100644
--- a/iris.go
+++ b/iris.go
@@ -93,16 +93,16 @@ const (
// Default iris instance entry and its public fields, use it with iris.$anyPublicFuncOrField
var (
- Default *Framework
- Config *Configuration
- Logger *log.Logger // if you want colors in your console then you should use this https://github.com/iris-contrib/logger instead.
- Plugins PluginContainer
+ Default *Framework
+ Config *Configuration
+ Logger *log.Logger // if you want colors in your console then you should use this https://github.com/iris-contrib/logger instead.
+ Plugins PluginContainer
// Router field holds the main http.Handler which can be changed.
// if you want to get benefit with iris' context make use of:
// ctx:= iris.AcquireCtx(http.ResponseWriter, *http.Request) to get the context at the beginning of your handler
// iris.ReleaseCtx(ctx) to release/put the context to the pool, at the very end of your custom handler.
//
- // Want to change the default Router's behavior to something else like Gorilla's Mux?
+ // Want to change the default Router's behavior to something else like Gorilla's Mux?
// See more: https://github.com/iris-contrib/plugin/tree/master/gorillamux
Router http.Handler
Websocket *WebsocketServer
@@ -262,7 +262,7 @@ type Framework struct {
// ctx:= iris.AcquireCtx(http.ResponseWriter, *http.Request) to get the context at the beginning of your handler
// iris.ReleaseCtx(ctx) to release/put the context to the pool, at the very end of your custom handler.
//
- // Want to change the default Router's behavior to something else like Gorilla's Mux?
+ // Want to change the default Router's behavior to something else like Gorilla's Mux?
// See more: https://github.com/iris-contrib/plugin/tree/master/gorillamux
Router http.Handler
diff --git a/middleware/README.md b/middleware/README.md
new file mode 100644
index 00000000..4825c19d
--- /dev/null
+++ b/middleware/README.md
@@ -0,0 +1,72 @@
+# Middleware
+
+We should mention that Iris is compatible with **ALL** net/http middleware out there,
+You are not restricted to so-called 'iris-made' middleware. They do exists, mostly, for your learning curve.
+
+Navigate through [iris-contrib/middleware](https://github.com/iris-contrib/through) repository to view iris-made 'middleware'.
+
+> By the word 'middleware', we mean a single or a collection of route handlers which may execute before/or after the main route handler.
+
+
+## Installation
+
+```sh
+$ go get github.com/iris-contrib/middleware/...
+```
+
+## How can I register a middleware?
+
+```go
+app := iris.New()
+/* per root path and all its children */
+app.Use(logger)
+
+/* execute always last */
+// app.Done(logger)
+
+/* per-route, order matters. */
+// app.Get("/", logger, indexHandler)
+
+/* per party (group of routes) */
+// userRoutes := app.Party("/user", logger)
+// userRoutes.Post("/login", loginAuthHandler)
+```
+
+## How 'hard' is to create an Iris middleware?
+
+```go
+myMiddleware := func(ctx *iris.Context){
+ /* using ctx.Set you can transfer ANY data between handlers,
+ use ctx.Get("welcomed") to get its value on the next handler(s).
+ */
+ ctx.Set("welcomed", true)
+
+ println("My middleware!")
+}
+```
+> func(ctx *iris.Context) is just the `iris.HandlerFunc` signature which implements the `iris.Handler`/ `Serve(Context)` method.
+
+```go
+app := iris.New()
+/* root path and all its children */
+app.UseFunc(myMiddleware)
+
+app.Get("/", indexHandler)
+```
+
+## Convert `http.Handler` to `iris.Handler` using the `iris.ToHandler`
+
+```go
+app := iris.New()
+
+sillyHTTPHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
+ println(r.RequestURI)
+})
+
+app.Use(iris.ToHandler(sillyHTTPHandler))
+```
+
+
+## What next?
+
+Read more about [iris.Handler](https://docs.iris-go.com/using-handlers.html), [iris.HandlerFunc](https://docs.iris-go.com/using-handlerfuncs.html) and [Middleware](https://docs.iris-go.com/middleware.html).
diff --git a/plugins/README.md b/plugins/README.md
new file mode 100644
index 00000000..20b0f77e
--- /dev/null
+++ b/plugins/README.md
@@ -0,0 +1,19 @@
+# Plugins
+
+Navigate through [iris-contrib/plugin](https://github.com/iris-contrib/plugin) repository to view all available 'plugins'.
+
+> By the word 'plugin', we mean an event-driven system and not the future go1.8 plugin feature.
+
+
+## Installation
+
+```sh
+$ go get github.com/iris-contrib/plugin/...
+```
+
+## How can I register a plugin?
+
+```go
+app := iris.New()
+app.Plugins.Add(thePlugin)
+```