The fastest go web framework which provides robust set of features for building modern & shiny web applications.
- Context: Iris uses Context for storing route params, sharing variables between middlewares and render rich content to the client.
- Plugins: You can build your own plugins to inject the Iris framework*.
- Full API: All http methods are supported, you can group routes and sharing resources together*.
- Zero allocations: Iris generates zero garbage*.
- Multi server instances: Besides the fact that Iris has a default main server. You can declare as many as you need*.
- Compatible: Iris is compatible with the native net/http package.
Q: What makes iris significantly faster?
-
Iris uses the same algorithm as the BSD's kernel does for routing (call it Trie)
-
Iris has 5 different types of Routers, which are optimized and auto-selected before the server listen
-
The more you use it, more faster it becomes. Because Iris (can) use cache for routing, it's optional. If you disable it it stills the fastest but only with a small difference from other routers/frameworks
-
Iris can detect how much cores the machine using at runtime and optimize itself
-
Middlewares and Plugins are 'light' and that is, a principle.
- Install
- Introduction
- TLS
- Handlers
- Using Handlers
- Using HandlerFuncs
- Using Annotated
- Using native http.Handler - Using native http.Handler via iris.ToHandlerFunc()
- Middlewares
- API
- Declaration & Options
- Party
- Named Parameters
- Catch all and Static serving
- Custom HTTP Errors
- Context
- Plugins
- Internationalization and Localization
- Examples
- Benchmarks
- Third Party Middlewares
- Contributors
- Community
- Todo
- External source articles
- License
Iris is still in development status, in order to have the latest version update the package one per week
$ go get -u github.com/kataras/iris
The name of this framework came from Greek mythology, Iris was the name of the Greek goddess of the rainbow. Iris is a very minimal but flexible golang http middleware & standalone web application framework, providing a robust set of features for building single & multi-page, web applications.
package main
import "github.com/kataras/iris"
func main() {
iris.Get("/hello", func(c *iris.Context) {
c.HTML("<b> Hello </b>")
})
iris
F438
.Listen(":8080")
}
Note: for macOS, If you are having problems on .Listen then pass only the port "8080" without ':'
//1 defaults to tcp 8080
iris.Listen()
//2
log.Fatal(iris.Listen(":8080"))
//3
http.ListenAndServe(":8080",iris.Serve())
//4
log.Fatal(http.ListenAndServe(":8080",iris.Serve()))
TLS for https:// and http2:
ListenTLS(fulladdr string, certFile, keyFile string) error
//1
iris.ListenTLS(":8080", "myCERTfile.cert", "myKEYfile.key")
//2
log.Fatal(iris.ListenTLS(":8080", "myCERTfile.cert", "myKEYfile.key"))
Handlers should implement the Handler interface:
type Handler interface {
Serve(*Context)
}
type myHandlerGet struct {
}
func (m myHandlerGet) Serve(c *iris.Context) {
c.Write("From %s",c.Request.URL.Path)
}
//and so on
iris.Handle("GET", "/get", myHandlerGet)
iris.Handle("POST", "/post", post)
iris.Handle("PUT", "/put", put)
iris.Handle("DELETE", "/delete", del)
HandlerFuncs should implement the Serve(*Context) func. HandlerFunc is most simple method to register a route or a middleware, but under the hoods it's acts like a Handler. It's implements the Handler interface as well:
type HandlerFunc func(*Context)
func (h HandlerFunc) Serve(c *Context) {
h(c)
}
HandlerFuncs shoud have this function signature:
func handlerFunc(c *iris.Context) {
c.Write("Hello")
}
iris.HandleFunc("GET","/letsgetit",handlerFunc)
//OR
iris.Get("/get", handlerFunc)
iris.Post("/post", handlerFunc)
iris.Put("/put", handlerFunc)
iris.Delete("/delete", handlerFunc)
Implements the Handler interface
///file: userhandler.go
import "github.com/kataras/iris"
type UserHandler struct {
iris.Handler `get:"/profile/user/:userId"`
}
func (u *UserHandler) Serve(c *iris.Context) {
defer c.Close()
userId := c.Param("userId")
c.RenderFile("user.html", struct{ Message string }{Message: "Hello User with ID: " + userId})
}
///file: main.go
//...cache the html files
iris.Templates("src/iristests/templates/**/*.html")
//...register the handler
iris.HandleAnnotated(&UserHandler{})
//...continue writing your wonderful API
Note that using native http handler you cannot access url params.
type nativehandler struct {}
func (_ nativehandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
}
func main() {
iris.Handle("", "/path", iris.ToHandler(nativehandler{}))
//"" means ANY(GET,POST,PUT,DELETE and so on)
}
iris.Get("/letsget", iris.ToHandlerFunc(nativehandler{}))
iris.Post("/letspost", iris.ToHandlerFunc(nativehandler{}))
iris.Put("/letsput", iris.ToHandlerFunc(nativehandler{}))
iris.Delete("/letsdelete", iris.ToHandlerFunc(nativehandler{}))
Middlewares in Iris are not complicated, imagine them as simple Handlers. They should implement the Handler interface as well:
type Handler interface {
Serve(*Context)
}
type Middleware []Handler
Handler middleware example:
type myMiddleware struct {}
func (m *myMiddleware) Serve(c *iris.Context){
shouldContinueToTheNextHandler := true
if shouldContinueToTheNextHandler {
c.Next()
}else{
c.SendStatus(403,"Forbidden !!")
}
}
iris.Use(&myMiddleware{})
iris.Get("/home", func (c *iris.Context){
c.HTML("<h1>Hello from /home </h1>")
})
iris.Listen()
HandlerFunc middleware example:
func myMiddleware(c *iris.Context){
c.Next()
}
iris.UseFunc(myMiddleware)
HandlerFunc middleware for a specific route:
func mySecondMiddleware(c *iris.Context){
c.Next()
}
iris.Get("/dashboard", func(c *iris.Context) {
loggedIn := true
if loggedIn {
c.Next()
}
}, mySecondMiddleware, func (c *iris.Context){
c.Write("The last HandlerFunc is the main handler, all before that are the middlewares for this route /dashboard")
})
iris.Listen(":8080")
Uses one of build'n Iris middlewares, view practical examples here
package main
import (
"github.com/kataras/iris"
"github.com/kataras/iris/middleware/gzip"
)
type Page struct {
Title string
}
iris.Templates("./yourpath/templates/*")
iris.Use(gzip.Gzip(gzip.DefaultCompression))
iris.Get("/", func(c *iris.Context) {
c.RenderFile("index.html", Page{"My Index Title"})
})
iris.Listen(":8080") // .Listen() listens to TCP port 8080 by default
Use of GET, POST, PUT, DELETE, HEAD, PATCH & OPTIONS
package main
import "github.com/kataras/iris"
func main() {
iris.Get("/home", testGet)
iris.Post("/login",testPost)
iris.Put("/add",testPut)
iris.Delete("/remove",testDelete)
iris.Head("/testHead",testHead)
iris.Patch("/testPatch",testPatch)
iris.Options("/testOptions",testOptions)
iris.Listen(":8080")
}
func testGet(c *iris.Context) {
//...
}
func testPost(c *iris.Context) {
//...
}
//and so on....
Let's make a pause,
- Q: Other frameworks needs more lines to start a server, why Iris is different?
- A: Iris gives you the freedom to choose between three methods/ways to use Iris
- global iris.
- set a new iris with variable = iris**.New()**
- set a new iris with custom options with variable = iris**.Custom(options)**
import "github.com/kataras/iris"
// 1.
func methodFirst() {
iris.Get("/home",func(c *iris.Context){})
iris.Listen(":8080")
//iris.ListenTLS(":8080","yourcertfile.cert","yourkeyfile.key"
}
// 2.
func methodSecond() {
api := iris.New()
api.Get("/home",func(c *iris.Context){})
api.Listen(":8080")
}
// 3.
func methodThree() {
//these are the default options' values
options := iris.StationOptions{
Profile: false,
ProfilePath: iris.DefaultProfilePath,
Cache: true,
CacheMaxItems: 0,
CacheResetDuration: 5 * time.Minute,
PathCorrection: true, //explanation at the end of this chapter
}//these are the default values that you can change
//DefaultProfilePath = "/debug/pprof"
api := iris.Custom(options)
api.Get("/home",func(c *iris.Context){})
api.Listen(":8080")
}
Note that with 2. & 3. you can define and use more than one Iris container in the same app, when it's necessary.
As you can see there are some options that you can chage at your iris declaration, you cannot change them after. If an option value not passed then it considers to be false if bool or the default if string.
For example if we do that...
import "github.com/kataras/iris"
func main() {
options := iris.StationOptions{
Cache: true,
Profile: true,
ProfilePath: "/mypath/debug",
}
api := iris.Custom(options)
api.Listen(":8080")
}
run it, then you can open your browser, type 'localhost:8080/mypath/debug/profile' at the location input field and you should see a webpage shows you informations about CPU.
For profiling & debug there are seven (7) generated pages ('/debug/pprof/' is the default profile path, which on previous example we changed it to '/mypath/debug'):
- /debug/pprof/cmdline
- /debug/pprof/profile
- /debug/pprof/symbol
- /debug/pprof/goroutine
- /debug/pprof/heap
- /debug/pprof/threadcreate
- /debug/pprof/pprof/block
PathCorrection corrects and redirects the requested path to the registed 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, redirects the client to the correct path /home and VICE - VERSA if /home/ is registed but /home is requested then it redirects to /home/ (Default is true)
Let's party with Iris web framework!
func main() {
//log everything middleware
iris.UseFunc(func(c *iris.Context) {
println("[Global log] the requested url path is: ", c.Request.URL.Path)
c.Next()
})
// manage all /users
users := iris.Party("/users")
{
// provide a middleware
users.UseFunc(func(c *iris.Context) {
println("LOG [/users...] This is the middleware for: ", c.Request.URL.Path)
c.Next()
})
users.Post("/login", loginHandler)
users.Get("/:userId", singleUserHandler)
users.Delete("/:userId", userAccountRemoveUserHandler)
}
// Party inside an existing Party example:
beta:= iris.Party("/beta")
admin := beta.Party("/admin")
{
/// GET: /beta/admin/
admin.Get("/", func(c *iris.Context){})
/// POST: /beta/admin/signin
admin.Post("/signin", func(c *iris.Context){})
/// GET: /beta/admin/dashboard
admin.Get("/dashboard", func(c *iris.Context){})
/// PUT: /beta/admin/users/add
admin.Put("/users/add", func(c *iris.Context){})
}
iris.Listen(":8080")
}
Named parameters are just custom paths to your routes, you can access them for each request using context's c.Param("nameoftheparameter"). Get all, as array ({Key,Value}) using c.Params property.
No limit on how long a path can be.
Usage:
package main
import "github.com/kataras/iris"
func main() {
// MATCH to /hello/anywordhere (if PathCorrection:true match also /hello/anywordhere/)
// NOT match to /hello or /hello/ or /hello/anywordhere/something
iris.Get("/hello/:name", func(c *iris.Context) {
name := c.Param("name")
c.Write("Hello %s", name)
})
// MATCH to /profile/iris/friends/42 (if PathCorrection:true matches also /profile/iris/friends/42/ ,otherwise not match)
// NOT match to /profile/ , /profile/something ,
// NOT match to /profile/something/friends, /profile/something/friends ,
// NOT match to /profile/anything/friends/42/something
iris.Get("/profile/:fullname/friends/:friendId",
func(c *iris.Context){
name:= c.Param("fullname")
//friendId := c.ParamInt("friendId")
c.HTML("<b> Hello </b>"+name)
})
iris.Listen(":8080")
//or
//log.Fatal(http.ListenAndServe(":8080", iris.Serve()))
}
####Catch all
// Will match any request which url's preffix is "/anything/" and has content after that
iris.Get("/anything/*randomName", func(c *iris.Context) { } )
// Match: /anything/whateverhere/whateveragain , /anything/blablabla
// c.Params("randomName") will be /whateverhere/whateveragain, blablabla
// Not Match: /anything , /anything/ , /something
iris.Get("/public/*assets", iris.Static("./static/resources/","/public/"))
// Visible URL-> /public/assets/favicon.ico
You can define your own handlers for http errors, which can render an html file for example. e.g for for 404 not found:
package main
import "github.com/kataras/iris"
func main() {
iris.OnError(404,func (c *iris.Context){
c.HTML("<h1> The page you looking doesn't exists </h1>")
c.Status(404)
})
//or OnNotFound(func (c *iris.Context){})... for 404 only.
//or OnPanic(func (c *iris.Context){})... for 500 only.
//...
}
We saw how to declare a custom error for a http status code, now let's look for how to send/emit an error to the client manually , for example let's emit the 404 we defined before, simple:
iris.Get("/thenotfound",func (c *iris.Context) {
c.EmitError(404)
//or c.NotFound() for 404 only.
//and c.Panic() for 500 only.
})
Variables
- ResponseWriter
- The ResponseWriter is the exactly the same as you used to use with the standar http library.
- Request
- The Request is the pointer of the *Request, is the exactly the same as you used to use with the standar http library.
- Params
- Contains the Named path Parameters, imagine it as a map[string]string which contains all parameters of a request.
Functions
-
Clone()
- Returns a clone of the Context, useful when you want to use the context outscoped for example in goroutines.
-
Write(contents string)
- Writes a pure string to the ResponseWriter and sends to the client.
-
Param(key string) returns string
- Returns the string representation of the key's named parameter's value. Registed path= /profile/:name) Requested url is /profile/something where the key argument is the named parameter's key, returns the value which is 'something' here.
-
ParamInt(key string) returns integer, error
- Returns the int representation of the key's named parameter's value, if something goes wrong the second return value, the error is not nil.
-
URLParam(key string) returns string
- Returns the string representation of a requested url parameter (?key=something) where the key argument is the name of, something is the returned value.
-
URLParamInt(key string) returns integer, error
- Returns the int representation of a requested url parameter
-
SetCookie(name string, value string)
- Adds a cookie to the request.
-
GetCookie(name string) returns string
- Get the cookie value, as string, of a cookie.
-
ServeFile(path string)
- This just calls the http.ServeFile, which serves a file given by the path argument to the client.
-
NotFound()
- Sends a http.StatusNotFound with a custom template you defined (if any otherwise the default template is there) to the client. --- Note: We will learn all about Custom Error Handlers later.
-
Close()
- Calls the Request.Body.Close().
-
WriteHTML(status int, contents string) & HTML(contents string)
- WriteHTML: Writes html string with a given http status to the client, it sets the Header with the correct content-type.
- HTML: Same as WriteHTML but you don't have to pass a status, it's defaulted to http.StatusOK (200).
-
WriteData(status int, binaryData []byte) & Data(binaryData []byte)
- WriteData: Writes binary data with a given http status to the client, it sets the Header with the correct content-type.
- Data : Same as WriteData but you don't have to pass a status, it's defaulted to http.StatusOK (200).
-
WriteText(status int, contents string) & Text(contents string)
- WriteText: Writes plain text with a given http status to the client, it sets the Header with the correct content-type.
- Text: Same as WriteTextbut you don't have to pass a status, it's defaulted to http.StatusOK (200).
-
ReadJSON(jsonObject interface{}) error
- ReadJSON: reads the request's body content and parses it, assigning the result into jsonObject passed by argument. Don't forget to pass the argument as reference.
-
WriteJSON(status int, jsonObject interface{}) & JSON(jsonObject interface{}) returns error
- WriteJSON: Writes json which is converted from structed object(s) with a given http status to the client, it sets the Header with the correct content-type. If something goes wrong then it's returned value which is an error type is not nil. No indent.
-
RenderJSON(jsonObjects ...interface{}) returns error - RenderJSON: Same as WriteJSON & JSON but with Indent (formated json) - JSON: Same as WriteJSON but you don't have to pass a status, it's defaulted to http.StatusOK (200).
-
ReadXML(xmlObject interface{}) error
- ReadXML: reads the request's body and parses it, assigin the result into xmlObject passed by argument.
-
WriteXML(status int, xmlBytes []byte) & XML(xmlBytes []byte) returns error
- WriteXML: Writes writes xml which is converted from []byte( usualy string) with a given http status to the client, it sets the Header with the correct content-type. If something goes wrong then it's returned value which is an error type is not nil.
- XML: Same as WriteXML but you don't have to pass a status, it's defaulted to http.StatusOK (200).
-
RenderFile(file string, pageContext interface{}) returns error
- RenderFile: Renders a file by its name (which a file is saved to the template cache) and a page context passed to the function, default http status is http.StatusOK(200) if the template was found, otherwise http.StatusNotFound(404). If something goes wrong then it's returned value which is an error type is not nil.
-
Render(pageContext interface{}) returns error
- Render: Renders the root file template and a context passed to the function, default http status is http.StatusOK(200) if the template was found, otherwise http.StatusNotFound(404). If something goes wrong then it's returned value which is an error type is not nil. --- Note: We will learn how to add templates at the next chapters.
-
Next()
- Next: calls all the next handler from the middleware stack, it used inside a middleware.
-
SendStatus(statusCode int, message string)
- SendStatus: writes a http statusCode with a text/plain message.
-
Redirect(url string, statusCode...int) - Redirect: redirects the client to a specific relative path, if statusCode is empty then 302 is used (temporary redirect).
-
EmitError(statusCode int)
- EmitError: sends the custom error to the client by it's status code ( see Custom HTTP Errors chapter).
-
Panic()
- Panic: sends the 500 internal server (custom) error to the client.
[[TODO chapters: Register custom error handlers, cache templates , create & use middleware]]
Inside the examples branch you will find practical examples
Plugins are modules that you can build to inject the Iris' flow. Think it like a middleware for the Iris framework itself, not only the requests. Middleware starts it's actions after the server listen, Plugin on the other hand starts working when you registed them, from the begin, to the end. Look how it's interface looks:
type (
// IPlugin is the interface which all Plugins must implement.
//
// A Plugin can register other plugins also from it's Activate state
IPlugin interface {
// GetName has to returns the name of the plugin, a name is unique
// name has to be not dependent from other methods of the plugin,
// because it is being called even before the Activate
GetName() string
// GetDescription has to returns the description of what the plugins is used for
GetDescription() string
// Activate called BEFORE the plugin being added to the plugins list,
// if Activate returns none nil error then the plugin is not being added to the list
// it is being called only one time
//
// PluginContainer parameter used to add other plugins if that's necessary by the plugin
Activate(IPluginContainer) error
}
IPluginPreHandle interface {
// PreHandle it's being called every time BEFORE a Route is registed to the Router
//
// parameter is the Route
PreHandle(IRoute)
}
IPluginPostHandle interface {
// PostHandle it's being called every time AFTER a Route successfully registed to the Router
//
// parameter is the Route
PostHandle(IRoute)
}
IPluginPreListen interface {
// PreListen it's being called only one time, BEFORE the Server is started (if .Listen called)
// is used to do work at the time all other things are ready to go
// parameter is the station
PreListen(*Station)
}
IPluginPostListen interface {
// PostListen it's being called only one time, AFTER the Server is started (if .Listen called)
// parameter is the station
PostListen(*Station)
}
IPluginPreClose interface {
// PreClose it's being called only one time, BEFORE the Iris .Close method
// any plugin cleanup/clear memory happens here
//
// The plugin is deactivated after this state
PreClose(*Station)
}
)
A small example, imagine that you want to get all routes registered to your server (OR modify them at runtime), with their time registed, methods, (sub)domain and the path, what whould you do on other frameworks when you want something from the framework which it doesn't supports out of the box? and what you can do with Iris:
//file myplugin.go
package main
import (
"time"
"github.com/kataras/iris"
)
type RouteInfo struct {
Method string
Domain string
Path string
TimeRegisted time.Time
}
type myPlugin struct {
container iris.IPluginContainer
routes []RouteInfo
}
func NewMyPlugin() *myPlugin {
return &myPlugin{routes: make([]RouteInfo, 0)}
}
// All plugins must at least implements these 3 functions
func (i *myPlugin) Activate(container iris.IPluginContainer) error {
// use the container if you want to register other plugins to the server, yes it's possible a plugin can registers other plugins too.
// here we set the container in order to use it's printf later at the PostListen.
i.container = container
return nil
}
func (i myPlugin) GetName() string {
return "MyPlugin"
}
func (i myPlugin) GetDescription() string {
return "My Plugin is just a simple Iris plugin.\n"
}
//
// Implement our plugin, you can view your inject points - listeners on the /kataras/iris/plugin.go too.
//
// Implement the PostHandle, because this is what we need now, we need to add a listener after a route is registed to our server so we do:
func (i *myPlugin) PostHandle(route iris.IRoute) {
myRouteInfo := &RouteInfo{}
myRouteInfo.Method = route.GetMethod()
myRouteInfo.Domain = route.GetDomain()
myRouteInfo.Path = route.GetPath()
myRouteInfo.TimeRegisted = time.Now()
i.routes = append(i.routes, myRouteInfo)
}
// PostListen called after the server is started, here you can do a lot of staff
// you have the right to access the whole iris' Station also, here you can add more routes and do anything you want, for example start a second server too, an admin web interface!
// for example let's print to the server's stdout the routes we collected...
func (i *myPlugin) PostListen(s *iris.Station) {
i.container.Printf("From MyPlugin: You have registed %d routes ", len(i.routes))
//do what ever you want, if you have imagination you can do a lot
}
//
Let's register our plugin:
//file main.go
package main
import "github.com/kataras/iris"
func main() {
iris.Plugin(NewMyPlugin())
//the plugin is running and caching all these routes
iris.Get("/", func(c *iris.Context){})
iris.Post("/login", func(c *iris.Context){})
iris.Get("/login", func(c *iris.Context){})
iris.Get("/something", func(c *iris.Context){})
iris.Listen()
}
Output:
From MyPlugin: You have registed 4 routes
An example of one plugin which is under development is the Iris control, a web interface that gives you control to your server remotely. You can find it's code here
With Intel(R) Core(TM) i7-4710HQ CPU @ 2.50GHz 2.50 HGz and 8GB Ram:
- Total Operations (Executions)
- Nanoseconds per operation ns/op
- Heap Memory B/op
- Allocations per operation allocs/op
Benchmark name | Total Operations | ns/op | B/op | allocs/op |
---|---|---|---|---|
BenchmarkAce_GithubAll | 10000 | 121206 | 13792 | 167 |
BenchmarkBear_GithubAll | 10000 | 348919 | 86448 | 943 |
BenchmarkBeego_GithubAll | 5000 | 296816 | 16608 | 524 |
BenchmarkBone_GithubAll | 500 | 2502143 | 548736 | 7241 |
BenchmarkDenco_GithubAll | 20000 | 99705 | 20224 | 167 |
BenchmarkEcho_GithubAll | 30000 | 45469 | 0 | 0 |
BenchmarkGin_GithubAll | 50000 | 39402 | 0 | 0 |
BenchmarkGocraftWeb_GithubAll | 5000 | 446025 | 131656 | 1686 |
BenchmarkGoji_GithubAll | 2000 | 547698 | 56112 | 334 |
BenchmarkGojiv2_GithubAll | 2000 | 763043 | 118864 | 3103 |
BenchmarkGoJsonRest_GithubAll | 5000 | 538030 | 134371 | 2737 |
BenchmarkGoRestful_GithubAll | 100 | 14870850 | 837832 | 6913 |
BenchmarkGorillaMux_GithubAll | 200 | 6690383 | 144464 | 1588 |
BenchmarkHttpRouter_GithubAll | 20000 | 65653 | 13792 | 167 |
BenchmarkHttpTreeMux_GithubAll | 10000 | 215312 | 65856 | 671 |
BenchmarkIris_GithubAll | 100000 | 20731 | 0 | 0 |
BenchmarkKocha_GithubAll | 10000 | 167209 | 23304 | 843 |
BenchmarkLARS_GithubAll | 30000 | 41069 | 0 | 0 |
BenchmarkMacaron_GithubAll | 2000 | 665038 | 201138 | 1803 |
BenchmarkMartini_GithubAll | 100 | 5433644 | 228213 | 2483 |
BenchmarkPat_GithubAll | 300 | 4210240 | 1499569 | 27435 |
BenchmarkPossum_GithubAll | 10000 | 255114 | 84448 | 609 |
BenchmarkR2router_GithubAll | 10000 | 237113 | 77328 | 979 |
BenchmarkRevel_GithubAll | 2000 | 1150565 | 337424 | 5512 |
BenchmarkRivet_GithubAll | 20000 | 96555 | 16272 | 167 |
BenchmarkTango_GithubAll | 5000 | 417423 | 87075 | 2267 |
BenchmarkTigerTonic_GithubAll | 2000 | 994556 | 233680 | 5035 |
BenchmarkTraffic_GithubAll | 200 | 7770444 | 2659331 | 21848 |
BenchmarkVulcan_GithubAll | 5000 | 292216 | 19894 | 609 |
Note: Some of these, may not be work.
Iris has a middleware system to create it's own middleware and is at a state which tries to find person who are be willing to convert them to Iris middleware or create new. Contact or open an issue if you are interesting.
Middleware | Author | Description | Tested |
---|---|---|---|
sessions | Ported to Iris | Session Management | Yes |
Graceful | Tyler Bunnell | Graceful HTTP Shutdown | Yes |
gzip | Iris | GZIP response compression | Yes |
RestGate | Prasanga Siripala | Secure authentication for REST API endpoints | No |
secure | Cory Jacobsen | Middleware that implements a few quick security wins | Yes |
JWT Middleware | Auth0 | Middleware checks for a JWT on the Authorization header on incoming requests and decodes it |
No |
binding | Matt Holt | Data binding from HTTP requests into structs | No |
i18n | Iris | Internationalization and Localization | Yes |
logrus | Dan Buch | Logrus-based logger | No |
render | Cory Jacobsen | Render JSON, XML and HTML templates | No |
gorelic | Jingwen Owen Ou | New Relic agent for Go runtime | No |
pongo2 | Iris | Middleware for pongo2 templates | Yes |
oauth2 | David Bochenski | oAuth2 middleware | No |
permissions2 | Alexander Rødseth | Cookies, users and permissions | No |
onthefly | Alexander Rødseth | Generate TinySVG, HTML and CSS on the fly | No |
cors | Keuller Magalhaes | Cross Origin Resource Sharing (CORS) support | Yes |
xrequestid | Andrea Franz | Middleware that assigns a random X-Request-Id header to each request | No |
VanGoH | Taylor Wrobel | Configurable AWS-Style HMAC authentication middleware | No |
stats | Florent Messa | Store information about your web application (response time, etc.) | No |
Thanks goes to the people who have contributed code to this package, see the GitHub Contributors page.
If you'd like to discuss this package, or ask questions about it, feel free to
- Never stop writing the docs.
- Provide full README for examples branch and thirdparty middleware examples.
- Before any commit run -count 50 -benchtime 30s , if performance stays on top then commit else find other way to do the same thing.
- Notice the author of any thirdparty package before I try to port into iris myself, maybe they can do it better.
- Notice author's of middleware, which I'm writing examples for,to take a look, if they don't want to exists in the Iris community, I have to respect them.
- Provide a lighter, with less using bytes, to save middleware for a route.
- Create examples.
- Subdomains supports with the same syntax as iris.Get, iris.Post ...
- Provide a more detailed benchmark table to the README with all go web frameworks that I know, no just the 6 most famous
- Convert useful middlewares out there into Iris middlewares, or contact with their authors to do so.
- Provide automatic HTTPS using https://letsencrypt.org/how-it-works/.
- Create administration web interface as plugin.
- Create an easy websocket api.
- Create a mechanism that scan for Typescript files, compile them on server startup and serve them.
According to my article ( comparative ultra wide frame Go Http routing performance ) on a variety of relatively Go http routing framework, Iris clear winner, its performance far exceeds other Golang http routing framework.
- +1 pending article waiting, after writer's holidays
This project is licensed under the BSD 3-Clause License. License can be found here.