diff --git a/README.md b/README.md
index ac1e8ef0..1bc33bee 100644
--- a/README.md
+++ b/README.md
@@ -40,64 +40,24 @@ Ideally suited for both experienced and novice Developers.
-
-
-Quick Look
-------------
-
-```go
-package main
-
-import "github.com/kataras/iris"
-
-func main() {
- // serve static files, just a fav here
- iris.Favicon("./favicon.ico")
-
- // handle "/" - HTTP METHOD: "GET"
- iris.Get("/", func(ctx *iris.Context) {
- ctx.Render("index.html", nil)
- })
-
- iris.Get("/login", func(ctx *iris.Context) {
- ctx.Render("login.html", iris.Map{"Title": "Login Page"})
- })
-
- // handle "/login" - HTTP METHOD: "POST"
- iris.Post("/login", func(ctx *iris.Context) {
- secret := ctx.PostValue("secret")
- ctx.Session().Set("secret", secret)
-
- ctx.Redirect("/user")
- })
-
- // handle websocket connections
- iris.Config.Websocket.Endpoint = "/mychat"
- iris.Websocket.OnConnection(func(c iris.WebsocketConnection) {
- c.Join("myroom")
-
- c.On("chat", func(message string){
- c.To("myroom").Emit("chat", "From "+c.ID()+": "+message)
- })
- })
-
- // serve requests at http://localhost:8080
- iris.Listen(":8080")
-}
-```
-
-What's inside?
-------------
+## Feature Overview
- Focus on high performance
- Automatically install TLS certificates from https://letsencrypt.org
- Robust routing and middleware ecosystem
+- Build RESTful APIs
+- Group API's and subdomains
+- Body binding for JSON, XML, and any form element
+- More than 40 handy functions to send HTTP responses
+- Database Communication with any ORM
- Define virtual hosts and (wildcard) subdomains with path level routing
- Graceful shutdown
- Limit request body
-- I18N
+- Localization i18N
- Serve static files
- Log requests
+- Define your format and output for the logger
+- Define custom HTTP errors handlers
- Gzip response
- Authentication
- OAuth, OAuth2 supporting 27+ popular websites
@@ -111,15 +71,16 @@ What's inside?
- HTTP to HTTPS non WWW
- Non WWW to WWW
- WWW to non WWW
-- View system supporting more than six template engines
+- View system supporting more than six template engines, you can still use anything you like
- Highly scalable rich render (Markdown, JSON, JSONP, XML...)
- Websocket API similar to socket.io
- Hot Reload
- Typescript integration + Web IDE
- Checks for updates at startup
+- Highly customizable
-Getting Started
-------------
+
+## Quick Start
### Installation
@@ -129,7 +90,657 @@ The only requirement is the [Go Programming Language](https://golang.org/dl), at
$ go get -u github.com/kataras/iris/iris
```
-> If you have installation issues or you are connected to the Internet through China please, [click here](https://kataras.gitbooks.io/iris/content/install.html).
+### Hello, World!
+
+```sh
+$ cat helloworld.go
+```
+
+```go
+package main
+
+import "github.com/kataras/iris"
+
+func main(){
+
+ iris.Get("/", func(ctx *iris.Context){
+ ctx.Write("Hello, %s", "World!")
+ })
+
+ iris.Get("/myjson", func(ctx *iris.Context){
+ ctx.JSON(iris.Map{
+ "Name": "Iris",
+ "Released": "13 March 2016",
+ "Stars": 5250,
+ })
+ })
+
+ iris.Listen(":8080")
+}
+
+```
+
+```sh
+$ go run helloworld.go
+```
+
+Navigate to http://localhost:8080 and you should see Hello, World!
+
+### New
+
+```go
+// New with default configuration
+app := iris.New()
+
+app.Listen(....)
+
+// New with configuration struct
+app := iris.New(iris.Configuration{ DisablePathEscape: true})
+
+app.Listen(...)
+
+// Default station
+iris.Listen(...)
+
+// Default station with custom configuration
+iris.Config.DisablePathEscape = true
+
+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)`
+```go
+iris.ListenLETSENCRYPT(":8080")
+```
+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.FormValueString("name")
+ email := ctx.FormValueString("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.FormValueString("name")
+ email := ctx.FormValueString("email")
+ // Get avatar
+ avatar, err := ctx.FormFile("avatar")
+ if err != nil {
+ return err
+ }
+
+ // Source
+ src, err := avatar.Open()
+ if err != nil {
+ return err
+ }
+ defer src.Close()
+
+ // Destination
+ dst, err := os.Create(avatar.Filename)
+ if err != nil {
+ return err
+ }
+ defer dst.Close()
+
+ // Copy
+ if _, err = io.Copy(dst, src); err != nil {
+ return err
+ }
+
+ 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)
+ }
+ 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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/serialize-engines.html)
+
+### Static Content
+
+Serve files or directories, use the correct for your case, if you don't know which one, just use the `Static(relative string, systemPath string, stripSlashes int)`.
+
+```go
+// StaticHandler returns a HandlerFunc to serve static system directory
+// Accepts 5 parameters
+//
+// first param is the systemPath (string)
+// Path to the root directory to serve files from.
+//
+// second is the stripSlashes (int) level
+// * stripSlashes = 0, original path: "/foo/bar", result: "/foo/bar"
+// * stripSlashes = 1, original path: "/foo/bar", result: "/bar"
+// * stripSlashes = 2, original path: "/foo/bar", result: ""
+//
+// third is the compress (bool)
+// Transparently compresses responses if set to true.
+//
+// The server tries minimizing CPU usage by caching compressed files.
+// It adds FSCompressedFileSuffix suffix to the original file name and
+// tries saving the resulting compressed file under the new file name.
+// So it is advisable to give the server write access to Root
+// and to all inner folders in order to minimze CPU usage when serving
+// compressed responses.
+//
+// fourth is the generateIndexPages (bool)
+// Index pages for directories without files matching IndexNames
+// are automatically generated if set.
+//
+// Directory index generation may be quite slow for directories
+// with many files (more than 1K), so it is discouraged enabling
+// index pages' generation for such directories.
+//
+// fifth is the indexNames ([]string)
+// List of index file names to try opening during directory access.
+//
+// For example:
+//
+// * index.html
+// * index.htm
+// * my-super-index.xml
+//
+StaticHandler(systemPath string, stripSlashes int, compress bool,
+ generateIndexPages bool, indexNames []string) HandlerFunc
+
+// Static registers a route which serves a system directory
+// this doesn't generates an index page which list all files
+// no compression is used also, for these features look at StaticFS func
+// accepts three parameters
+// first parameter is the request url path (string)
+// second parameter is the system directory (string)
+// third parameter is the level (int) of stripSlashes
+// * stripSlashes = 0, original path: "/foo/bar", result: "/foo/bar"
+// * stripSlashes = 1, original path: "/foo/bar", result: "/bar"
+// * stripSlashes = 2, original path: "/foo/bar", result: ""
+Static(relative string, systemPath string, stripSlashes int)
+
+// StaticFS registers a route which serves a system directory
+// generates an index page which list all files
+// uses compression which file cache, if you use this method it will generate compressed files also
+// think this function as small fileserver with http
+// accepts three parameters
+// first parameter is the request url path (string)
+// second parameter is the system directory (string)
+// third parameter is the level (int) of stripSlashes
+// * stripSlashes = 0, original path: "/foo/bar", result: "/foo/bar"
+// * stripSlashes = 1, original path: "/foo/bar", result: "/bar"
+// * stripSlashes = 2, original path: "/foo/bar", result: ""
+StaticFS(relative string, systemPath string, stripSlashes int)
+
+// 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)
+// third parameter is the level (int) of stripSlashes
+// * stripSlashes = 0, original path: "/foo/bar", result: "/foo/bar"
+// * stripSlashes = 1, original path: "/foo/bar", result: "/bar"
+// * stripSlashes = 2, original path: "/foo/bar", result: ""
+StaticWeb(relative string, systemPath string, stripSlashes int)
+
+// 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.Static("/public", "./static/assets/", 1)
+//-> /public/assets/favicon.ico
+```
+
+```go
+iris.StaticFS("/ftp", "./myfiles/public", 1)
+```
+
+```go
+iris.StaticWeb("/","./my_static_html_website", 1)
+```
+
+```go
+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
+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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/plugin-editor.html) |
+| [Typescript Plugin](https://github.com/iris-contrib/plugin/tree/master/typescript) | Auto-compile client-side typescript files | [book section](https://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/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://kataras.gitbooks.io/iris/content/plugin-iriscontrol.html) |
+
+### 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.Write("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.Write("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.Write("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.Write("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")
+
+```
+
+> 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://kataras.gitbooks.io/iris/content/package-sessions.html)
+
+### Websockets
+
+```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.HostString()})
+ })
+
+ // 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($("