iris

package module
v10.7.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 29, 2018 License: BSD-3-Clause Imports: 27 Imported by: 0

README

Iris Web Framework

build status report card vscode-iris chat view examples release

Iris is a fast, simple yet fully featured and very efficient web framework for Go.

Iris provides a beautifully expressive and easy to use foundation for your next website or API.

Iris offers a complete and decent solution and support for all gophers around the globe.

Learn what others say about Iris and star this github repository to stay up to date.

Installation

The only requirement is the Go Programming Language

$ go get -u github.com/kataras/iris

Iris takes advantage of the vendor directory feature. You get truly reproducible builds, as this method guards against upstream renames and deletes.

Updated at: Tuesday, 21 November 2017

Benchmarks from third-party source over the rest web frameworks

Comparison with other frameworks

Known issues for code editors and IDEs at general
VS Code

For some reason the latest vscode-go language extension does not provide enough intelligence for the iris.Context type alias (input parameters documentation and definition navigation). Probably you have already experienced this issue with other Go libraries too, it is not an iris-specific issue, it is a general issue for all Golang type aliases.

Therefore if you use VS Code and you need these editor's features, import the original path; add an extra import statement of the original path of the Context, that will do it:

import (
    "github.com/kataras/iris"
    "github.com/kataras/iris/context" // <- HERE
)

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, so far, iris is the fastest web framework ever created in terms of performance.

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.

Quick start

# assume the following codes in example.go file
$ cat example.go
package main

import "github.com/kataras/iris"

func main() {
    app := iris.Default()
    app.Get("/ping", func(ctx iris.Context) {
        ctx.JSON(iris.Map{
            "message": "pong",
        })
    })
    // listen and serve on http://0.0.0.0:8080.
    app.Run(iris.Addr(":8080"))
}
# run example.go and visit http://0.0.0.0:8080/ping on browser
$ go run example.go

Dependency Injection

The package hero contains features for binding any object or functions that handlers can use, these are called dependencies.

With Iris you get truly safe bindings thanks to the hero package. It is blazing-fast, near to raw handlers performance because Iris calculates everything before even server goes online!

Below you will see some screenshots I prepared for you in order to be easier to understand:

1. Path Parameters - Built'n Dependencies

2. Services - Static Dependencies

3. Per-Request - Dynamic Dependencies

hero funcs are very easy to understand and when you start using them you never go back.

With Iris you also get real and blazing-fast MVC support which uses "hero" under the hoods.

API Examples

Using Get, Post, Put, Patch, Delete and Options
func main() {
    // Creates an application with default middleware:
    // logger and recovery (crash-free) middleware.
    app := iris.Default()

    app.Get("/someGet", getting)
    app.Post("/somePost", posting)
    app.Put("/somePut", putting)
    app.Delete("/someDelete", deleting)
    app.Patch("/somePatch", patching)
    app.Head("/someHead", head)
    app.Options("/someOptions", options)

    app.Run(iris.Addr(":8080"))
}
Parameters in path
func main() {
    app := iris.Default()

    // This handler will match /user/john but will not match neither /user/ or /user.
    app.Get("/user/{name}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        ctx.Writef("Hello %s", name)
    })

    // However, this one will match /user/john/ and also /user/john/send.
    app.Post("/user/{name:string}/{action:path}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        action := ctx.Params().Get("action")
        message := name + " is " + action
        ctx.WriteString(message)
    })

    app.Run(iris.Addr(":8080"))
}

If parameter type is missing then defaults to string, therefore {name:string} and {name} do the same exactly thing.

Learn more about path parameter's types by navigating here.

Querystring parameters
func main() {
    app := iris.Default()

    // Query string parameters are parsed using the existing underlying request object.
    // The request responds to a url matching:  /welcome?firstname=Jane&lastname=Doe.
    app.Get("/welcome", func(ctx iris.Context) {
        firstname := ctx.URLParamDefault("firstname", "Guest")
        // shortcut for ctx.Request().URL.Query().Get("lastname").
        lastname := ctx.URLParam("lastname") 

        ctx.Writef("Hello %s %s", firstname, lastname)
    })

    app.Run(iris.Addr(":8080"))
}
Multipart/Urlencoded Form
func main() {
    app := iris.Default()

    app.Post("/form_post", func(ctx iris.Context) {
        message := ctx.FormValue("message")
        nick := ctx.FormValueDefault("nick", "anonymous")

        ctx.JSON(iris.Map{
            "status":  "posted",
            "message": message,
            "nick":    nick,
        })
    })

    app.Run(iris.Addr(":8080"))
}
Another example: query + post form
POST /post?id=1234&page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=manu&message=this_is_great
func main() {
    app := iris.Default()

    app.Post("/post", func(ctx iris.Context) {
        id := ctx.URLParam("id")
        page := ctx.URLParamDefault("page", "0")
        name := ctx.FormValue("name")
        message := ctx.FormValue("message")
        // or `ctx.PostValue` for POST, PUT & PATCH-only HTTP Methods.

        app.Logger().Infof("id: %s; page: %s; name: %s; message: %s", id, page, name, message)
    })

    app.Run(iris.Addr(":8080"))
}
id: 1234; page: 1; name: manu; message: this_is_great
Extract Referer
package main

import (
    "github.com/kataras/iris"
    "github.com/kataras/iris/context"
)

func main() {
    app := iris.New()

    app.Get("/", func(ctx context.Context) /* or iris.Context, it's the same for Go 1.9+. */ {

        // request header "referer" or url parameter "referer".
        r := ctx.GetReferrer()
        switch r.Type {
        case context.ReferrerSearch:
            ctx.Writef("Search %s: %s\n", r.Label, r.Query)
            ctx.Writef("Google: %s\n", r.GoogleType)
        case context.ReferrerSocial:
            ctx.Writef("Social %s\n", r.Label)
        case context.ReferrerIndirect:
            ctx.Writef("Indirect: %s\n", r.URL)
        }
    })

    app.Run(iris.Addr(":8080"))
}

How to curl:

curl http://localhost:8080?referer=https://twitter.com/Xinterio/status/1023566830974251008
curl http://localhost:8080?referer=https://www.google.com/search?q=Top+6+golang+web+frameworks&oq=Top+6+golang+web+frameworks
Upload files
const maxSize = 5 << 20 // 5MB

func main() {
    app := iris.Default()
    app.Post("/upload", iris.LimitRequestBodySize(maxSize), func(ctx iris.Context) {
        //
        // UploadFormFiles
        // uploads any number of incoming files ("multiple" property on the form input).
        //

        // The second, optional, argument
        // can be used to change a file's name based on the request,
        // at this example we will showcase how to use it
        // by prefixing the uploaded file with the current user's ip.
        ctx.UploadFormFiles("./uploads", beforeSave)
    })

    app.Run(iris.Addr(":8080"))
}

func beforeSave(ctx iris.Context, file *multipart.FileHeader) {
    ip := ctx.RemoteAddr()
    // make sure you format the ip in a way
    // that can be used for a file name (simple case):
    ip = strings.Replace(ip, ".", "_", -1)
    ip = strings.Replace(ip, ":", "_", -1)

    // you can use the time.Now, to prefix or suffix the files
    // based on the current time as well, as an exercise.
    // i.e unixTime :=	time.Now().Unix()
    // prefix the Filename with the $IP-
    // no need for more actions, internal uploader will use this
    // name to save the file into the "./uploads" folder.
    file.Filename = ip + "-" + file.Filename
}

How to curl:

curl -X POST http://localhost:8080/upload \
  -F "files[]=@./myfile.zip" \
  -F "files[]=@./mysecondfile.zip" \
  -H "Content-Type: multipart/form-data"
Grouping routes
func main() {
	app := iris.Default()

	// Simple group: v1.
	v1 := app.Party("/v1")
	{
		v1.Post("/login", loginEndpoint)
		v1.Post("/submit", submitEndpoint)
		v1.Post("/read", readEndpoint)
	}

	// Simple group: v2.
	v2 := app.Party("/v2")
	{
		v2.Post("/login", loginEndpoint)
		v2.Post("/submit", submitEndpoint)
		v2.Post("/read", readEndpoint)
	}

	app.Run(iris.Addr(":8080"))
}
Blank Iris without middleware by default

Use

app := iris.New()

instead of

// Default with the Logger and Recovery middleware already attached.
app := iris.Default()
Using middleware
import (
    "github.com/kataras/iris"

    "github.com/kataras/iris/middleware/recover"
    "github.com/kataras/iris/middleware/logger"
)

func main() {
    // Creates an application without any middleware by default.
    app := iris.New()

    // Recover middleware recovers from any panics and writes a 500 if there was one.
    app.Use(recover.New())

    requestLogger := logger.New(logger.Config{
        // Status displays status code
        Status: true,
        // IP displays request's remote address
        IP: true,
        // Method displays the http method
        Method: true,
        // Path displays the request path
        Path: true,
        // Query appends the url query to the Path.
        Query: true,

        // if !empty then its contents derives from `ctx.Values().Get("logger_message")
        // will be added to the logs.
        MessageContextKeys: []string{"logger_message"},

        // if !empty then its contents derives from `ctx.GetHeader("User-Agent")
        MessageHeaderKeys: []string{"User-Agent"},
    })
    app.Use(requestLogger)

    // Per route middleware, you can add as many as you desire.
    app.Get("/benchmark", MyBenchLogger(), benchEndpoint)

    // Authorization party /user.
    // authorized := app.Party("/user", AuthRequired())
    // exactly the same as:
    authorized := app.Party("/user")
    // per party middleware! in this case we use the custom created
    // AuthRequired() middleware just in the "authorized" group/party.
    authorized.Use(AuthRequired())
    {
        authorized.Post("/login", loginEndpoint)
        authorized.Post("/submit", submitEndpoint)
        authorized.Post("/read", readEndpoint)

        // nested group: /user/testing
        testing := authorized.Party("/testing")
        testing.Get("/analytics", analyticsEndpoint)
    }

    // Listen and serve on http://0.0.0.0:8080
    app.Run(iris.Addr(":8080"))
}
How to write log file
package main

import (
	"os"
	"time"

	"github.com/kataras/iris"
)

// Get a filename based on the date, just for the sugar.
func todayFilename() string {
    today := time.Now().Format("Jan 02 2006")
    return today + ".txt"
}

func newLogFile() *os.File {
    filename := todayFilename()
    // Open the file, this will append to the today's file if server restarted.
    f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
    if err != nil {
        panic(err)
    }

    return f
}

func main() {
    f := newLogFile()
    defer f.Close()

    app := iris.New()
    // Attach the file as logger, remember, iris' app logger is just an io.Writer.
    // Use the following code if you need to write the logs to file and console at the same time.
    // app.Logger().SetOutput(io.MultiWriter(f, os.Stdout))
    app.Logger().SetOutput(f)

    app.Get("/ping", func(ctx iris.Context) {
        // for the sake of simplicity, in order see the logs at the ./_today_.txt
        ctx.Application().Logger().Infof("Request path: %s", ctx.Path())
        ctx.WriteString("pong")
    })

    // Navigate to http://localhost:8080/ping
    // and open the ./logs{TODAY}.txt file.
    app.Run(
        iris.Addr(":8080"),
        iris.WithoutBanner,
        iris.WithoutVersionChecker,
        iris.WithoutServerError(iris.ErrServerClosed),
    )
}
Model binding and validation

Iris uses go-playground/validator.v9 for validation. Check the full docs on tags usage here.

Example detail code.

Note that you need to set the corresponding binding tag on all fields you want to bind. For example, when binding from JSON, set json:"fieldname".

package main

import (
    "fmt"

    "github.com/kataras/iris"
    "gopkg.in/go-playground/validator.v9"
)

// User contains user information.
type User struct {
    FirstName      string     `json:"fname"`
    LastName       string     `json:"lname"`
    Age            uint8      `json:"age" validate:"gte=0,lte=130"`
    Email          string     `json:"email" validate:"required,email"`
    FavouriteColor string     `json:"favColor" validate:"hexcolor|rgb|rgba"`
    Addresses      []*Address `json:"addresses" validate:"required,dive,required"`
}

// Address houses a users address information.
type Address struct {
    Street string `json:"street" validate:"required"`
    City   string `json:"city" validate:"required"`
    Planet string `json:"planet" validate:"required"`
    Phone  string `json:"phone" validate:"required"`
}

// Use a single instance of Validate, it caches struct info.
var validate *validator.Validate

func main() {
    validate = validator.New()

    // Register validation for 'User'
    // NOTE: only have to register a non-pointer type for 'User', validator
    // interanlly dereferences during it's type checks.
    validate.RegisterStructValidation(UserStructLevelValidation, User{})

    app := iris.New()
    app.Post("/user", func(ctx iris.Context) {
        var user User
        if err := ctx.ReadJSON(&user); err != nil {
            // Handle error.
        }

        // Returns InvalidValidationError for bad validation input,
        // nil or ValidationErrors ( []FieldError )
        err := validate.Struct(user)
        if err != nil {

            // This check is only needed when your code could produce
            // an invalid value for validation such as interface with nil
            // value most including myself do not usually have code like this.
            if _, ok := err.(*validator.InvalidValidationError); ok {
                ctx.StatusCode(iris.StatusInternalServerError)
                ctx.WriteString(err.Error())
                return
            }

            ctx.StatusCode(iris.StatusBadRequest)
            for _, err := range err.(validator.ValidationErrors) {
                fmt.Println()
                fmt.Println(err.Namespace())
                fmt.Println(err.Field())
                fmt.Println(err.StructNamespace())
                fmt.Println(err.StructField())
                fmt.Println(err.Tag())
                fmt.Println(err.ActualTag())
                fmt.Println(err.Kind())
                fmt.Println(err.Type())
                fmt.Println(err.Value())
                fmt.Println(err.Param())
                fmt.Println()
            }

            return
        }

        // save user to database.
    })

    app.Run(iris.Addr(":8080"))
}

func UserStructLevelValidation(sl validator.StructLevel) {
    user := sl.Current().Interface().(User)

    if len(user.FirstName) == 0 && len(user.LastName) == 0 {
        sl.ReportError(user.FirstName, "FirstName", "fname", "fnameorlname", "")
        sl.ReportError(user.LastName, "LastName", "lname", "fnameorlname", "")
    }
}
{
    "fname": "",
    "lname": "",
    "age": 45,
    "email": "mail@example.com",
    "favColor": "#000",
    "addresses": [{
        "street": "Eavesdown Docks",
        "planet": "Persphone",
        "phone": "none",
        "city": "Unknown"
    }]
}
Websockets
package main

import (
    "fmt"

    "github.com/kataras/iris"
    "github.com/kataras/iris/websocket"
)

func main() {
    app := iris.New()

    app.Get("/", func(ctx iris.Context) {
        ctx.ServeFile("websockets.html", false) // second parameter: enable gzip?
    })

    setupWebsocket(app)

    // x2
    // http://localhost:8080
    // http://localhost:8080
    // write something, press submit, see the result.
    app.Run(iris.Addr(":8080"))
}

func setupWebsocket(app *iris.Application) {
    // create our echo websocket server
    ws := websocket.New(websocket.Config{
        ReadBufferSize:  1024,
        WriteBufferSize: 1024,
    })
    ws.OnConnection(handleConnection)

    // register the server on an endpoint.
    // see the inline javascript code in the websockets.html,
    // this endpoint is used to connect to the server.
    app.Get("/echo", ws.Handler())
    // serve the javascript built'n client-side library,
    // see websockets.html script tags, this path is used.
    app.Any("/iris-ws.js", websocket.ClientHandler())
}

func handleConnection(c websocket.Connection) {
	// Read events from browser
    c.On("chat", func(msg string) {
        // Print the message to the console, c.Context() is the iris's http context.
        fmt.Printf("%s sent: %s\n", c.Context().RemoteAddr(), msg)
        // Write message back to the client message owner with:
        // c.Emit("chat", msg)
        // Write message to all except this client with:
        c.To(websocket.Broadcast).Emit("chat", msg)
    })
}

websockets.html

<!-- the message's input -->
<input id="input" type="text" />

<!-- when clicked then an iris websocket event will be sent to the server,
at this example we registered the 'chat' -->
<button onclick="send()">Send</button>

<!-- the messages will be shown here -->
<pre id="output"></pre>
<!-- import the iris client-side library for browser-->
<script src="/iris-ws.js"></script>

<script>
    var scheme = document.location.protocol == "https:" ? "wss" : "ws";
    var port = document.location.port ? (":" + document.location.port) : "";
    // see app.Get("/echo", ws.Handler()) on main.go
    var wsURL = scheme + "://" + document.location.hostname + port+"/echo";

    var input = document.getElementById("input");
    var output = document.getElementById("output");

    // Ws comes from the auto-served '/iris-ws.js'
    var socket = new Ws(wsURL)
    socket.OnConnect(function () {
        output.innerHTML += "Status: Connected\n";
    });

    socket.OnDisconnect(function () {
        output.innerHTML += "Status: Disconnected\n";
    });

    // read events from the server
    socket.On("chat", function (msg) {
        addMessage(msg);
    });

    function send() {
        addMessage("Me: " + input.value); // write ourselves
        socket.Emit("chat", input.value); // send chat event data to the websocket server
        input.value = ""; // clear the input
    }

    function addMessage(msg) {
        output.innerHTML += msg + "\n";
    }
</script>

Navigate to the _examples/websocket folder for more.

Cookies

Are you looking about http sessions instead?

Let's write a simple application which will make use of the HTTP Cookies.

$ cat _examples/cookies/basic/main.go
package main

import "github.com/kataras/iris"

func newApp() *iris.Application {
    app := iris.New()

    // Set A Cookie.
    app.Get("/cookies/{name}/{value}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        value := ctx.Params().Get("value")

        ctx.SetCookieKV(name, value)

        ctx.Writef("cookie added: %s = %s", name, value)
    })

    // Retrieve A Cookie.
    app.Get("/cookies/{name}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")

        value := ctx.GetCookie(name)

        ctx.WriteString(value)
    })

    // Delete A Cookie.
    app.Delete("/cookies/{name}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")

        ctx.RemoveCookie(name)

        ctx.Writef("cookie %s removed", name)
    })

    return app
}

func main() {
    app := newApp()

    // GET:    http://localhost:8080/cookies/my_name/my_value
    // GET:    http://localhost:8080/cookies/my_name
    // DELETE: http://localhost:8080/cookies/my_name
    app.Run(iris.Addr(":8080"))
}
  • Alternatively, use a regular http.Cookie: ctx.SetCookie(&http.Cookie{...})
  • If you want to set custom the path: ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored")).
  • If you want to be available only to the current request path: ctx.SetCookieKV(name, value, iris.CookieCleanPath /* or iris.CookiePath("") */)
    • iris.CookieExpires(time.Duration)
    • iris.CookieHTTPOnly(false)
  • ctx.Request().Cookie(name) is also available, it's the net/http approach
  • Learn more about path parameter's types by clicking here.
Testing

Iris offers an incredible support for the httpexpect, a Testing Framework for web applications. However, you are able to use the standard Go's net/http/httptest package as well but in this example we will use the kataras/iris/httptest.

package main

import (
    "fmt"
    "testing"

    "github.com/kataras/iris/httptest"
)

// go test -v -run=TestCookiesBasic$
func TestCookiesBasic(t *testing.T) {
    app := newApp()
    e := httptest.New(t, app, httptest.URL("http://example.com"))

    cookieName, cookieValue := "my_cookie_name", "my_cookie_value"

    // Test Set A Cookie.
    t1 := e.GET(fmt.Sprintf("/cookies/%s/%s", cookieName, cookieValue)).Expect().Status(httptest.StatusOK)
    t1.Cookie(cookieName).Value().Equal(cookieValue) // validate cookie's existence, it should be there now.
    t1.Body().Contains(cookieValue)

    path := fmt.Sprintf("/cookies/%s", cookieName)

    // Test Retrieve A Cookie.
    t2 := e.GET(path).Expect().Status(httptest.StatusOK)
    t2.Body().Equal(cookieValue)

    // Test Remove A Cookie.
    t3 := e.DELETE(path).Expect().Status(httptest.StatusOK)
    t3.Body().Contains(cookieName)

    t4 := e.GET(path).Expect().Status(httptest.StatusOK)
    t4.Cookies().Empty()
    t4.Body().Empty()
}

Learn

First of all, the most correct way to begin with a web framework is to learn the basics of the programming language and the standard http capabilities, if your web application is a very simple personal project without performance and maintainability requirements you may want to proceed just with the standard packages. After that follow the guidelines:

  • Navigate through 100+1 examples and some iris starter kits we crafted for you
  • Read the godocs for any details
  • Prepare a cup of coffee or tea, whatever pleases you the most, and read some articles we found for you
Iris starter kits
  1. A basic web app built in Iris for Go
  2. A mini social-network created with the awesome Iris💖💖
  3. Iris isomorphic react/hot reloadable/redux/css-modules starter kit
  4. Demo project with react using typescript and Iris
  5. Self-hosted Localization Management Platform built with Iris and Angular
  6. Iris + Docker and Kubernetes
  7. Quickstart for Iris with Nanobox
  8. A Hasura starter project with a ready to deploy Golang hello-world web app with IRIS

Did you build something similar? Let us know!

Middleware

Iris has a great collection of handlers[1][2] that you can use side by side with your web apps. However you are not limited to them - you are free to use any third-party middleware that is compatible with the net/http package, _examples/convert-handlers will show you the way.

Iris, unlike others, is 100% compatible with the standards and that's why the majority of the big companies that adapt Go to their workflow, like a very famous US Television Network, trust Iris; it's up-to-date and it will be always aligned with the std net/http package which is modernized by the Go Authors on each new release of the Go Programming Language.

Articles
Video Courses

Support

  • HISTORY file is your best friend, it contains information about the latest features and changes
  • Did you happen to find a bug? Post it at github issues
  • Do you have any questions or need to speak with someone experienced to solve a problem at real-time? Join us to the community chat
  • Complete our form-based user experience report by clicking here
  • Do you like the framework? Tweet something about it! The People have spoken:
Get hired

There are many companies and start-ups looking for Go web developers with Iris experience as requirement, we are searching for you every day and we post those information via our facebook page, like the page to get notified, we have already posted some of them.

Backers

Thank you to all our backers! 🙏 Become a backer



For more information about contributing to the Iris project please check the CONTRIBUTING.md file.

List of all Contributors

License

Iris is licensed under the 3-Clause BSD License. Iris is 100% free and open-source software.

For any questions regarding the license please send e-mail.

Documentation

Overview

Package iris provides a beautifully expressive and easy to use foundation for your next website, API, or distributed app.

Source code and other details for the project are available at GitHub:

https://github.com/teamlint/iris

Current Version

10.7.0

Installation

The only requirement is the Go Programming Language, at least version 1.8 but 1.10 and above is highly recommended.

$ go get -u github.com/teamlint/iris

Example code:

package main

import "github.com/teamlint/iris"

// User is just a bindable object structure.
type User struct {
    Username  string `json:"username"`
    Firstname string `json:"firstname"`
    Lastname  string `json:"lastname"`
    City      string `json:"city"`
    Age       int    `json:"age"`
}

func main() {
    app := iris.New()

    // Define templates using the std html/template engine.
    // Parse and load all files inside "./views" folder with ".html" file extension.
    // Reload the templates on each request (development mode).
    app.RegisterView(iris.HTML("./views", ".html").Reload(true))

    // Register custom handler for specific http errors.
    app.OnErrorCode(iris.StatusInternalServerError, func(ctx iris.Context) {
        // .Values are used to communicate between handlers, middleware.
        errMessage := ctx.Values().GetString("error")
        if errMessage != "" {
            ctx.Writef("Internal server error: %s", errMessage)
            return
        }

        ctx.Writef("(Unexpected) internal server error")
    })

    app.Use(func(ctx iris.Context) {
        ctx.Application().Logger().Infof("Begin request for path: %s", ctx.Path())
        ctx.Next()
    })

    // app.Done(func(ctx iris.Context) {})

    // Method POST: http://localhost:8080/decode
    app.Post("/decode", func(ctx iris.Context) {
        var user User
        ctx.ReadJSON(&user)
        ctx.Writef("%s %s is %d years old and comes from %s", user.Firstname, user.Lastname, user.Age, user.City)
    })

    // Method GET: http://localhost:8080/encode
    app.Get("/encode", func(ctx iris.Context) {
        doe := User{
            Username:  "Johndoe",
            Firstname: "John",
            Lastname:  "Doe",
            City:      "Neither FBI knows!!!",
            Age:       25,
        }

        ctx.JSON(doe)
    })

    // Method GET: http://localhost:8080/profile/anytypeofstring
    app.Get("/profile/{username:string}", profileByUsername)

    // Want to use a custom regex expression instead?
    // Easy: app.Get("/profile/{username:string regexp(^[a-zA-Z ]+$)}")
    //
    // If parameter type is missing then it's string which accepts anything,
    // i.e: /{paramname} it's exactly the same as /{paramname:string}.

    usersRoutes := app.Party("/users", logThisMiddleware)
    {
        // Method GET: http://localhost:8080/users/42
        usersRoutes.Get("/{id:int min(1)}", getUserByID)
        // Method POST: http://localhost:8080/users/create
        usersRoutes.Post("/create", createUser)
    }

    // Listen for incoming HTTP/1.x & HTTP/2 clients on localhost port 8080.
    app.Run(iris.Addr(":8080"), iris.WithCharset("UTF-8"))
}

func logThisMiddleware(ctx iris.Context) {
    ctx.Application().Logger().Infof("Path: %s | IP: %s", ctx.Path(), ctx.RemoteAddr())

    // .Next is required to move forward to the chain of handlers,
    // if missing then it stops the execution at this handler.
    ctx.Next()
}

func profileByUsername(ctx iris.Context) {
    // .Params are used to get dynamic path parameters.
    username := ctx.Params().Get("username")
    ctx.ViewData("Username", username)
    // renders "./views/users/profile.html"
    // with {{ .Username }} equals to the username dynamic path parameter.
    ctx.View("users/profile.html")
}

func getUserByID(ctx iris.Context) {
    userID := ctx.Params().Get("id") // Or convert directly using: .Values().GetInt/GetInt64 etc...
    // your own db fetch here instead of user :=...
    user := User{Username: "username" + userID}

    ctx.XML(user)
}

func createUser(ctx iris.Context) {
    var user User
    err := ctx.ReadForm(&user)
    if err != nil {
        ctx.Values().Set("error", "creating user, read and parse form failed. "+err.Error())
        ctx.StatusCode(iris.StatusInternalServerError)
        return
    }
    // renders "./views/users/create_verification.html"
    // with {{ . }} equals to the User object, i.e {{ .Username }} , {{ .Firstname}} etc...
    ctx.ViewData("", user)
    ctx.View("users/create_verification.html")
}

Listening and gracefully shutdown

You can start the server(s) listening to any type of `net.Listener` or even `http.Server` instance. The method for initialization of the server should be passed at the end, via `Run` function.

Below you'll see some useful examples:

// Listening on tcp with network address 0.0.0.0:8080
app.Run(iris.Addr(":8080"))

// Same as before but using a custom http.Server which may be in use somewhere else too
app.Run(iris.Server(&http.Server{Addr:":8080"}))

// Using a custom net.Listener
l, err := net.Listen("tcp4", ":8080")
if err != nil {
    panic(err)
}
app.Run(iris.Listener(l))

// TLS using files
app.Run(iris.TLS("127.0.0.1:443", "mycert.cert", "mykey.key"))

// Automatic TLS
app.Run(iris.AutoTLS(":443", "example.com", "admin@example.com"))

// UNIX socket
if errOs := os.Remove(socketFile); errOs != nil && !os.IsNotExist(errOs) {
    app.Logger().Fatal(errOs)
}

l, err := net.Listen("unix", socketFile)

if err != nil {
    app.Logger().Fatal(err)
}

if err = os.Chmod(socketFile, mode); err != nil {
    app.Logger().Fatal(err)
}

app.Run(iris.Listener(l))

// Using any func() error,
// the responsibility of starting up a listener is up to you with this way,
// for the sake of simplicity we will use the
// ListenAndServe function of the `net/http` package.
app.Run(iris.Raw(&http.Server{Addr:":8080"}).ListenAndServe)

UNIX and BSD hosts can take advantage of the reuse port feature.

Example code:

package main

import (
    // Package tcplisten provides customizable TCP net.Listener with various
    // performance-related options:
    //
    //   - SO_REUSEPORT. This option allows linear scaling server performance
    //     on multi-CPU servers.
    //     See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details.
    //
    //   - TCP_DEFER_ACCEPT. This option expects the server reads from the accepted
    //     connection before writing to them.
    //
    //   - TCP_FASTOPEN. See https://lwn.net/Articles/508865/ for details.
    "github.com/valyala/tcplisten"

    "github.com/teamlint/iris"
)

// $ go get github.com/valyala/tcplisten
// $ go run main.go

func main() {
    app := iris.New()

    app.Get("/", func(ctx iris.Context) {
        ctx.HTML("<b>Hello World!</b>")
    })

    listenerCfg := tcplisten.Config{
        ReusePort:   true,
        DeferAccept: true,
        FastOpen:    true,
    }

    l, err := listenerCfg.NewListener("tcp", ":8080")
    if err != nil {
        panic(err)
    }

    app.Run(iris.Listener(l))
}

That's all with listening, you have the full control when you need it.

Let's continue by learning how to catch CONTROL+C/COMMAND+C or unix kill command and shutdown the server gracefully.

Gracefully Shutdown on CONTROL+C/COMMAND+C or when kill command sent is ENABLED BY-DEFAULT.

In order to manually manage what to do when app is interrupted, we have to disable the default behavior with the option `WithoutInterruptHandler` and register a new interrupt handler (globally, across all possible hosts).

Example code:

package main

import (
    stdContext "context"
    "time"

    "github.com/teamlint/iris"
)

func main() {
    app := iris.New()

    iris.RegisterOnInterrupt(func() {
        timeout := 5 * time.Second
        ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
        defer cancel()
        // close all hosts
        app.Shutdown(ctx)
    })

    app.Get("/", func(ctx iris.Context) {
        ctx.HTML(" <h1>hi, I just exist in order to see if the server is closed</h1>")
    })

    // http://localhost:8080
    app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler)
}

Hosts

Access to all hosts that serve your application can be provided by the `Application#Hosts` field, after the `Run` method.

But the most common scenario is that you may need access to the host before the `Run` method, there are two ways of gain access to the host supervisor, read below.

First way is to use the `app.NewHost` to create a new host and use one of its `Serve` or `Listen` functions to start the application via the `iris#Raw` Runner. Note that this way needs an extra import of the `net/http` package.

Example Code:

h := app.NewHost(&http.Server{Addr:":8080"})
h.RegisterOnShutdown(func(){
    println("terminate")
})

app.Run(iris.Raw(h.ListenAndServe))

Second, and probably easier way is to use the `host.Configurator`.

Note that this method requires an extra import statement of "github.com/teamlint/iris/core/host" when using go < 1.9, if you're targeting on go1.9 then you can use the `iris#Supervisor` and omit the extra host import.

All common `Runners` we saw earlier (`iris#Addr, iris#Listener, iris#Server, iris#TLS, iris#AutoTLS`) accept a variadic argument of `host.Configurator`, there are just `func(*host.Supervisor)`. Therefore the `Application` gives you the rights to modify the auto-created host supervisor through these.

Example Code:

package main

import (
    stdContext "context"
    "time"

    "github.com/teamlint/iris"
    "github.com/teamlint/iris/core/host"
)

func main() {
    app := iris.New()

    app.Get("/", func(ctx iris.Context) {
        ctx.HTML("<h1>Hello, try to refresh the page after ~10 secs</h1>")
    })

    app.Logger().Info("Wait 10 seconds and check your terminal again")
    // simulate a shutdown action here...
    go func() {
        <-time.After(10 * time.Second)
        timeout := 5 * time.Second
        ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
        defer cancel()
        // close all hosts, this will notify the callback we had register
        // inside the `configureHost` func.
        app.Shutdown(ctx)
    }()

    // start the server as usual, the only difference is that
    // we're adding a second (optional) function
    // to configure the just-created host supervisor.
    //
    // http://localhost:8080
    // wait 10 seconds and check your terminal.
    app.Run(iris.Addr(":8080", configureHost), iris.WithoutServerError(iris.ErrServerClosed))

}

func configureHost(su *host.Supervisor) {
    // here we have full access to the host that will be created
    // inside the `Run` function.
    //
    // we register a shutdown "event" callback
    su.RegisterOnShutdown(func() {
        println("terminate")
    })
    // su.RegisterOnError
    // su.RegisterOnServe
}

Read more about listening and gracefully shutdown by navigating to:

https://github.com/teamlint/iris/tree/master/_examples/#http-listening

Routing

All HTTP methods are supported, developers can also register handlers for same paths for different methods. The first parameter is the HTTP Method, second parameter is the request path of the route, third variadic parameter should contains one or more iris.Handler executed by the registered order when a user requests for that specific resouce path from the server.

Example code:

app := iris.New()

app.Handle("GET", "/contact", func(ctx iris.Context) {
    ctx.HTML("<h1> Hello from /contact </h1>")
})

In order to make things easier for the user, iris provides functions for all HTTP Methods. The first parameter is the request path of the route, second variadic parameter should contains one or more iris.Handler executed by the registered order when a user requests for that specific resouce path from the server.

Example code:

app := iris.New()

// Method: "GET"
app.Get("/", handler)

// Method: "POST"
app.Post("/", handler)

// Method: "PUT"
app.Put("/", handler)

// Method: "DELETE"
app.Delete("/", handler)

// Method: "OPTIONS"
app.Options("/", handler)

// Method: "TRACE"
app.Trace("/", handler)

// Method: "CONNECT"
app.Connect("/", handler)

// Method: "HEAD"
app.Head("/", handler)

// Method: "PATCH"
app.Patch("/", handler)

// register the route for all HTTP Methods
app.Any("/", handler)

func handler(ctx iris.Context){
    ctx.Writef("Hello from method: %s and path: %s", ctx.Method(), ctx.Path())
}

Grouping Routes

A set of routes that are being groupped by path prefix can (optionally) share the same middleware handlers and template layout. A group can have a nested group too.

`.Party` is being used to group routes, developers can declare an unlimited number of (nested) groups.

Example code:

users := app.Party("/users", myAuthMiddlewareHandler)

// http://myhost.com/users/42/profile
users.Get("/{id:int}/profile", userProfileHandler)
// http://myhost.com/users/messages/1
users.Get("/inbox/{id:int}", userMessageHandler)

Custom HTTP Errors

iris developers are able to register their own handlers for http statuses like 404 not found, 500 internal server error and so on.

Example code:

// when 404 then render the template $templatedir/errors/404.html
app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context){
    ctx.View("errors/404.html")
})

app.OnErrorCode(500, func(ctx iris.Context){
    // ...
})

Basic HTTP API

With the help of iris's expressionist router you can build any form of API you desire, with safety.

Example code:

package main

import "github.com/teamlint/iris"

func main() {
    app := iris.New()

    // registers a custom handler for 404 not found http (error) status code,
    // fires when route not found or manually by ctx.StatusCode(iris.StatusNotFound).
    app.OnErrorCode(iris.StatusNotFound, notFoundHandler)

    // GET -> HTTP Method
    // / -> Path
    // func(ctx iris.Context) -> The route's handler.
    //
    // Third receiver should contains the route's handler(s), they are executed by order.
    app.Handle("GET", "/", func(ctx iris.Context) {
        // navigate to the middle of $GOPATH/src/github.com/teamlint/iris/context/context.go
        // to overview all context's method (there a lot of them, read that and you will learn how iris works too)
        ctx.HTML("Hello from " + ctx.Path()) // Hello from /
    })

    app.Get("/home", func(ctx iris.Context) {
        ctx.Writef(`Same as app.Handle("GET", "/", [...])`)
    })

    app.Get("/donate", donateHandler, donateFinishHandler)

    // Pssst, don't forget dynamic-path example for more "magic"!
    app.Get("/api/users/{userid:int min(1)}", func(ctx iris.Context) {
        userID, err := ctx.Params().GetInt("userid")

        if err != nil {
            ctx.Writef("error while trying to parse userid parameter," +
                "this will never happen if :int is being used because if it's not integer it will fire Not Found automatically.")
            ctx.StatusCode(iris.StatusBadRequest)
            return
        }

        ctx.JSON(map[string]interface{}{
            // you can pass any custom structured go value of course.
            "user_id": userID,
        })
    })
    // app.Post("/", func(ctx iris.Context){}) -> for POST http method.
    // app.Put("/", func(ctx iris.Context){})-> for "PUT" http method.
    // app.Delete("/", func(ctx iris.Context){})-> for "DELETE" http method.
    // app.Options("/", func(ctx iris.Context){})-> for "OPTIONS" http method.
    // app.Trace("/", func(ctx iris.Context){})-> for "TRACE" http method.
    // app.Head("/", func(ctx iris.Context){})-> for "HEAD" http method.
    // app.Connect("/", func(ctx iris.Context){})-> for "CONNECT" http method.
    // app.Patch("/", func(ctx iris.Context){})-> for "PATCH" http method.
    // app.Any("/", func(ctx iris.Context){}) for all http methods.

    // More than one route can contain the same path with a different http mapped method.
    // You can catch any route creation errors with:
    // route, err := app.Get(...)
    // set a name to a route: route.Name = "myroute"

    // You can also group routes by path prefix, sharing middleware(s) and done handlers.

    adminRoutes := app.Party("/admin", adminMiddleware)

    adminRoutes.Done(func(ctx iris.Context) { // executes always last if ctx.Next()
        ctx.Application().Logger().Infof("response sent to " + ctx.Path())
    })
    // adminRoutes.Layout("/views/layouts/admin.html") // set a view layout for these routes, see more at view examples.

    // GET: http://localhost:8080/admin
    adminRoutes.Get("/", func(ctx iris.Context) {
        // [...]
        ctx.StatusCode(iris.StatusOK) // default is 200 == iris.StatusOK
        ctx.HTML("<h1>Hello from admin/</h1>")

        ctx.Next() // in order to execute the party's "Done" Handler(s)
    })

    // GET: http://localhost:8080/admin/login
    adminRoutes.Get("/login", func(ctx iris.Context) {
        // [...]
    })
    // POST: http://localhost:8080/admin/login
    adminRoutes.Post("/login", func(ctx iris.Context) {
        // [...]
    })

    // subdomains, easier than ever, should add localhost or 127.0.0.1 into your hosts file,
    // etc/hosts on unix or C:/windows/system32/drivers/etc/hosts on windows.
    v1 := app.Party("v1.")
    { // braces are optional, it's just type of style, to group the routes visually.

        // http://v1.localhost:8080
        v1.Get("/", func(ctx iris.Context) {
            ctx.HTML("Version 1 API. go to <a href='" + ctx.Path() + "/api" + "'>/api/users</a>")
        })

        usersAPI := v1.Party("/api/users")
        {
            // http://v1.localhost:8080/api/users
            usersAPI.Get("/", func(ctx iris.Context) {
                ctx.Writef("All users")
            })
            // http://v1.localhost:8080/api/users/42
            usersAPI.Get("/{userid:int}", func(ctx iris.Context) {
                ctx.Writef("user with id: %s", ctx.Params().Get("userid"))
            })
        }
    }

    // wildcard subdomains.
    wildcardSubdomain := app.Party("*.")
    {
        wildcardSubdomain.Get("/", func(ctx iris.Context) {
            ctx.Writef("Subdomain can be anything, now you're here from: %s", ctx.Subdomain())
        })
    }

    // http://localhost:8080
    // http://localhost:8080/home
    // http://localhost:8080/donate
    // http://localhost:8080/api/users/42
    // http://localhost:8080/admin
    // http://localhost:8080/admin/login
    //
    // http://localhost:8080/api/users/0
    // http://localhost:8080/api/users/blabla
    // http://localhost:8080/wontfound
    //
    // if hosts edited:
    //  http://v1.localhost:8080
    //  http://v1.localhost:8080/api/users
    //  http://v1.localhost:8080/api/users/42
    //  http://anything.localhost:8080
    app.Run(iris.Addr(":8080"))
}

func adminMiddleware(ctx iris.Context) {
    // [...]
    ctx.Next() // to move to the next handler, or don't that if you have any auth logic.
}

func donateHandler(ctx iris.Context) {
    ctx.Writef("Just like an inline handler, but it can be " +
        "used by other package, anywhere in your project.")

    // let's pass a value to the next handler
    // Values is the way handlers(or middleware) are communicating between each other.
    ctx.Values().Set("donate_url", "https://github.com/teamlint/iris#-people")
    ctx.Next() // in order to execute the next handler in the chain, look donate route.
}

func donateFinishHandler(ctx iris.Context) {
    // values can be any type of object so we could cast the value to a string
    // but iris provides an easy to do that, if donate_url is not defined, then it returns an empty string instead.
    donateURL := ctx.Values().GetString("donate_url")
    ctx.Application().Logger().Infof("donate_url value was: " + donateURL)
    ctx.Writef("\n\nDonate sent(?).")
}

func notFoundHandler(ctx iris.Context) {
    ctx.HTML("Custom route for 404 not found http code, here you can render a view, html, json <b>any valid response</b>.")
}

Parameterized Path

At the previous example, we've seen static routes, group of routes, subdomains, wildcard subdomains, a small example of parameterized path with a single known parameter and custom http errors, now it's time to see wildcard parameters and macros.

iris, like net/http std package registers route's handlers by a Handler, the iris' type of handler is just a func(ctx iris.Context) where context comes from github.com/teamlint/iris/context.

Iris has the easiest and the most powerful routing process you have ever meet.

At the same time, iris has its own interpeter(yes like a programming language) for route's path syntax and their dynamic path parameters parsing and evaluation, We call them "macros" for shortcut. How? It calculates its needs and if not any special regexp needed then it just registers the route with the low-level path syntax, otherwise it pre-compiles the regexp and adds the necessary middleware(s).

Standard macro types for parameters:

+------------------------+
| {param:string}         |
+------------------------+
string type
anything

+------------------------+
| {param:int}            |
+------------------------+
int type
only numbers (0-9)

+------------------------+
| {param:long}           |
+------------------------+
int64 type
only numbers (0-9)

+------------------------+
| {param:boolean}        |
+------------------------+
bool type
only "1" or "t" or "T" or "TRUE" or "true" or "True"
or "0" or "f" or "F" or "FALSE" or "false" or "False"

+------------------------+
| {param:alphabetical}   |
+------------------------+
alphabetical/letter type
letters only (upper or lowercase)

+------------------------+
| {param:file}           |
+------------------------+
file type
letters (upper or lowercase)
numbers (0-9)
underscore (_)
dash (-)
point (.)
no spaces ! or other character

+------------------------+
| {param:path}           |
+------------------------+
path type
anything, should be the last part, more than one path segment,
i.e: /path1/path2/path3 , ctx.Params().Get("param") == "/path1/path2/path3"

if type is missing then parameter's type is defaulted to string, so {param} == {param:string}.

If a function not found on that type then the "string"'s types functions are being used. i.e:

{param:int min(3)}

Besides the fact that iris provides the basic types and some default "macro funcs" you are able to register your own too!.

Register a named path parameter function:

app.Macros().Int.RegisterFunc("min", func(argument int) func(paramValue string) bool {
    [...]
    return true/false -> true means valid.
})

at the func(argument ...) you can have any standard type, it will be validated before the server starts so don't care about performance here, the only thing it runs at serve time is the returning func(paramValue string) bool.

{param:string equal(iris)} , "iris" will be the argument here:
app.Macros().String.RegisterFunc("equal", func(argument string) func(paramValue string) bool {
    return func(paramValue string){ return argument == paramValue }
})

Example Code:

	// you can use the "string" type which is valid for a single path parameter that can be anything.
	app.Get("/username/{name}", func(ctx iris.Context) {
		ctx.Writef("Hello %s", ctx.Params().Get("name"))
	}) // type is missing = {name:string}

	// Let's register our first macro attached to int macro type.
	// "min" = the function
	// "minValue" = the argument of the function
	// func(string) bool = the macro's path parameter evaluator, this executes in serve time when
	// a user requests a path which contains the :int macro type with the min(...) macro parameter function.
	app.Macros().Int.RegisterFunc("min", func(minValue int) func(string) bool {
		// do anything before serve here [...]
		// at this case we don't need to do anything
		return func(paramValue string) bool {
			n, err := strconv.Atoi(paramValue)
			if err != nil {
				return false
			}
			return n >= minValue
		}
	})

	// http://localhost:8080/profile/id>=1
	// this will throw 404 even if it's found as route on : /profile/0, /profile/blabla, /profile/-1
	// macro parameter functions are optional of course.
	app.Get("/profile/{id:int min(1)}", func(ctx iris.Context) {
		// second parameter is the error but it will always nil because we use macros,
		// the validaton already happened.
		id, _ := ctx.Params().GetInt("id")
		ctx.Writef("Hello id: %d", id)
	})

	// to change the error code per route's macro evaluator:
	app.Get("/profile/{id:int min(1)}/friends/{friendid:int min(1) else 504}", func(ctx iris.Context) {
		id, _ := ctx.Params().GetInt("id")
		friendid, _ := ctx.Params().GetInt("friendid")
		ctx.Writef("Hello id: %d looking for friend id: ", id, friendid)
	}) // this will throw e 504 error code instead of 404 if all route's macros not passed.

	// http://localhost:8080/game/a-zA-Z/level/0-9
	// remember, alphabetical is lowercase or uppercase letters only.
	app.Get("/game/{name:alphabetical}/level/{level:int}", func(ctx iris.Context) {
		ctx.Writef("name: %s | level: %s", ctx.Params().Get("name"), ctx.Params().Get("level"))
	})

	// let's use a trivial custom regexp that validates a single path parameter
	// which its value is only lowercase letters.

	// http://localhost:8080/lowercase/anylowercase
	app.Get("/lowercase/{name:string regexp(^[a-z]+)}", func(ctx iris.Context) {
		ctx.Writef("name should be only lowercase, otherwise this handler will never executed: %s", ctx.Params().Get("name"))
	})

	// http://localhost:8080/single_file/app.js
	app.Get("/single_file/{myfile:file}", func(ctx iris.Context) {
		ctx.Writef("file type validates if the parameter value has a form of a file name, got: %s", ctx.Params().Get("myfile"))
	})

	// http://localhost:8080/myfiles/any/directory/here/
	// this is the only macro type that accepts any number of path segments.
	app.Get("/myfiles/{directory:path}", func(ctx iris.Context) {
		ctx.Writef("path type accepts any number of path segments, path after /myfiles/ is: %s", ctx.Params().Get("directory"))
    })

	app.Run(iris.Addr(":8080"))
}

A path parameter name should contain only alphabetical letters, symbols, containing '_' and numbers are NOT allowed. If route failed to be registered, the app will panic without any warnings if you didn't catch the second return value(error) on .Handle/.Get....

Last, do not confuse ctx.Values() with ctx.Params(). Path parameter's values goes to ctx.Params() and context's local storage that can be used to communicate between handlers and middleware(s) goes to ctx.Values(), path parameters and the rest of any custom values are separated for your own good.

Run

$ go run main.go

Static Files

// 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 and HEAD method routes.
// If second parameter is empty, otherwise the requestPath is the second parameter
// it uses gzip compression (compression on each request, no file cache).
//
// Returns the GET *Route.
StaticServe(systemPath string, requestPath ...string) (*Route, error)

// StaticContent registers a GET and HEAD method routes to the requestPath
// that are ready to serve raw static bytes, memory cached.
//
// Returns the GET *Route.
StaticContent(reqPath string, cType string, content []byte) (*Route, error)

// 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.
//
// Returns the GET *Route.
//
// Example: https://github.com/teamlint/iris/tree/master/_examples/file-server/embedding-files-into-app
StaticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) (*Route, error)

// 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).
//
// Returns the GET *Route.
Favicon(favPath string, requestPath ...string) (*Route, error)

// StaticWeb returns a handler that serves HTTP requests
// with the contents of the file system rooted at directory.
//
// first parameter: the route path
// second parameter: the system directory
// third OPTIONAL parameter: the exception routes
//      (= give priority to these routes instead of the static handler)
// for more options look app.StaticHandler.
//
//     app.StaticWeb("/static", "./static")
//
// As a special case, the returned file server redirects any request
// ending in "/index.html" to the same path, without the final
// "index.html".
//
// StaticWeb calls the StaticHandler(systemPath, listingDirectories: false, gzip: false ).
//
// Returns the GET *Route.
StaticWeb(requestPath string, systemPath string, exceptRoutes ...*Route) (*Route, error)

Example code:

package main

import "github.com/teamlint/iris"

func main() {
    app := iris.New()

    // This will serve the ./static/favicons/ion_32_32.ico to: localhost:8080/favicon.ico
    app.Favicon("./static/favicons/ion_32_32.ico")

    // app.Favicon("./static/favicons/ion_32_32.ico", "/favicon_48_48.ico")
    // This will serve the ./static/favicons/ion_32_32.ico to: localhost:8080/favicon_48_48.ico

    app.Get("/", func(ctx iris.Context) {
        ctx.HTML(`<a href="/favicon.ico"> press here to see the favicon.ico</a>.
        At some browsers like chrome, it should be visible at the top-left side of the browser's window,
        because some browsers make requests to the /favicon.ico automatically,
        so iris serves your favicon in that path too (you can change it).`)
    }) // if favicon doesn't show to you, try to clear your browser's cache.

    app.Run(iris.Addr(":8080"))
}

More examples can be found here: https://github.com/teamlint/iris/tree/master/_examples/beginner/file-server

Middleware Ecosystem

Middleware is just a concept of ordered chain of handlers. Middleware can be registered globally, per-party, per-subdomain and per-route.

Example code:

// globally
// before any routes, appends the middleware to all routes
app.Use(func(ctx iris.Context){
   // ... any code here

   ctx.Next() // in order to continue to the next handler,
   // if that is missing then the next in chain handlers will be not executed,
   // useful for authentication middleware
})

// globally
// after or before any routes, prepends the middleware to all routes
app.UseGlobal(handler1, handler2, handler3)

// per-route
app.Post("/login", authenticationHandler, loginPageHandler)

// per-party(group of routes)
users := app.Party("/users", usersMiddleware)
users.Get("/", usersIndex)

// per-subdomain
mysubdomain := app.Party("mysubdomain.", firstMiddleware)
mysubdomain.Use(secondMiddleware)
mysubdomain.Get("/", mysubdomainIndex)

// per wildcard, dynamic subdomain
dynamicSub := app.Party(".*", firstMiddleware, secondMiddleware)
dynamicSub.Get("/", func(ctx iris.Context){
  ctx.Writef("Hello from subdomain: "+ ctx.Subdomain())
})

iris is able to wrap and convert any external, third-party Handler you used to use to your web application. Let's convert the https://github.com/rs/cors net/http external middleware which returns a `next form` handler.

Example code:

package main

import (
    "github.com/rs/cors"

    "github.com/teamlint/iris"
)

func main() {

    app := iris.New()
    corsOptions := cors.Options{
        AllowedOrigins:   []string{"*"},
        AllowCredentials: true,
    }

    corsWrapper := cors.New(corsOptions).ServeHTTP

    app.WrapRouter(corsWrapper)

    v1 := app.Party("/api/v1")
    {
        v1.Get("/", h)
        v1.Put("/put", h)
        v1.Post("/post", h)
    }

    app.Run(iris.Addr(":8080"))
}

func h(ctx iris.Context) {
    ctx.Application().Logger().Infof(ctx.Path())
    ctx.Writef("Hello from %s", ctx.Path())
}

View Engine

Iris supports 5 template engines out-of-the-box, developers can still use any external golang template engine, as `context/context#ResponseWriter()` is an `io.Writer`.

All of these five template engines have common features with common API, like Layout, Template Funcs, Party-specific layout, partial rendering and more.

The standard html,
its template parser is the golang.org/pkg/html/template/

Django,
its template parser is the github.com/flosch/pongo2

Pug(Jade),
its template parser is the github.com/Joker/jade

Handlebars,
its template parser is the github.com/aymerick/raymond

Amber,
its template parser is the github.com/eknkc/amber

Example code:

package main

import "github.com/teamlint/iris"

func main() {
    app := iris.New()

    // - standard html  | iris.HTML(...)
    // - django         | iris.Django(...)
    // - pug(jade)      | iris.Pug(...)
    // - handlebars     | iris.Handlebars(...)
    // - amber          | iris.Amber(...)

    tmpl := iris.HTML("./templates", ".html")
    tmpl.Reload(true) // reload templates on each request (development mode)
    // default template funcs are:
    //
    // - {{ urlpath "mynamedroute" "pathParameter_ifneeded" }}
    // - {{ render "header.html" }}
    // - {{ render_r "header.html" }} // partial relative path to current page
    // - {{ yield }}
    // - {{ current }}

    // register a custom template func.
    tmpl.AddFunc("greet", func(s string) string {
        return "Greetings " + s + "!"
    })

    // register the view engine to the views, this will load the templates.
    app.RegisterView(tmpl)

    app.Get("/", hi)

    // http://localhost:8080
    app.Run(iris.Addr(":8080"), iris.WithCharset("UTF-8")) // defaults to that but you can change it.
}

func hi(ctx iris.Context) {
    ctx.ViewData("Title", "Hi Page")
    ctx.ViewData("Name", "iris") // {{.Name}} will render: iris
    // ctx.ViewData("", myCcustomStruct{})
    ctx.View("hi.html")
}

View engine supports bundled(https://github.com/shuLhan/go-bindata) template files too. go-bindata gives you two functions, asset and assetNames, these can be setted to each of the template engines using the `.Binary` func.

Example code:

package main

import "github.com/teamlint/iris"

func main() {
    app := iris.New()
    // $ go get -u github.com/shuLhan/go-bindata/...
    // $ go-bindata ./templates/...
    // $ go build
    // $ ./embedding-templates-into-app
    // html files are not used, you can delete the folder and run the example
    app.RegisterView(iris.HTML("./templates", ".html").Binary(Asset, AssetNames))
    app.Get("/", hi)

    // http://localhost:8080
    app.Run(iris.Addr(":8080"))
}

type page struct {
    Title, Name string
}

func hi(ctx iris.Context) {
    ctx.ViewData("", page{Title: "Hi Page", Name: "iris"})
    ctx.View("hi.html")
}

A real example can be found here: https://github.com/teamlint/iris/tree/master/_examples/view/embedding-templates-into-app.

Enable auto-reloading of templates on each request. Useful while developers are in dev mode as they no neeed to restart their app on every template edit.

Example code:

pugEngine := iris.Pug("./templates", ".jade")
pugEngine.Reload(true) // <--- set to true to re-build the templates on each request.
app.RegisterView(pugEngine)

Note:

In case you're wondering, the code behind the view engines derives from the "github.com/teamlint/iris/view" package, access to the engines' variables can be granded by "github.com/teamlint/iris" package too.

iris.HTML(...) is a shortcut of view.HTML(...)
iris.Django(...)     >> >>      view.Django(...)
iris.Pug(...)        >> >>      view.Pug(...)
iris.Handlebars(...) >> >>      view.Handlebars(...)
iris.Amber(...)      >> >>      view.Amber(...)

Each one of these template engines has different options located here: https://github.com/teamlint/iris/tree/master/view .

Sessions

This example will show how to store and access data from a session.

You don’t need any third-party library, but If you want you can use any session manager compatible or not.

In this example we will only allow authenticated users to view our secret message on the /secret page. To get access to it, the will first have to visit /login to get a valid session cookie, which logs him in. Additionally he can visit /logout to revoke his access to our secret message.

Example code:

// main.go
package main

import (
    "github.com/teamlint/iris"

    "github.com/teamlint/iris/sessions"
)

var (
    cookieNameForSessionID = "mycookiesessionnameid"
    sess                   = sessions.New(sessions.Config{Cookie: cookieNameForSessionID})
)

func secret(ctx iris.Context) {

    // Check if user is authenticated
    if auth, _ := sess.Start(ctx).GetBoolean("authenticated"); !auth {
        ctx.StatusCode(iris.StatusForbidden)
        return
    }

    // Print secret message
    ctx.WriteString("The cake is a lie!")
}

func login(ctx iris.Context) {
    session := sess.Start(ctx)

    // Authentication goes here
    // ...

    // Set user as authenticated
    session.Set("authenticated", true)
}

func logout(ctx iris.Context) {
    session := sess.Start(ctx)

    // Revoke users authentication
    session.Set("authenticated", false)
}

func main() {
    app := iris.New()

    app.Get("/secret", secret)
    app.Get("/login", login)
    app.Get("/logout", logout)

    app.Run(iris.Addr(":8080"))
}

Running the example:

$ go get github.com/teamlint/iris/sessions
$ go run main.go

$ curl -s http://localhost:8080/secret
Forbidden

$ curl -s -I http://localhost:8080/login
Set-Cookie: mycookiesessionnameid=MTQ4NzE5Mz...

$ curl -s --cookie "mycookiesessionnameid=MTQ4NzE5Mz..." http://localhost:8080/secret
The cake is a lie!

Sessions persistence can be achieved using one (or more) `sessiondb`.

Example Code:

package main

import (
    "time"

    "github.com/teamlint/iris"

    "github.com/teamlint/iris/sessions"
    "github.com/teamlint/iris/sessions/sessiondb/redis"
    "github.com/teamlint/iris/sessions/sessiondb/redis/service"
)

// tested with redis version 3.0.503.
// for windows see: https://github.com/ServiceStack/redis-windows
func main() {
    // replace with your running redis' server settings:
    db := redis.New(service.Config{
        Network:     service.DefaultRedisNetwork,
        Addr:        service.DefaultRedisAddr,
        Password:    "",
        Database:    "",
        MaxIdle:     0,
        MaxActive:   0,
        IdleTimeout: service.DefaultRedisIdleTimeout,
        Prefix:      ""}) // optionally configure the bridge between your redis server

    // close connection when control+C/cmd+C
    iris.RegisterOnInterrupt(func() {
        db.Close()
    })

    defer db.Close() // close the database connection if application errored.

    sess := sessions.New(sessions.Config{
        Cookie:  "sessionscookieid",
        Expires: 45 * time.Minute}, // <=0 means unlimited life. Defaults to 0.
    )

    //
    // IMPORTANT:
    //
    sess.UseDatabase(db)

    // the rest of the code stays the same.
    app := iris.New()

    app.Get("/", func(ctx iris.Context) {
        ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
    })
    app.Get("/set", func(ctx iris.Context) {
        s := sess.Start(ctx)
        //set session values
        s.Set("name", "iris")

        //test if setted here
        ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name"))
    })

    app.Get("/set/{key}/{value}", func(ctx iris.Context) {
        key, value := ctx.Params().Get("key"), ctx.Params().Get("value")
        s := sess.Start(ctx)
        // set session values
        s.Set(key, value)

        // test if setted here
        ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key))
    })

    app.Get("/get", func(ctx iris.Context) {
        // get a specific key, as string, if no found returns just an empty string
        name := sess.Start(ctx).GetString("name")

        ctx.Writef("The 'name' on the /set was: %s", name)
    })

    app.Get("/get/{key}", func(ctx iris.Context) {
        // get a specific key, as string, if no found returns just an empty string
        name := sess.Start(ctx).GetString(ctx.Params().Get("key"))

        ctx.Writef("The name on the /set was: %s", name)
    })

    app.Get("/delete", func(ctx iris.Context) {
        // delete a specific key
        sess.Start(ctx).Delete("name")
    })

    app.Get("/clear", func(ctx iris.Context) {
        // removes all entries
        sess.Start(ctx).Clear()
    })

    app.Get("/destroy", func(ctx iris.Context) {
        //destroy, removes the entire session data and cookie
        sess.Destroy(ctx)
    })

    app.Get("/update", func(ctx iris.Context) {
        // updates expire date with a new date
        sess.ShiftExpiration(ctx)
    })

    app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
}

More examples:

https://github.com/teamlint/iris/tree/master/_examples/sessions

Websockets

In this example we will create a small chat between web sockets via browser.

Example Server Code:

// main.go
package main

import (
    "fmt"

    "github.com/teamlint/iris"

    "github.com/teamlint/iris/websocket"
)

func main() {
    app := iris.New()

    app.Get("/", func(ctx iris.Context) {
        ctx.ServeFile("websockets.html", false) // second parameter: enable gzip?
    })

    setupWebsocket(app)

    // x2
    // http://localhost:8080
    // http://localhost:8080
    // write something, press submit, see the result.
    app.Run(iris.Addr(":8080"))
}

func setupWebsocket(app *iris.Application) {
    // create our echo websocket server
    ws := websocket.New(websocket.Config{
        ReadBufferSize:  1024,
        WriteBufferSize: 1024,
    })
    ws.OnConnection(handleConnection)

    // register the server on an endpoint.
    // see the inline javascript code i the websockets.html, this endpoint is used to connect to the server.
    app.Get("/echo", ws.Handler())

    // serve the javascript built'n client-side library,
    // see websockets.html script tags, this path is used.
    app.Any("/iris-ws.js", func(ctx iris.Context) {
        ctx.Write(websocket.ClientSource)
    })
}

func handleConnection(c websocket.Connection) {
    // Read events from browser
    c.On("chat", func(msg string) {
        // Print the message to the console, c.Context() is the iris's http context.
        fmt.Printf("%s sent: %s\n", c.Context().RemoteAddr(), msg)
        // Write message back to the client message owner:
        // c.Emit("chat", msg)
        c.To(websocket.Broadcast).Emit("chat", msg)
    })
}

Example Client(javascript) Code:

<!-- websockets.html -->
<input id="input" type="text" />
<button onclick="send()">Send</button>
<pre id="output"></pre>
<script src="/iris-ws.js"></script>
<script>
    var input = document.getElementById("input");
    var output = document.getElementById("output");

    // Ws comes from the auto-served '/iris-ws.js'
    var socket = new Ws("ws://localhost:8080/echo");
    socket.OnConnect(function () {
        output.innerHTML += "Status: Connected\n";
    });

    socket.OnDisconnect(function () {
        output.innerHTML += "Status: Disconnected\n";
    });

    // read events from the server
    socket.On("chat", function (msg) {
        addMessage(msg)
    });

    function send() {
        addMessage("Me: "+input.value) // write ourselves
        socket.Emit("chat", input.value);// send chat event data to the websocket server
        input.value = ""; // clear the input
    }

    function addMessage(msg) {
        output.innerHTML += msg + "\n";
    }
</script>

Running the example:

$ go get github.com/teamlint/iris/websocket
$ go run main.go
$ start http://localhost:8080

MVC - Model View Controller

Iris has first-class support for the MVC pattern, you'll not find these stuff anywhere else in the Go world.

Example Code:

package main

import (
    "github.com/teamlint/iris"
    "github.com/teamlint/iris/mvc"

    "github.com/teamlint/iris/middleware/logger"
    "github.com/teamlint/iris/middleware/recover"
)

func main() {
    app := iris.New()
    // Optionally, add two built'n handlers
    // that can recover from any http-relative panics
    // and log the requests to the terminal.
    app.Use(recover.New())
    app.Use(logger.New())

    // Serve a controller based on the root Router, "/".
    mvc.New(app).Handle(new(ExampleController))

    // http://localhost:8080
    // http://localhost:8080/ping
    // http://localhost:8080/hello
    // http://localhost:8080/custom_path
    app.Run(iris.Addr(":8080"))
}

// ExampleController serves the "/", "/ping" and "/hello".
type ExampleController struct{}

// Get serves
// Method:   GET
// Resource: http://localhost:8080
func (c *ExampleController) Get() mvc.Result {
    return mvc.Response{
        ContentType: "text/html",
        Text:        "<h1>Welcome</h1>",
    }
}

// GetPing serves
// Method:   GET
// Resource: http://localhost:8080/ping
func (c *ExampleController) GetPing() string {
    return "pong"
}

// GetHello serves
// Method:   GET
// Resource: http://localhost:8080/hello
func (c *ExampleController) GetHello() interface{} {
    return map[string]string{"message": "Hello Iris!"}
}

// GetUserBy serves // Method: GET // Resource: http://localhost:8080/user/{username:string} // By is a reserved "keyword" to tell the framework that you're going to // bind path parameters in the function's input arguments, and it also // helps to have "Get" and "GetBy" in the same controller. // // func (c *ExampleController) GetUserBy(username string) mvc.Result { // return mvc.View{ // Name: "user/username.html", // Data: username, // } // }

Can use more than one, the factory will make sure that the correct http methods are being registered for each route for this controller, uncomment these if you want:

func (c *ExampleController) Post() {}
func (c *ExampleController) Put() {}
func (c *ExampleController) Delete() {}
func (c *ExampleController) Connect() {}
func (c *ExampleController) Head() {}
func (c *ExampleController) Patch() {}
func (c *ExampleController) Options() {}
func (c *ExampleController) Trace() {}

func (c *ExampleController) All() {}
//        OR
func (c *ExampleController) Any() {}

func (c *ExampleController) BeforeActivation(b mvc.BeforeActivation) {
    // 1 -> the HTTP Method
    // 2 -> the route's path
    // 3 -> this controller's method name that should be handler for that route.
    b.Handle("GET", "/mypath/{param}", "DoIt", optionalMiddlewareHere...)
}

// After activation, all dependencies are set-ed - so read only access on them
// but still possible to add custom controller or simple standard handlers.
func (c *ExampleController) AfterActivation(a mvc.AfterActivation) {}

Iris web framework supports Request data, Models, Persistence Data and Binding with the fastest possible execution.

Characteristics:

All HTTP Methods are supported, for example if want to serve `GET` then the controller should have a function named `Get()`, you can define more than one method function to serve in the same Controller.

Register custom controller's struct's methods as handlers with custom paths(even with regex parametermized path) via the `BeforeActivation` custom event callback, per-controller. Example:

package main

import (
    "github.com/teamlint/iris"
    "github.com/teamlint/iris/mvc"
)

func main() {
    app := iris.New()
    mvc.Configure(app.Party("/root"), myMVC)
    app.Run(iris.Addr(":8080"))
}

func myMVC(app *mvc.Application) {
    // app.Register(...)
    // app.Router.Use/UseGlobal/Done(...)
    app.Handle(new(MyController))
}

type MyController struct {}

func (m *MyController) BeforeActivation(b mvc.BeforeActivation) {
    // b.Dependencies().Add/Remove
    // b.Router().Use/UseGlobal/Done // and any standard API call you already know

    // 1-> Method
    // 2-> Path
    // 3-> The controller's function name to be parsed as handler
    // 4-> Any handlers that should run before the MyCustomHandler
    b.Handle("GET", "/something/{id:long}", "MyCustomHandler", anyMiddleware...)
}

// GET: http://localhost:8080/root
func (m *MyController) Get() string { return "Hey" }

// GET: http://localhost:8080/root/something/{id:long}
func (m *MyController) MyCustomHandler(id int64) string { return "MyCustomHandler says Hey" }

Persistence data inside your Controller struct (share data between requests) by defining services to the Dependencies or have a `Singleton` controller scope.

Share the dependencies between controllers or register them on a parent MVC Application, and ability to modify dependencies per-controller on the `BeforeActivation` optional event callback inside a Controller, i.e

func(c *MyController) BeforeActivation(b mvc.BeforeActivation) { b.Dependencies().Add/Remove(...) }

Access to the `Context` as a controller's field(no manual binding is neede) i.e `Ctx iris.Context` or via a method's input argument, i.e

func(ctx iris.Context, otherArguments...)

Models inside your Controller struct (set-ed at the Method function and rendered by the View). You can return models from a controller's method or set a field in the request lifecycle and return that field to another method, in the same request lifecycle.

Flow as you used to, mvc application has its own `Router` which is a type of `iris/router.Party`, the standard iris api. `Controllers` can be registered to any `Party`, including Subdomains, the Party's begin and done handlers work as expected.

Optional `BeginRequest(ctx)` function to perform any initialization before the method execution, useful to call middlewares or when many methods use the same collection of data.

Optional `EndRequest(ctx)` function to perform any finalization after any method executed.

Session dynamic dependency via manager's `Start` to the MVC Application, i.e

mvcApp.Register(sessions.New(sessions.Config{Cookie: "iris_session_id"}).Start)

Inheritance, recursively.

Access to the dynamic path parameters via the controller's methods' input arguments, no binding is needed. When you use the Iris' default syntax to parse handlers from a controller, you need to suffix the methods with the `By` word, uppercase is a new sub path. Example:

Register one or more relative paths and able to get path parameters, i.e

If `mvc.New(app.Party("/user")).Handle(new(user.Controller))`

- `func(*Controller) Get()` - `GET:/user` , as usual.
- `func(*Controller) Post()` - `POST:/user`, as usual.
- `func(*Controller) GetLogin()` - `GET:/user/login`
- `func(*Controller) PostLogin()` - `POST:/user/login`
- `func(*Controller) GetProfileFollowers()` - `GET:/user/profile/followers`
- `func(*Controller) PostProfileFollowers()` - `POST:/user/profile/followers`
- `func(*Controller) GetBy(id int64)` - `GET:/user/{param:long}`
- `func(*Controller) PostBy(id int64)` - `POST:/user/{param:long}`

If `mvc.New(app.Party("/profile")).Handle(new(profile.Controller))`

- `func(*Controller) GetBy(username string)` - `GET:/profile/{param:string}`

If `mvc.New(app.Party("/assets")).Handle(new(file.Controller))`

- `func(*Controller) GetByWildard(path string)` - `GET:/assets/{param:path}`

If `mvc.New(app.Party("/equality")).Handle(new(profile.Equality))`

- `func(*Controller) GetBy(is bool)` - `GET:/equality/{param:boolean}`
- `func(*Controller) GetByOtherBy(is bool, otherID int64)` - `GET:/equality/{paramfirst:boolean}/other/{paramsecond:long}`

Supported types for method functions receivers: int, int64, bool and string.

Response via output arguments, optionally, i.e

func(c *ExampleController) Get() string |
(string, string) |
(string, int) |
(string, error) |
int |
(int, string) |
(any, int) |
error |
(int, error) |
(customStruct, error) |
(any, error) |
bool |
(any, bool)
customStruct |
(customStruct, int) |
(customStruct, string) |
`Result` or (`Result`, error)

Where `any` means everything, from custom structs to standard language's types-. `Result` is an interface which contains only that function: Dispatch(ctx iris.Context) and Get where HTTP Method function(Post, Put, Delete...).

Iris MVC Method Result

Iris has a very powerful and blazing fast MVC support, you can return any value of any type from a method function and it will be sent to the client as expected.

* if `string` then it's the body. * if `string` is the second output argument then it's the content type. * if `int` then it's the status code. * if `bool` is false then it throws 404 not found http error by skipping everything else. * if `error` and not nil then (any type) response will be omitted and error's text with a 400 bad request will be rendered instead. * if `(int, error)` and error is not nil then the response result will be the error's text with the status code as `int`. * if `custom struct` or `interface{}` or `slice` or `map` then it will be rendered as json, unless a `string` content type is following. * if `mvc.Result` then it executes its `Dispatch` function, so good design patters can be used to split the model's logic where needed.

Examples with good patterns to follow but not intend to be used in production of course can be found at: https://github.com/teamlint/iris/tree/master/_examples/#mvc.

Using Iris MVC for code reuse

By creating components that are independent of one another, developers are able to reuse components quickly and easily in other applications. The same (or similar) view for one application can be refactored for another application with different data because the view is simply handling how the data is being displayed to the user.

If you're new to back-end web development read about the MVC architectural pattern first, a good start is that wikipedia article: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller.

That's the basics

But you should have a basic idea of the framework by now, we just scratched the surface. If you enjoy what you just saw and want to learn more, please follow the below links:

Examples:

https://github.com/teamlint/iris/tree/master/_examples

Middleware:

https://github.com/teamlint/iris/tree/master/middleware
https://github.com/iris-contrib/middleware

Home Page:

https://iris-go.com

Book (in-progress):

https://docs.iris-go.com

Index

Constants

View Source
const (
	StatusContinue           = 100 // RFC 7231, 6.2.1
	StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
	StatusProcessing         = 102 // RFC 2518, 10.1

	StatusOK                   = 200 // RFC 7231, 6.3.1
	StatusCreated              = 201 // RFC 7231, 6.3.2
	StatusAccepted             = 202 // RFC 7231, 6.3.3
	StatusNonAuthoritativeInfo = 203 // RFC 7231, 6.3.4
	StatusNoContent            = 204 // RFC 7231, 6.3.5
	StatusResetContent         = 205 // RFC 7231, 6.3.6
	StatusPartialContent       = 206 // RFC 7233, 4.1
	StatusMultiStatus          = 207 // RFC 4918, 11.1
	StatusAlreadyReported      = 208 // RFC 5842, 7.1
	StatusIMUsed               = 226 // RFC 3229, 10.4.1

	StatusMultipleChoices  = 300 // RFC 7231, 6.4.1
	StatusMovedPermanently = 301 // RFC 7231, 6.4.2
	StatusFound            = 302 // RFC 7231, 6.4.3
	StatusSeeOther         = 303 // RFC 7231, 6.4.4
	StatusNotModified      = 304 // RFC 7232, 4.1
	StatusUseProxy         = 305 // RFC 7231, 6.4.5

	StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7
	StatusPermanentRedirect = 308 // RFC 7538, 3

	StatusBadRequest                   = 400 // RFC 7231, 6.5.1
	StatusUnauthorized                 = 401 // RFC 7235, 3.1
	StatusPaymentRequired              = 402 // RFC 7231, 6.5.2
	StatusForbidden                    = 403 // RFC 7231, 6.5.3
	StatusNotFound                     = 404 // RFC 7231, 6.5.4
	StatusMethodNotAllowed             = 405 // RFC 7231, 6.5.5
	StatusNotAcceptable                = 406 // RFC 7231, 6.5.6
	StatusProxyAuthRequired            = 407 // RFC 7235, 3.2
	StatusRequestTimeout               = 408 // RFC 7231, 6.5.7
	StatusConflict                     = 409 // RFC 7231, 6.5.8
	StatusGone                         = 410 // RFC 7231, 6.5.9
	StatusLengthRequired               = 411 // RFC 7231, 6.5.10
	StatusPreconditionFailed           = 412 // RFC 7232, 4.2
	StatusRequestEntityTooLarge        = 413 // RFC 7231, 6.5.11
	StatusRequestURITooLong            = 414 // RFC 7231, 6.5.12
	StatusUnsupportedMediaType         = 415 // RFC 7231, 6.5.13
	StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4
	StatusExpectationFailed            = 417 // RFC 7231, 6.5.14
	StatusTeapot                       = 418 // RFC 7168, 2.3.3
	StatusUnprocessableEntity          = 422 // RFC 4918, 11.2
	StatusLocked                       = 423 // RFC 4918, 11.3
	StatusFailedDependency             = 424 // RFC 4918, 11.4
	StatusUpgradeRequired              = 426 // RFC 7231, 6.5.15
	StatusPreconditionRequired         = 428 // RFC 6585, 3
	StatusTooManyRequests              = 429 // RFC 6585, 4
	StatusRequestHeaderFieldsTooLarge  = 431 // RFC 6585, 5
	StatusUnavailableForLegalReasons   = 451 // RFC 7725, 3

	StatusInternalServerError           = 500 // RFC 7231, 6.6.1
	StatusNotImplemented                = 501 // RFC 7231, 6.6.2
	StatusBadGateway                    = 502 // RFC 7231, 6.6.3
	StatusServiceUnavailable            = 503 // RFC 7231, 6.6.4
	StatusGatewayTimeout                = 504 // RFC 7231, 6.6.5
	StatusHTTPVersionNotSupported       = 505 // RFC 7231, 6.6.6
	StatusVariantAlsoNegotiates         = 506 // RFC 2295, 8.1
	StatusInsufficientStorage           = 507 // RFC 4918, 11.5
	StatusLoopDetected                  = 508 // RFC 5842, 7.2
	StatusNotExtended                   = 510 // RFC 2774, 7
	StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
)

HTTP status codes as registered with IANA. See: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Raw Copy from the net/http std package in order to recude the import path of "net/http" for the users.

Copied from `net/http` package.

View Source
const (
	MethodGet     = "GET"
	MethodPost    = "POST"
	MethodPut     = "PUT"
	MethodDelete  = "DELETE"
	MethodConnect = "CONNECT"
	MethodHead    = "HEAD"
	MethodPatch   = "PATCH"
	MethodOptions = "OPTIONS"
	MethodTrace   = "TRACE"
)

HTTP Methods copied from `net/http`.

View Source
const MethodNone = "NONE"

MethodNone is an iris-specific "virtual" method to store the "offline" routes.

View Source
const NoLayout = view.NoLayout

NoLayout to disable layout for a particular template file A shortcut for the `view#NoLayout`.

Variables

View Source
var (
	// HTML view engine.
	// Conversion for the view.HTML.
	HTML = view.HTML
	// Django view engine.
	// Conversion for the view.Django.
	Django = view.Django
	// Handlebars view engine.
	// Conversion for the view.Handlebars.
	Handlebars = view.Handlebars
	// Pug view engine.
	// Conversion for the view.Pug.
	Pug = view.Pug
	// Amber view engine.
	// Conversion for the view.Amber.
	Amber = view.Amber
)
View Source
var (
	// LimitRequestBodySize is a middleware which sets a request body size limit
	// for all next handlers in the chain.
	//
	// A shortcut for the `context#LimitRequestBodySize`.
	LimitRequestBodySize = context.LimitRequestBodySize
	// StaticEmbeddedHandler returns a Handler which can serve
	// embedded into executable files.
	//
	//
	// Examples: https://github.com/teamlint/iris/tree/master/_examples/file-server
	StaticEmbeddedHandler = router.StaticEmbeddedHandler
	// StripPrefix returns a handler that serves HTTP requests
	// by removing the given prefix from the request URL's Path
	// and invoking the handler h. StripPrefix handles a
	// request for a path that doesn't begin with prefix by
	// replying with an HTTP 404 not found error.
	//
	// Usage:
	// fileserver := Party#StaticHandler("./static_files", false, false)
	// h := iris.StripPrefix("/static", fileserver)
	// app.Get("/static/{f:path}", h)
	// app.Head("/static/{f:path}", h)
	StripPrefix = router.StripPrefix
	// Gzip is a middleware which enables writing
	// using gzip compression, if client supports.
	//
	// A shortcut for the `context#Gzip`.
	Gzip = context.Gzip
	// FromStd converts native http.Handler, http.HandlerFunc & func(w, r, next) to context.Handler.
	//
	// Supported form types:
	// 		 .FromStd(h http.Handler)
	// 		 .FromStd(func(w http.ResponseWriter, r *http.Request))
	// 		 .FromStd(func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc))
	//
	// A shortcut for the `handlerconv#FromStd`.
	FromStd = handlerconv.FromStd
	// Cache is a middleware providing server-side cache functionalities
	// to the next handlers, can be used as: `app.Get("/", iris.Cache, aboutHandler)`.
	// It should be used after Static methods.
	// See `iris#Cache304` for an alternative, faster way.
	//
	// Examples can be found at: https://github.com/teamlint/iris/tree/master/_examples/#caching
	Cache = cache.Handler
	// NoCache is a middleware which overrides the Cache-Control, Pragma and Expires headers
	// in order to disable the cache during the browser's back and forward feature.
	//
	// A good use of this middleware is on HTML routes; to refresh the page even on "back" and "forward" browser's arrow buttons.
	//
	// See `iris#StaticCache` for the opposite behavior.
	//
	// A shortcut of the `cache#NoCache`
	NoCache = cache.NoCache
	// StaticCache middleware for caching static files by sending the "Cache-Control" and "Expires" headers to the client.
	// It accepts a single input parameter, the "cacheDur", a time.Duration that it's used to calculate the expiration.
	//
	// If "cacheDur" <=0 then it returns the `NoCache` middleware instaed to disable the caching between browser's "back" and "forward" actions.
	//
	// Usage: `app.Use(iris.StaticCache(24 * time.Hour))` or `app.Use(iris.Staticcache(-1))`.
	// A middleware, which is a simple Handler can be called inside another handler as well, example:
	// cacheMiddleware := iris.StaticCache(...)
	// func(ctx iris.Context){
	//  cacheMiddleware(ctx)
	//  [...]
	// }
	//
	// A shortcut of the `cache#StaticCache`
	StaticCache = cache.StaticCache
	// Cache304 sends a `StatusNotModified` (304) whenever
	// the "If-Modified-Since" request header (time) is before the
	// time.Now() + expiresEvery (always compared to their UTC values).
	// Use this, which is a shortcut of the, `chache#Cache304` instead of the "github.com/teamlint/iris/cache" or iris.Cache
	// for better performance.
	// Clients that are compatible with the http RCF (all browsers are and tools like postman)
	// will handle the caching.
	// The only disadvantage of using that instead of server-side caching
	// is that this method will send a 304 status code instead of 200,
	// So, if you use it side by side with other micro services
	// you have to check for that status code as well for a valid response.
	//
	// Developers are free to extend this method's behavior
	// by watching system directories changes manually and use of the `ctx.WriteWithExpiration`
	// with a "modtime" based on the file modified date,
	// simillary to the `StaticWeb`(which sends status OK(200) and browser disk caching instead of 304).
	//
	// A shortcut of the `cache#Cache304`.
	Cache304 = cache.Cache304

	// CookiePath is a `CookieOption`.
	// Use it to change the cookie's Path field.
	//
	// A shortcut for the `context#CookiePath`.
	CookiePath = context.CookiePath
	// CookieCleanPath is a `CookieOption`.
	// Use it to clear the cookie's Path field, exactly the same as `CookiePath("")`.
	//
	// A shortcut for the `context#CookieCleanPath`.
	CookieCleanPath = context.CookieCleanPath
	// CookieExpires is a `CookieOption`.
	// Use it to change the cookie's Expires and MaxAge fields by passing the lifetime of the cookie.
	//
	// A shortcut for the `context#CookieExpires`.
	CookieExpires = context.CookieExpires
	// CookieHTTPOnly is a `CookieOption`.
	// Use it to set the cookie's HttpOnly field to false or true.
	// HttpOnly field defaults to true for `RemoveCookie` and `SetCookieKV`.
	//
	// A shortcut for the `context#CookieHTTPOnly`.
	CookieHTTPOnly = context.CookieHTTPOnly
	// CookieEncode is a `CookieOption`.
	// Provides encoding functionality when adding a cookie.
	// Accepts a `context#CookieEncoder` and sets the cookie's value to the encoded value.
	// Users of that is the `context#SetCookie` and `context#SetCookieKV`.
	//
	// Example: https://github.com/teamlint/iris/tree/master/_examples/cookies/securecookie
	//
	// A shortcut for the `context#CookieEncode`.
	CookieEncode = context.CookieEncode
	// CookieDecode is a `CookieOption`.
	// Provides decoding functionality when retrieving a cookie.
	// Accepts a `context#CookieDecoder` and sets the cookie's value to the decoded value before return by the `GetCookie`.
	// User of that is the `context#GetCookie`.
	//
	// Example: https://github.com/teamlint/iris/tree/master/_examples/cookies/securecookie
	//
	// A shortcut for the `context#CookieDecode`.
	CookieDecode = context.CookieDecode
)
View Source
var ErrServerClosed = http.ErrServerClosed

ErrServerClosed is returned by the Server's Serve, ServeTLS, ListenAndServe, and ListenAndServeTLS methods after a call to Shutdown or Close.

A shortcut for the `http#ErrServerClosed`.

View Source
var RegisterOnInterrupt = host.RegisterOnInterrupt

RegisterOnInterrupt registers a global function to call when CTRL+C/CMD+C pressed or a unix kill command received.

A shortcut for the `host#RegisterOnInterrupt`.

View Source
var (
	// Version is the current version number of the Iris Web Framework.
	Version = maintenance.Version
)
View Source
var WithFireMethodNotAllowed = func(app *Application) {
	app.config.FireMethodNotAllowed = true
}

WithFireMethodNotAllowed enanbles the FireMethodNotAllowed setting.

See `Configuration`.

View Source
var WithGlobalConfiguration = func(app *Application) {
	app.Configure(WithConfiguration(YAML(globalConfigurationKeyword)))
}

WithGlobalConfiguration will load the global yaml configuration file from the home directory and it will set/override the whole app's configuration to that file's contents. The global configuration file can be modified by user and be used by multiple iris instances.

This is useful when we run multiple iris servers that share the same configuration, even with custom values at its "Other" field.

Usage: `app.Configure(iris.WithGlobalConfiguration)` or `app.Run(iris.Runner, iris.WithGlobalConfiguration)`.

View Source
var WithOptimizations = func(app *Application) {
	app.config.EnableOptimizations = true
}

WithOptimizations can force the application to optimize for the best performance where is possible.

See `Configuration`.

View Source
var WithPathEscape = func(app *Application) {
	app.config.EnablePathEscape = true
}

WithPathEscape enanbles the PathEscape setting.

See `Configuration`.

View Source
var WithoutAutoFireStatusCode = func(app *Application) {
	app.config.DisableAutoFireStatusCode = true
}

WithoutAutoFireStatusCode disables the AutoFireStatusCode setting.

See `Configuration`.

View Source
var WithoutBanner = WithoutStartupLog

WithoutBanner is a conversion for the `WithoutStartupLog` option.

Turns off the information send, once, to the terminal when the main server is open.

View Source
var WithoutBodyConsumptionOnUnmarshal = func(app *Application) {
	app.config.DisableBodyConsumptionOnUnmarshal = true
}

WithoutBodyConsumptionOnUnmarshal disables BodyConsumptionOnUnmarshal setting.

See `Configuration`.

View Source
var WithoutInterruptHandler = func(app *Application) {
	app.config.DisableInterruptHandler = true
}

WithoutInterruptHandler disables the automatic graceful server shutdown when control/cmd+C pressed.

View Source
var WithoutPathCorrection = func(app *Application) {
	app.config.DisablePathCorrection = true
}

WithoutPathCorrection disables the PathCorrection setting.

See `Configuration`.

View Source
var WithoutStartupLog = func(app *Application) {
	app.config.DisableStartupLog = true
}

WithoutStartupLog turns off the information send, once, to the terminal when the main server is open.

View Source
var WithoutVersionChecker = func(app *Application) {
	app.config.DisableVersionChecker = true
}

WithoutVersionChecker will disable the version checker and updater. The Iris server will be not receive automatic updates if you pass this to the `Run` function. Use it only while you're ready for Production environment.

Functions

This section is empty.

Types

type Application

type Application struct {
	// routing embedded | exposing APIBuilder's and Router's public API.
	*router.APIBuilder
	*router.Router
	ContextPool *context.Pool

	// Hosts contains a list of all servers (Host Supervisors) that this app is running on.
	//
	// Hosts may be empty only if application ran(`app.Run`) with `iris.Raw` option runner,
	// otherwise it contains a single host (`app.Hosts[0]`).
	//
	// Additional Host Supervisors can be added to that list by calling the `app.NewHost` manually.
	//
	// Hosts field is available after `Run` or `NewHost`.
	Hosts []*host.Supervisor
	// contains filtered or unexported fields
}

Application is responsible to manage the state of the application. It contains and handles all the necessary parts to create a fast web server.

func Default

func Default() *Application

Default returns a new Application instance which, unlike `New`, recovers on panics and logs the incoming http requests.

func New

func New() *Application

New creates and returns a fresh empty iris *Application instance.

func (*Application) Build

func (app *Application) Build() error

Build sets up, once, the framework. It builds the default router with its default macros and the template functions that are very-closed to iris.

func (*Application) ConfigurationReadOnly

func (app *Application) ConfigurationReadOnly() context.ConfigurationReadOnly

ConfigurationReadOnly returns an object which doesn't allow field writing.

func (*Application) Configure

func (app *Application) Configure(configurators ...Configurator) *Application

Configure can called when modifications to the framework instance needed. It accepts the framework instance and returns an error which if it's not nil it's printed to the logger. See configuration.go for more.

Returns itself in order to be used like `app:= New().Configure(...)`

func (*Application) ConfigureHost

func (app *Application) ConfigureHost(configurators ...host.Configurator) *Application

ConfigureHost accepts one or more `host#Configuration`, these configurators functions can access the host created by `app.Run`, they're being executed when application is ready to being served to the public.

It's an alternative way to interact with a host that is automatically created by `app.Run`.

These "configurators" can work side-by-side with the `iris#Addr, iris#Server, iris#TLS, iris#AutoTLS, iris#Listener` final arguments("hostConfigs") too.

Note that these application's host "configurators" will be shared with the rest of the hosts that this app will may create (using `app.NewHost`), meaning that `app.NewHost` will execute these "configurators" everytime that is being called as well.

These "configurators" should be registered before the `app.Run` or `host.Serve/Listen` functions.

func (*Application) Logger

func (app *Application) Logger() *golog.Logger

Logger returns the golog logger instance(pointer) that is being used inside the "app".

Available levels: - "disable" - "fatal" - "error" - "warn" - "info" - "debug" Usage: app.Logger().SetLevel("error") Defaults to "info" level.

Callers can use the application's logger which is the same `golog.Default` logger, to print custom logs too. Usage: app.Logger().Error/Errorf("...") app.Logger().Warn/Warnf("...") app.Logger().Info/Infof("...") app.Logger().Debug/Debugf("...")

Setting one or more outputs: app.Logger().SetOutput(io.Writer...) Adding one or more outputs : app.Logger().AddOutput(io.Writer...)

Adding custom levels requires import of the `github.com/teamlint/golog` package:

First we create our level to a golog.Level
in order to be used in the Log functions.
var SuccessLevel golog.Level = 6
Register our level, just three fields.
golog.Levels[SuccessLevel] = &golog.LevelMetadata{
	Name:    "success",
	RawText: "[SUCC]",
	// ColorfulText (Green Color[SUCC])
	ColorfulText: "\x1b[32m[SUCC]\x1b[0m",
}

Usage: app.Logger().SetLevel("success") app.Logger().Logf(SuccessLevel, "a custom leveled log message")

func (*Application) NewHost

func (app *Application) NewHost(srv *http.Server) *host.Supervisor

NewHost accepts a standar *http.Server object, completes the necessary missing parts of that "srv" and returns a new, ready-to-use, host (supervisor).

func (*Application) RegisterView

func (app *Application) RegisterView(viewEngine view.Engine)

RegisterView should be used to register view engines mapping to a root directory and the template file(s) extension.

func (*Application) Run

func (app *Application) Run(serve Runner, withOrWithout ...Configurator) error

Run builds the framework and starts the desired `Runner` with or without configuration edits.

Run should be called only once per Application instance, it blocks like http.Server.

If more than one server needed to run on the same iris instance then create a new host and run it manually by `go NewHost(*http.Server).Serve/ListenAndServe` etc... or use an already created host: h := NewHost(*http.Server) Run(Raw(h.ListenAndServe), WithCharset("UTF-8"), WithRemoteAddrHeader("CF-Connecting-IP"))

The Application can go online with any type of server or iris's host with the help of the following runners: `Listener`, `Server`, `Addr`, `TLS`, `AutoTLS` and `Raw`.

func (*Application) SPA

func (app *Application) SPA(assetHandler context.Handler) *router.SPABuilder

SPA accepts an "assetHandler" which can be the result of an app.StaticHandler or app.StaticEmbeddedHandler. Use that when you want to navigate from /index.html to / automatically it's a helper function which just makes some checks based on the `IndexNames` and `AssetValidators` before the assetHandler call.

Example: https://github.com/teamlint/iris/tree/master/_examples/file-server/single-page-application

func (*Application) Shutdown

func (app *Application) Shutdown(ctx stdContext.Context) error

Shutdown gracefully terminates all the application's server hosts. Returns an error on the first failure, otherwise nil.

func (*Application) SubdomainRedirect

func (app *Application) SubdomainRedirect(from, to router.Party) router.Party

SubdomainRedirect registers a router wrapper which redirects(StatusMovedPermanently) a (sub)domain to another subdomain or to the root domain as fast as possible, before the router's try to execute route's handler(s).

It receives two arguments, they are the from and to/target locations, 'from' can be a wildcard subdomain as well (app.WildcardSubdomain()) 'to' is not allowed to be a wildcard for obvious reasons, 'from' can be the root domain(app) when the 'to' is not the root domain and visa-versa.

Usage: www := app.Subdomain("www") <- same as app.Party("www.") app.SubdomainRedirect(app, www) This will redirect all http(s)://mydomain.com/%anypath% to http(s)://www.mydomain.com/%anypath%.

One or more subdomain redirects can be used to the same app instance.

If you need more information about this implementation then you have to navigate through the `core/router#NewSubdomainRedirectWrapper` function instead.

Example: https://github.com/teamlint/iris/tree/master/_examples/subdomains/redirect

func (*Application) View

func (app *Application) View(writer io.Writer, filename string, layout string, bindingData interface{}) error

View executes and writes the result of a template file to the writer.

First parameter is the writer to write the parsed template. Second parameter is the relative, to templates directory, template filename, including extension. Third parameter is the layout, can be empty string. Forth parameter is the bindable data to the template, can be nil.

Use context.View to render templates to the client instead. Returns an error on failure, otherwise nil.

func (*Application) ViewResult

func (app *Application) ViewResult(filename string, layout string, bindingData interface{}) string

ViewResult executes and return the result of a template file.

func (*Application) WWW

func (app *Application) WWW() router.Party

WWW creates and returns a "www." subdomain. The difference from `app.Subdomain("www")` or `app.Party("www.")` is that the `app.WWW()` method wraps the router so all http(s)://mydomain.com will be redirect to http(s)://www.mydomain.com. Other subdomains can be registered using the app: `sub := app.Subdomain("mysubdomain")`, child subdomains can be registered using the www := app.WWW(); www.Subdomain("wwwchildSubdomain").

type Configuration

type Configuration struct {

	// IgnoreServerErrors will cause to ignore the matched "errors"
	// from the main application's `Run` function.
	// This is a slice of string, not a slice of error
	// users can register these errors using yaml or toml configuration file
	// like the rest of the configuration fields.
	//
	// See `WithoutServerError(...)` function too.
	//
	// Example: https://github.com/teamlint/iris/tree/master/_examples/http-listening/listen-addr/omit-server-errors
	//
	// Defaults to an empty slice.
	IgnoreServerErrors []string `json:"ignoreServerErrors,omitempty" yaml:"IgnoreServerErrors" toml:"IgnoreServerErrors"`

	// DisableStartupLog if setted to true then it turns off the write banner on server startup.
	//
	// Defaults to false.
	DisableStartupLog bool `json:"disableStartupLog,omitempty" yaml:"DisableStartupLog" toml:"DisableStartupLog"`
	// DisableInterruptHandler if setted to true then it disables the automatic graceful server shutdown
	// when control/cmd+C pressed.
	// Turn this to true if you're planning to handle this by your own via a custom host.Task.
	//
	// Defaults to false.
	DisableInterruptHandler bool `json:"disableInterruptHandler,omitempty" yaml:"DisableInterruptHandler" toml:"DisableInterruptHandler"`

	// DisableVersionChecker if true then process will be not be notified for any available updates.
	//
	// Defaults to false.
	DisableVersionChecker bool `json:"disableVersionChecker,omitempty" yaml:"DisableVersionChecker" toml:"DisableVersionChecker"`

	// DisablePathCorrection corrects and redirects the requested path to the registered path
	// for example, if /home/ path is requested but no handler for this Route found,
	// then the Router checks if /home handler exists, if yes,
	// (permant)redirects the client to the correct path /home
	//
	// Defaults to false.
	DisablePathCorrection bool `json:"disablePathCorrection,omitempty" yaml:"DisablePathCorrection" toml:"DisablePathCorrection"`

	// EnablePathEscape when is true then its escapes the path, the named parameters (if any).
	// Change to false it if you want something like this https://github.com/teamlint/iris/issues/135 to work
	//
	// When do you need to Disable(false) it:
	// accepts parameters with slash '/'
	// Request: http://localhost:8080/details/Project%2FDelta
	// ctx.Param("project") returns the raw named parameter: Project%2FDelta
	// which you can escape it manually with net/url:
	// projectName, _ := url.QueryUnescape(c.Param("project").
	//
	// Defaults to false.
	EnablePathEscape bool `json:"enablePathEscape,omitempty" yaml:"EnablePathEscape" toml:"EnablePathEscape"`

	// EnableOptimization when this field is true
	// then the application tries to optimize for the best performance where is possible.
	//
	// Defaults to false.
	EnableOptimizations bool `json:"enableOptimizations,omitempty" yaml:"EnableOptimizations" toml:"EnableOptimizations"`
	// FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and
	//  fires the 405 error instead of 404
	// Defaults to false.
	FireMethodNotAllowed bool `json:"fireMethodNotAllowed,omitempty" yaml:"FireMethodNotAllowed" toml:"FireMethodNotAllowed"`

	// DisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders.
	// If setted to true then it
	// disables the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`.
	//
	// By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
	// if this field setted to true then a new buffer will be created to read from and the request body.
	// The body will not be changed and existing data before the
	// context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
	DisableBodyConsumptionOnUnmarshal bool `` /* 132-byte string literal not displayed */

	// DisableAutoFireStatusCode if true then it turns off the http error status code handler automatic execution
	// from (`context.StatusCodeNotSuccessful`, defaults to < 200 || >= 400).
	// If that is false then for a direct error firing, then call the "context#FireStatusCode(statusCode)" manually.
	//
	// By-default a custom http error handler will be fired when "context.StatusCode(code)" called,
	// code should be equal with the result of the the `context.StatusCodeNotSuccessful` in order to be received as an "http error handler".
	//
	// Developer may want this option to setted as true in order to manually call the
	// error handlers when needed via "context#FireStatusCode(< 200 || >= 400)".
	// HTTP Custom error handlers are being registered via app.OnErrorCode(code, handler)".
	//
	// Defaults to false.
	DisableAutoFireStatusCode bool `json:"disableAutoFireStatusCode,omitempty" yaml:"DisableAutoFireStatusCode" toml:"DisableAutoFireStatusCode"`

	// TimeFormat time format for any kind of datetime parsing
	// Defaults to  "Mon, 02 Jan 2006 15:04:05 GMT".
	TimeFormat string `json:"timeFormat,omitempty" yaml:"TimeFormat" toml:"TimeFormat"`

	// Charset character encoding for various rendering
	// used for templates and the rest of the responses
	// Defaults to "UTF-8".
	Charset string `json:"charset,omitempty" yaml:"Charset" toml:"Charset"`

	// PostMaxMemory sets the maximum post data size
	// that a client can send to the server, this differs
	// from the overral request body size which can be modified
	// by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize`.
	//
	// Defaults to 32MB or 32 << 20 if you prefer.
	PostMaxMemory int64 `json:"postMaxMemory" yaml:"PostMaxMemory" toml:"PostMaxMemory"`

	// Context values' keys for various features.
	//
	// TranslateLanguageContextKey & TranslateFunctionContextKey are used by i18n handlers/middleware
	// currently we have only one: https://github.com/teamlint/iris/tree/master/middleware/i18n.
	//
	// Defaults to "iris.translate" and "iris.language"
	TranslateFunctionContextKey string `json:"translateFunctionContextKey,omitempty" yaml:"TranslateFunctionContextKey" toml:"TranslateFunctionContextKey"`
	// TranslateLanguageContextKey used for i18n.
	//
	// Defaults to "iris.language"
	TranslateLanguageContextKey string `json:"translateLanguageContextKey,omitempty" yaml:"TranslateLanguageContextKey" toml:"TranslateLanguageContextKey"`

	// GetViewLayoutContextKey is the key of the context's user values' key
	// which is being used to set the template
	// layout from a middleware or the main handler.
	// Overrides the parent's or the configuration's.
	//
	// Defaults to "iris.ViewLayout"
	ViewLayoutContextKey string `json:"viewLayoutContextKey,omitempty" yaml:"ViewLayoutContextKey" toml:"ViewLayoutContextKey"`
	// GetViewDataContextKey is the key of the context's user values' key
	// which is being used to set the template
	// binding data from a middleware or the main handler.
	//
	// Defaults to "iris.viewData"
	ViewDataContextKey string `json:"viewDataContextKey,omitempty" yaml:"ViewDataContextKey" toml:"ViewDataContextKey"`
	// RemoteAddrHeaders are the allowed request headers names
	// that can be valid to parse the client's IP based on.
	// By-default no "X-" header is consired safe to be used for retrieving the
	// client's IP address, because those headers can manually change by
	// the client. But sometimes are useful e.g., when behind a proxy
	// you want to enable the "X-Forwarded-For" or when cloudflare
	// you want to enable the "CF-Connecting-IP", inneed you
	// can allow the `ctx.RemoteAddr()` to use any header
	// that the client may sent.
	//
	// Defaults to an empty map but an example usage is:
	// RemoteAddrHeaders {
	//	"X-Real-Ip":             true,
	//  "X-Forwarded-For":       true,
	// 	"CF-Connecting-IP": 	 true,
	//	}
	//
	// Look `context.RemoteAddr()` for more.
	RemoteAddrHeaders map[string]bool `json:"remoteAddrHeaders,omitempty" yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"`

	// Other are the custom, dynamic options, can be empty.
	// This field used only by you to set any app's options you want.
	//
	// Defaults to a non-nil empty map.
	Other map[string]interface{} `json:"other,omitempty" yaml:"Other" toml:"Other"`
	// contains filtered or unexported fields
}

Configuration the whole configuration for an iris instance these can be passed via options also, look at the top of this file(configuration.go). Configuration is a valid OptionSetter.

func DefaultConfiguration

func DefaultConfiguration() Configuration

DefaultConfiguration returns the default configuration for an iris station, fills the main Configuration

func TOML

func TOML(filename string) Configuration

TOML reads Configuration from a toml-compatible document file. Read more about toml's implementation at: https://github.com/toml-lang/toml

Accepts the absolute path of the configuration file. An error will be shown to the user via panic with the error message. Error may occur when the file doesn't exists or is not formatted correctly.

Note: if the char '~' passed as "filename" then it tries to load and return the configuration from the $home_directory + iris.tml, see `WithGlobalConfiguration` for more information.

Usage: app.Configure(iris.WithConfiguration(iris.YAML("myconfig.tml"))) or app.Run(iris.Runner, iris.WithConfiguration(iris.YAML("myconfig.tml"))).

func YAML

func YAML(filename string) Configuration

YAML reads Configuration from a configuration.yml file.

Accepts the absolute path of the cfg.yml. An error will be shown to the user via panic with the error message. Error may occur when the cfg.yml doesn't exists or is not formatted correctly.

Note: if the char '~' passed as "filename" then it tries to load and return the configuration from the $home_directory + iris.yml, see `WithGlobalConfiguration` for more information.

Usage: app.Configure(iris.WithConfiguration(iris.YAML("myconfig.yml"))) or app.Run(iris.Runner, iris.WithConfiguration(iris.YAML("myconfig.yml"))).

func (Configuration) GetCharset

func (c Configuration) GetCharset() string

GetCharset returns the Configuration#Charset, the character encoding for various rendering used for templates and the rest of the responses.

func (Configuration) GetDisableAutoFireStatusCode

func (c Configuration) GetDisableAutoFireStatusCode() bool

GetDisableAutoFireStatusCode returns the Configuration#DisableAutoFireStatusCode. Returns true when the http error status code handler automatic execution turned off.

func (Configuration) GetDisableBodyConsumptionOnUnmarshal

func (c Configuration) GetDisableBodyConsumptionOnUnmarshal() bool

GetDisableBodyConsumptionOnUnmarshal returns the Configuration#GetDisableBodyConsumptionOnUnmarshal, manages the reading behavior of the context's body readers/binders. If returns true then the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML` is disabled.

By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`, if this field setted to true then a new buffer will be created to read from and the request body. The body will not be changed and existing data before the context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.

func (Configuration) GetDisablePathCorrection

func (c Configuration) GetDisablePathCorrection() bool

GetDisablePathCorrection returns the Configuration#DisablePathCorrection, DisablePathCorrection corrects and redirects the requested path to the registered path for example, if /home/ path is requested but no handler for this Route found, then the Router checks if /home handler exists, if yes, (permant)redirects the client to the correct path /home.

func (Configuration) GetEnableOptimizations

func (c Configuration) GetEnableOptimizations() bool

GetEnableOptimizations returns whether the application has performance optimizations enabled.

func (Configuration) GetEnablePathEscape

func (c Configuration) GetEnablePathEscape() bool

GetEnablePathEscape is the Configuration#EnablePathEscape, returns true when its escapes the path, the named parameters (if any).

func (Configuration) GetFireMethodNotAllowed

func (c Configuration) GetFireMethodNotAllowed() bool

GetFireMethodNotAllowed returns the Configuration#FireMethodNotAllowed.

func (Configuration) GetOther

func (c Configuration) GetOther() map[string]interface{}

GetOther returns the Configuration#Other map.

func (Configuration) GetPostMaxMemory

func (c Configuration) GetPostMaxMemory() int64

GetPostMaxMemory returns the maximum configured post data size that a client can send to the server, this differs from the overral request body size which can be modified by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize`.

Defaults to 32MB or 32 << 20 if you prefer.

func (Configuration) GetRemoteAddrHeaders

func (c Configuration) GetRemoteAddrHeaders() map[string]bool

GetRemoteAddrHeaders returns the allowed request headers names that can be valid to parse the client's IP based on. By-default no "X-" header is consired safe to be used for retrieving the client's IP address, because those headers can manually change by the client. But sometimes are useful e.g., when behind a proxy you want to enable the "X-Forwarded-For" or when cloudflare you want to enable the "CF-Connecting-IP", inneed you can allow the `ctx.RemoteAddr()` to use any header that the client may sent.

Defaults to an empty map but an example usage is:

RemoteAddrHeaders {
	"X-Real-Ip":             true,
 "X-Forwarded-For":       true,
	"CF-Connecting-IP": 	 true,
	}

Look `context.RemoteAddr()` for more.

func (Configuration) GetTimeFormat

func (c Configuration) GetTimeFormat() string

GetTimeFormat returns the Configuration#TimeFormat, format for any kind of datetime parsing.

func (Configuration) GetTranslateFunctionContextKey

func (c Configuration) GetTranslateFunctionContextKey() string

GetTranslateFunctionContextKey returns the configuration's TranslateFunctionContextKey value, used for i18n.

func (Configuration) GetTranslateLanguageContextKey

func (c Configuration) GetTranslateLanguageContextKey() string

GetTranslateLanguageContextKey returns the configuration's TranslateLanguageContextKey value, used for i18n.

func (Configuration) GetVHost

func (c Configuration) GetVHost() string

GetVHost returns the non-exported vhost config field.

If original addr ended with :443 or :80, it will return the host without the port. If original addr was :https or :http, it will return localhost. If original addr was 0.0.0.0, it will return localhost.

func (Configuration) GetViewDataContextKey

func (c Configuration) GetViewDataContextKey() string

GetViewDataContextKey returns the key of the context's user values' key which is being used to set the template binding data from a middleware or the main handler.

func (Configuration) GetViewLayoutContextKey

func (c Configuration) GetViewLayoutContextKey() string

GetViewLayoutContextKey returns the key of the context's user values' key which is being used to set the template layout from a middleware or the main handler. Overrides the parent's or the configuration's.

type Configurator

type Configurator func(*Application)

Configurator is just an interface which accepts the framework instance.

It can be used to register a custom configuration with `Configure` in order to modify the framework instance.

Currently Configurator is being used to describe the configuration's fields values.

func WithCharset

func WithCharset(charset string) Configurator

WithCharset sets the Charset setting.

See `Configuration`.

func WithConfiguration

func WithConfiguration(c Configuration) Configurator

WithConfiguration sets the "c" values to the framework's configurations.

Usage: app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.Configuration{/* fields here */ })) or iris.WithConfiguration(iris.YAML("./cfg/iris.yml")) or iris.WithConfiguration(iris.TOML("./cfg/iris.tml"))

func WithOtherValue

func WithOtherValue(key string, val interface{}) Configurator

WithOtherValue adds a value based on a key to the Other setting.

See `Configuration`.

func WithPostMaxMemory

func WithPostMaxMemory(limit int64) Configurator

WithPostMaxMemory sets the maximum post data size that a client can send to the server, this differs from the overral request body size which can be modified by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize`.

Defaults to 32MB or 32 << 20 if you prefer.

func WithRemoteAddrHeader

func WithRemoteAddrHeader(headerName string) Configurator

WithRemoteAddrHeader enables or adds a new or existing request header name that can be used to validate the client's real IP.

By-default no "X-" header is consired safe to be used for retrieving the client's IP address, because those headers can manually change by the client. But sometimes are useful e.g., when behind a proxy you want to enable the "X-Forwarded-For" or when cloudflare you want to enable the "CF-Connecting-IP", inneed you can allow the `ctx.RemoteAddr()` to use any header that the client may sent.

Defaults to an empty map but an example usage is: WithRemoteAddrHeader("X-Forwarded-For")

Look `context.RemoteAddr()` for more.

func WithTimeFormat

func WithTimeFormat(timeformat string) Configurator

WithTimeFormat sets the TimeFormat setting.

See `Configuration`.

func WithoutRemoteAddrHeader

func WithoutRemoteAddrHeader(headerName string) Configurator

WithoutRemoteAddrHeader disables an existing request header name that can be used to validate and parse the client's real IP.

Keep note that RemoteAddrHeaders is already defaults to an empty map so you don't have to call this Configurator if you didn't add allowed headers via configuration or via `WithRemoteAddrHeader` before.

Look `context.RemoteAddr()` for more.

func WithoutServerError

func WithoutServerError(errors ...error) Configurator

WithoutServerError will cause to ignore the matched "errors" from the main application's `Run` function.

Usage: err := app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) will return `nil` if the server's error was `http/iris#ErrServerClosed`.

See `Configuration#IgnoreServerErrors []string` too.

Example: https://github.com/teamlint/iris/tree/master/_examples/http-listening/listen-addr/omit-server-errors

type Context

type Context = context.Context

Context is the midle-man server's "object" for the clients.

A New context is being acquired from a sync.Pool on each connection. The Context is the most important thing on the iris's http flow.

Developers send responses to the client's request through a Context. Developers get request information from the client's request by a Context.

type CookieOption

type CookieOption = context.CookieOption

CookieOption is the type of function that is accepted on context's methods like `SetCookieKV`, `RemoveCookie` and `SetCookie` as their (last) variadic input argument to amend the end cookie's form.

Any custom or built'n `CookieOption` is valid, see `CookiePath`, `CookieCleanPath`, `CookieExpires` and `CookieHTTPOnly` for more.

An alias for the `context/Context#CookieOption`.

type ExecutionOptions

type ExecutionOptions = router.ExecutionOptions

ExecutionOptions is a set of default behaviors that can be changed in order to customize the execution flow of the routes' handlers with ease.

See `ExecutionRules` and `core/router/Party#SetExecutionRules` for more.

type ExecutionRules

type ExecutionRules = router.ExecutionRules

ExecutionRules gives control to the execution of the route handlers outside of the handlers themselves. Usage:

Party#SetExecutionRules(ExecutionRules {
  Done: ExecutionOptions{Force: true},
})

See `core/router/Party#SetExecutionRules` for more. Example: https://github.com/teamlint/iris/tree/master/_examples/mvc/middleware/without-ctx-next

type Handler

type Handler = context.Handler

A Handler responds to an HTTP request. It writes reply headers and data to the Context.ResponseWriter() and then return. Returning signals that the request is finished; it is not valid to use the Context after or concurrently with the completion of the Handler call.

Depending on the HTTP client software, HTTP protocol version, and any intermediaries between the client and the iris server, it may not be possible to read from the Context.Request().Body after writing to the context.ResponseWriter(). Cautious handlers should read the Context.Request().Body first, and then reply.

Except for reading the body, handlers should not modify the provided Context.

If Handler panics, the server (the caller of Handler) assumes that the effect of the panic was isolated to the active request. It recovers the panic, logs a stack trace to the server error log, and hangs up the connection.

type Map

type Map = context.Map

A Map is a shortcut of the map[string]interface{}.

type Party

type Party = router.Party

Party is just a group joiner of routes which have the same prefix and share same middleware(s) also. Party could also be named as 'Join' or 'Node' or 'Group' , Party chosen because it is fun.

Look the `core/router#APIBuilder` for its implementation.

A shortcut for the `core/router#Party`, useful when `PartyFunc` is being used.

type Runner

type Runner func(*Application) error

Runner is just an interface which accepts the framework instance and returns an error.

It can be used to register a custom runner with `Run` in order to set the framework's server listen action.

Currently Runner is being used to declare the built'n server listeners.

See `Run` for more.

func Addr

func Addr(addr string, hostConfigs ...host.Configurator) Runner

Addr can be used as an argument for the `Run` method. It accepts a host address which is used to build a server and a listener which listens on that host and port.

Addr should have the form of host:port, i.e localhost:8080 or :8080.

Second argument is optional, it accepts one or more `func(*host.Configurator)` that are being executed on that specific host that this function will create to start the server. Via host configurators you can configure the back-end host supervisor, i.e to add events for shutdown, serve or error. An example of this use case can be found at: https://github.com/teamlint/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go Look at the `ConfigureHost` too.

See `Run` for more.

func AutoTLS

func AutoTLS(
	addr string,
	domain string, email string,
	hostConfigs ...host.Configurator) Runner

AutoTLS can be used as an argument for the `Run` method. It will start the Application's secure server using certifications created on the fly by the "autocert" golang/x package, so localhost may not be working, use it at "production" machine.

Addr should have the form of host:port, i.e mydomain.com:443.

The whitelisted domains are separated by whitespace in "domain" argument, i.e "iris-go.com", can be different than "addr". If empty, all hosts are currently allowed. This is not recommended, as it opens a potential attack where clients connect to a server by IP address and pretend to be asking for an incorrect host name. Manager will attempt to obtain a certificate for that host, incorrectly, eventually reaching the CA's rate limit for certificate requests and making it impossible to obtain actual certificates.

For an "e-mail" use a non-public one, letsencrypt needs that for your own security.

Note: `AutoTLS` will start a new server for you which will redirect all http versions to their https, including subdomains as well.

Last argument is optional, it accepts one or more `func(*host.Configurator)` that are being executed on that specific host that this function will create to start the server. Via host configurators you can configure the back-end host supervisor, i.e to add events for shutdown, serve or error. An example of this use case can be found at: https://github.com/teamlint/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go Look at the `ConfigureHost` too.

Usage: app.Run(iris.AutoTLS("iris-go.com:443", "iris-go.com www.iris-go.com", "mail@example.com"))

See `Run` and `core/host/Supervisor#ListenAndServeAutoTLS` for more.

func Listener

func Listener(l net.Listener, hostConfigs ...host.Configurator) Runner

Listener can be used as an argument for the `Run` method. It can start a server with a custom net.Listener via server's `Serve`.

Second argument is optional, it accepts one or more `func(*host.Configurator)` that are being executed on that specific host that this function will create to start the server. Via host configurators you can configure the back-end host supervisor, i.e to add events for shutdown, serve or error. An example of this use case can be found at: https://github.com/teamlint/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go Look at the `ConfigureHost` too.

See `Run` for more.

func Raw

func Raw(f func() error) Runner

Raw can be used as an argument for the `Run` method. It accepts any (listen) function that returns an error, this function should be block and return an error only when the server exited or a fatal error caused.

With this option you're not limited to the servers that iris can run by-default.

See `Run` for more.

func Server

func Server(srv *http.Server, hostConfigs ...host.Configurator) Runner

Server can be used as an argument for the `Run` method. It can start a server with a *http.Server.

Second argument is optional, it accepts one or more `func(*host.Configurator)` that are being executed on that specific host that this function will create to start the server. Via host configurators you can configure the back-end host supervisor, i.e to add events for shutdown, serve or error. An example of this use case can be found at: https://github.com/teamlint/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go Look at the `ConfigureHost` too.

See `Run` for more.

func TLS

func TLS(addr string, certFile, keyFile string, hostConfigs ...host.Configurator) Runner

TLS can be used as an argument for the `Run` method. It will start the Application's secure server.

Use it like you used to use the http.ListenAndServeTLS function.

Addr should have the form of host:port, i.e localhost:443 or :443. CertFile & KeyFile should be filenames with their extensions.

Second argument is optional, it accepts one or more `func(*host.Configurator)` that are being executed on that specific host that this function will create to start the server. Via host configurators you can configure the back-end host supervisor, i.e to add events for shutdown, serve or error. An example of this use case can be found at: https://github.com/teamlint/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go Look at the `ConfigureHost` too.

See `Run` for more.

type Supervisor

type Supervisor = host.Supervisor

Supervisor is a shortcut of the `host#Supervisor`. Used to add supervisor configurators on common Runners without the need of importing the `core/host` package.

type UnmarshalerFunc

type UnmarshalerFunc = context.UnmarshalerFunc

UnmarshalerFunc a shortcut, an alias for the `context#UnmarshalerFunc` type which implements the `context#Unmarshaler` interface for reading request's body via custom decoders, most of them already implement the `context#UnmarshalerFunc` like the json.Unmarshal, xml.Unmarshal, yaml.Unmarshal and every library which follows the best practises and is aligned with the Go standards.

See 'context#UnmarshalBody` for more.

Example: https://github.com/teamlint/iris/blob/master/_examples/http_request/read-custom-via-unmarshaler/main.go

Directories

Path Synopsis
_benchmarks
_examples
cache/client-side
Package main shows how you can use the `WriteWithExpiration` based on the "modtime", if it's newer than the request header then it will refresh the contents, otherwise will let the client (99.9% the browser) to handle the cache mechanism, it's faster than iris.Cache because server-side has nothing to do and no need to store the responses in the memory.
Package main shows how you can use the `WriteWithExpiration` based on the "modtime", if it's newer than the request header then it will refresh the contents, otherwise will let the client (99.9% the browser) to handle the cache mechanism, it's faster than iris.Cache because server-side has nothing to do and no need to store the responses in the memory.
experimental-handlers/csrf
This middleware provides Cross-Site Request Forgery protection.
This middleware provides Cross-Site Request Forgery protection.
experimental-handlers/jwt
iris provides some basic middleware, most for your learning curve.
iris provides some basic middleware, most for your learning curve.
http-listening/listen-letsencrypt
Package main provide one-line integration with letsencrypt.org
Package main provide one-line integration with letsencrypt.org
http_request/read-form
package main contains an example on how to use the ReadForm, but with the same way you can do the ReadJSON & ReadJSON
package main contains an example on how to use the ReadForm, but with the same way you can do the ReadJSON & ReadJSON
http_request/read-json-struct-validation
Package main shows the validator(latest, version 9) integration with Iris.
Package main shows the validator(latest, version 9) integration with Iris.
Code generated by hero.
http_responsewriter/sse
Package main shows how to send continuous event messages to the clients through SSE via a broker.
Package main shows how to send continuous event messages to the clients through SSE via a broker.
mvc/middleware
Package main shows how you can add middleware to an mvc Application, simply by using its `Router` which is a sub router(an iris.Party) of the main iris app.
Package main shows how you can add middleware to an mvc Application, simply by using its `Router` which is a sub router(an iris.Party) of the main iris app.
mvc/middleware/per-method
If you want to use it as middleware for the entire controller you can use its router which is just a sub router to add it as you normally do with standard API: I'll show you 4 different methods for adding a middleware into an mvc application, all of those 4 do exactly the same thing, select what you prefer, I prefer the last code-snippet when I need the middleware to be registered somewhere else as well, otherwise I am going with the first one: “`go // 1 mvc.Configure(app.Party("/user"), func(m *mvc.Application) { m.Router.Use(cache.Handler(10*time.Second)) }) “` “`go // 2 // same: userRouter := app.Party("/user") userRouter.Use(cache.Handler(10*time.Second)) mvc.Configure(userRouter, ...) “` “`go // 3 // same: userRouter := app.Party("/user", cache.Handler(10*time.Second)) mvc.Configure(userRouter, ...) “` “`go // 4 // same: app.PartyFunc("/user", func(r iris.Party){ r.Use(cache.Handler(10*time.Second)) mvc.Configure(r, ...) }) “` If you want to use a middleware for a single route, for a single controller's method that is already registered by the engine and not by custom `Handle` (which you can add the middleware there on the last parameter) and it's not depend on the `Next Handler` to do its job then you just call it on the method: “`go var myMiddleware := myMiddleware.New(...) // this should return an iris/context.Handler type UserController struct{} func (c *UserController) GetSomething(ctx iris.Context) { // ctx.Proceed checks if myMiddleware called `ctx.Next()` // inside it and returns true if so, otherwise false.
If you want to use it as middleware for the entire controller you can use its router which is just a sub router to add it as you normally do with standard API: I'll show you 4 different methods for adding a middleware into an mvc application, all of those 4 do exactly the same thing, select what you prefer, I prefer the last code-snippet when I need the middleware to be registered somewhere else as well, otherwise I am going with the first one: “`go // 1 mvc.Configure(app.Party("/user"), func(m *mvc.Application) { m.Router.Use(cache.Handler(10*time.Second)) }) “` “`go // 2 // same: userRouter := app.Party("/user") userRouter.Use(cache.Handler(10*time.Second)) mvc.Configure(userRouter, ...) “` “`go // 3 // same: userRouter := app.Party("/user", cache.Handler(10*time.Second)) mvc.Configure(userRouter, ...) “` “`go // 4 // same: app.PartyFunc("/user", func(r iris.Party){ r.Use(cache.Handler(10*time.Second)) mvc.Configure(r, ...) }) “` If you want to use a middleware for a single route, for a single controller's method that is already registered by the engine and not by custom `Handle` (which you can add the middleware there on the last parameter) and it's not depend on the `Next Handler` to do its job then you just call it on the method: “`go var myMiddleware := myMiddleware.New(...) // this should return an iris/context.Handler type UserController struct{} func (c *UserController) GetSomething(ctx iris.Context) { // ctx.Proceed checks if myMiddleware called `ctx.Next()` // inside it and returns true if so, otherwise false.
mvc/middleware/without-ctx-next
Package main is a simple example of the behavior change of the execution flow of the handlers, normally we need the `ctx.Next()` to call the next handler in a route's handler chain, but with the new `ExecutionRules` we can change this default behavior.
Package main is a simple example of the behavior change of the execution flow of the handlers, normally we need the `ctx.Next()` to call the next handler in a route's handler chain, but with the new `ExecutionRules` we can change this default behavior.
orm/xorm
Package main shows how an orm can be used within your web app it just inserts a column and select the first.
Package main shows how an orm can be used within your web app it just inserts a column and select the first.
subdomains/redirect
Package main shows how to register a simple 'www' subdomain, using the `app.WWW` method, which will register a router wrapper which will redirect all 'mydomain.com' requests to 'www.mydomain.com'.
Package main shows how to register a simple 'www' subdomain, using the `app.WWW` method, which will register a router wrapper which will redirect all 'mydomain.com' requests to 'www.mydomain.com'.
subdomains/single
Package main register static subdomains, simple as parties, check ./hosts if you use windows
Package main register static subdomains, simple as parties, check ./hosts if you use windows
subdomains/wildcard
Package main an example on how to catch dynamic subdomains - wildcard.
Package main an example on how to catch dynamic subdomains - wildcard.
tutorial/url-shortener
Package main shows how you can create a simple URL Shortener.
Package main shows how you can create a simple URL Shortener.
view/template_html_3
Package main an example on how to naming your routes & use the custom 'url path' HTML Template Engine, same for other template engines.
Package main an example on how to naming your routes & use the custom 'url path' HTML Template Engine, same for other template engines.
view/template_html_4
Package main an example on how to naming your routes & use the custom 'url' HTML Template Engine, same for other template engines.
Package main an example on how to naming your routes & use the custom 'url' HTML Template Engine, same for other template engines.
view/template_pug_1
Package main shows an example of pug actions based on https://github.com/Joker/jade/tree/master/example/actions
Package main shows an example of pug actions based on https://github.com/Joker/jade/tree/master/example/actions
cfg
ruleset
Package ruleset provides the basics rules which are being extended by rules.
Package ruleset provides the basics rules which are being extended by rules.
uri
contrib
core
memstore
Package memstore contains a store which is just a collection of key-value entries with immutability capabilities.
Package memstore contains a store which is just a collection of key-value entries with immutability capabilities.
di
Package di provides dependency injection for the Iris Hero and Iris MVC new features.
Package di provides dependency injection for the Iris Hero and Iris MVC new features.
middleware
basicauth
Package basicauth provides http basic authentication via middleware.
Package basicauth provides http basic authentication via middleware.
i18n
Package i18n provides internalization and localization via middleware.
Package i18n provides internalization and localization via middleware.
logger
Package logger provides request logging via middleware.
Package logger provides request logging via middleware.
pprof
Package pprof provides native pprof support via middleware.
Package pprof provides native pprof support via middleware.
recover
Package recover provides recovery for specific routes or for the whole app via middleware.
Package recover provides recovery for specific routes or for the whole app via middleware.
Package typescript provides a typescript compiler with hot-reloader and optionally a cloud-based editor, called 'alm-tools'.
Package typescript provides a typescript compiler with hot-reloader and optionally a cloud-based editor, called 'alm-tools'.
npm
Package websocket provides rich websocket support for the iris web framework.
Package websocket provides rich websocket support for the iris web framework.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL