10 Routing middleware
Gerasimos (Makis) Maropoulos edited this page 2020-06-18 09:47:07 +03:00

Middleware

When we talk about Middleware in Iris we're talking about running code before and/or after our main handler code in a HTTP request lifecycle. For example, logging middleware might write the incoming request details to a log, then call the handler code, before writing details about the response to the log. One of the cool things about middleware is that these units are extremely flexible and reusable.

A middleware is just a Handler form of func(ctx iris.Context), the middleware is being executed when the previous middleware calls the ctx.Next(), this can be used for authentication, i.e: if request authenticated then call ctx.Next() to process with the rest of the chain of handlers in the request otherwise fire an error response.

Writing a middleware

package main

import "github.com/kataras/iris/v12"

func main() {
    app := iris.New()
    // or app.Use(before) and app.Done(after).
    app.Get("/", before, mainHandler, after)
    app.Listen(":8080")
}

func before(ctx iris.Context) {
    shareInformation := "this is a sharable information between handlers"

    requestPath := ctx.Path()
    println("Before the mainHandler: " + requestPath)

    ctx.Values().Set("info", shareInformation)
    ctx.Next() // execute the next handler, in this case the main one.
}

func after(ctx iris.Context) {
    println("After the mainHandler")
}

func mainHandler(ctx iris.Context) {
    println("Inside mainHandler")

    // take the info from the "before" handler.
    info := ctx.Values().GetString("info")

    // write something to the client as a response.
    ctx.HTML("<h1>Response</h1>")
    ctx.HTML("<br/> Info: " + info)

    ctx.Next() // execute the "after".
}
$ go run main.go # and navigate to the http://localhost:8080
Now listening on: http://localhost:8080
Application started. Press CTRL+C to shut down.
Before the mainHandler: /
Inside mainHandler
After the mainHandler

Globally

package main

import "github.com/kataras/iris/v12"

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

    // register our routes.
    app.Get("/", indexHandler)
    app.Get("/contact", contactHandler)

    // Order of those calls does not matter,
    // `UseGlobal` and `DoneGlobal` are applied to existing routes
    // and future routes also.
    //
    // Remember: the `Use` and `Done` are applied to the current party's and its children,
    // so if we used the `app.Use/Done before the routes registration
    // it would work like UseGlobal/DoneGlobal in this case,
    // because the `app` is the root "Party".
    app.UseGlobal(before)
    app.DoneGlobal(after)

    app.Listen(":8080")
}

func before(ctx iris.Context) {
     // [...]
}

func after(ctx iris.Context) {
    // [...]
}

func indexHandler(ctx iris.Context) {
    // write something to the client as a response.
    ctx.HTML("<h1>Index</h1>")

    ctx.Next() // execute the "after" handler registered via `Done`.
}

func contactHandler(ctx iris.Context) {
    // write something to the client as a response.
    ctx.HTML("<h1>Contact</h1>")

    ctx.Next() // execute the "after" handler registered via `Done`.
}

You could also use the ExecutionRules to force Done handlers to be executed without the need of ctx.Next() in your route handlers, do it like this:

app.SetExecutionRules(iris.ExecutionRules{
    // Begin: ...
    // Main:  ...
    Done: iris.ExecutionOptions{Force: true},
})

Convert http.Handler/HandlerFunc

However you are not limited to them - you are free to use any third-party middleware that is compatible with the net/http package.

Iris, unlike others, is 100% compatible with the standards and that's why the majority of 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.

Any third-party middleware that written for net/http is compatible with Iris using the iris.FromStd(aThirdPartyMiddleware). Remember, ctx.ResponseWriter() and ctx.Request() returns the same net/http input arguments of an http.Handler.


Here is a list of some handlers made specifically for Iris:

Built-in

Middleware Example
basic authentication iris/_examples/auth/basicauth
request logger iris/_examples/logging/request-logger
HTTP method override iris/middleware/methodoverride/methodoverride_test.go
profiling (pprof) iris/_examples/pprof
Google reCAPTCHA iris/_examples/auth/recaptcha
hCaptcha iris/_examples/auth/recaptcha
recovery iris/_examples/recover
rate iris/_examples/request-ratelimit
jwt iris/_examples/auth/jwt
requestid iris/middleware/requestid/requestid_test.go

Community

Middleware Description Example
jwt Middleware checks for a JWT on the Authorization header on incoming requests and decodes it iris-contrib/middleware/jwt/_example
cors HTTP Access Control iris-contrib/middleware/cors/_example
secure Middleware that implements a few quick security wins iris-contrib/middleware/secure/_example
tollbooth Generic middleware to rate-limit HTTP requests iris-contrib/middleware/tollboothic/_examples/limit-handler
cloudwatch AWS cloudwatch metrics middleware iris-contrib/middleware/cloudwatch/_example
new relic Official New Relic Go Agent iris-contrib/middleware/newrelic/_example
prometheus Easily create metrics endpoint for the prometheus instrumentation tool iris-contrib/middleware/prometheus/_example
casbin An authorization library that supports access control models like ACL, RBAC, ABAC iris-contrib/middleware/casbin/_examples
raven Sentry client in Go iris-contrib/middleware/raven/_example
csrf Cross-Site Request Forgery Protection iris-contrib/middleware/csrf/_example
go-i18n i18n Iris Loader for nicksnyder/go-i18n iris-contrib/middleware/go-i18n/_example
throttler Rate limiting access to HTTP endpoints iris-contrib/middleware/throttler/_example

Third-Party

Iris has its own middleware form of func(ctx iris.Context) but it's also compatible with all net/http middleware forms. See here.