kataras / iris
- вторник, 15 марта 2016 г. в 02:13:32
Go
A very minimal but flexible golang web application framework, providing a robust set of features for building single & multi-page, web applications.
This project is under heavy development
Iris is a very minimal but flexible web framework written in go, providing a robust set of features for building single & multi-page, web applications.
$ go get github.com/kataras/iris
Iris is still in development status, in order to have the latest version update the package every 2-3 days
$ go get -u github.com/kataras/iris
Easy to use
Robust
Simplicity Equals Productivity. The best way to make something seem simple is to have it actually be simple. iris's main functionality has clean, classically beautiful APIs
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.Listen(":8080")
//or for https and http2
//iris.ListenTLS(8080,"localhost.cert","localhost.key")
//the cert and key must be in the same path of the executable main server file
}
Benchmark tests were written by 'the standar' way of benchmarking and comparing performance of other routers and frameworks, see go-http-routing-benchmark .
In order to have safe results, this table was taken from different source than Iris.
Benchmark name | 1 | 2 | 3 | 4 |
---|---|---|---|---|
BenchmarkAce_GithubAll | 10000 | 109482 | 13792 | 167 |
BenchmarkBear_GithubAll | 10000 | 287490 | 79952 | 943 |
BenchmarkBeego_GithubAll | 3000 | 562184 | 146272 | 2092 |
BenchmarkBone_GithubAll | 500 | 2578716 | 648016 | 8119 |
BenchmarkDenco_GithubAll | 20000 | 94955 | 20224 | 167 |
BenchmarkEcho_GithubAll | 30000 | 58705 | 0 | 0 |
BenchmarkGin_GithubAll | 30000 | 50991 | 0 | 0 |
BenchmarkGocraftWeb_GithubAll | 5000 | 449648 | 133280 | 1889 |
BenchmarkGoji_GithubAll | 2000 | 689748 | 56113 | 334 |
BenchmarkGoJsonRest_GithubAll | 5000 | 537769 | 135995 | 2940 |
BenchmarkGoRestful_GithubAll | 100 | 18410628 | 797236 | 7725 |
BenchmarkGorillaMux_GithubAll | 200 | 8036360 | 153137 | 1791 |
BenchmarkHttpRouter_GithubAll | 20000 | 63506 | 13792 | 167 |
BenchmarkHttpTreeMux_GithubAll | 10000 | 165927 | 56112 | 334 |
BenchmarkIris_GithubAll | 100000 | 19591 | 0 | 0 |
BenchmarkKocha_GithubAll | 10000 | 171362 | 23304 | 843 |
BenchmarkMacaron_GithubAll | 2000 | 817008 | 224960 | 2315 |
BenchmarkMartini_GithubAll | 100 | 12609209 | 237952 | 2686 |
BenchmarkPat_GithubAll | 300 | 4830398 | 1504101 | 32222 |
BenchmarkPossum_GithubAll | 10000 | 301716 | 97440 | 812 |
BenchmarkR2router_GithubAll | 10000 | 270691 | 77328 | 1182 |
BenchmarkRevel_GithubAll | 1000 | 1491919 | 345553 | 5918 |
BenchmarkRivet_GithubAll | 10000 | 283860 | 84272 | 1079 |
BenchmarkTango_GithubAll | 5000 | 473821 | 87078 | 2470 |
BenchmarkTigerTonic_GithubAll | 2000 | 1120131 | 241088 | 6052 |
BenchmarkTraffic_GithubAll | 200 | 8708979 | 2664762 | 22390 |
BenchmarkVulcan_GithubAll | 5000 | 353392 | 19894 | 609 |
BenchmarkZeus_GithubAll | 2000 | 944234 | 300688 | 2648 |
With Intel(R) Core(TM) i7-4710HQ CPU @ 2.50GHz 2.50 HGz and 8GB Ram:
Parameters in your routing pattern: Stop parsing the requested URL path, just give the path segment a name and the iris' router delivers the dynamic value to you. Really, path parameters are very cheap.
Can have static & parameterized matches: With other routers, like http.ServeMux, a requested URL path could match multiple patterns. Therefore they have some awkward pattern priority rules, like longest match or first registered, first matched. By design of this framework, a request can match to a static and parameterized routes at the same time, at any order you register them, the Iris' router is clever enough to understand the correct route for a request, so don't care just write your wonderful web app.
Party of routes: Combine routes where have same prefix, provide a middleware to this Party, a Party can have other Party too.
Compatible: At the end the Iris is just a middleware which acts like router and a small simply web framework, this means that you can you use it side-by-side with your favorite big and well-tested web framework. Iris is fully compatible with the net/http package.
Multi servers: Besides the fact that iris has a default main server. You can declare a new iris using the iris.New() func. example: server1:= iris.New(); server1.Get(....); server1.Listen(":9999")
As a developer you have three (3) methods to start with Iris.
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() {
options := iris.StationOptions{
Profile: false,
ProfilePath: iris.DefaultProfilePath,
Cache: true,
CacheMaxItems: 0,
CacheResetDuration: 5 * time.Minute,
}//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 a value not setted then the default used instead.
For example if we do that...
import "github.com/kataras/iris"
func main() {
options := iris.StationOptions{
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'):
Use of GET, POST, PUT, DELETE, HEAD, PATCH & OPTIONS
package main
import (
"github.com/kataras/iris"
"net/http"
)
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")
}
//iris is fully compatible with net/http package
func testGet(res http.ResponseWriter, req *http.Request) {
//...
}
//iris.Context gives more information and control of the route, as named parameters, redirect, error handling and render.
func testPost(c *iris.Context) {
//...
}
//and so on....
Let's party with Iris web framework!
func main() {
// manage all /users
users := iris.Party("/users")
{
users.Post("/login", loginHandler)
users.Get("/:userId", singleUserHandler)
users.Delete("/:userId", userAccountRemoveUserHandler)
}
// provide a simply middleware for this party
users.UseFunc(func(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
println("LOG [/users...] This is the middleware for: ", req.URL.Path)
next(res, req)
})
// Party inside an existing Party example:
beta:= iris.Party("/beta")
admin := beta.Party("/admin")
{
/// GET: /beta/admin/
admin.Get("/",adminIndexHandler)
/// POST: /beta/admin/signin
admin.Post("/signin", adminSigninHandler)
/// GET: /beta/admin/dashboard
admin.Get("/dashboard", admindashboardHandler)
/// PUT: /beta/admin/users/add
admin.Put("/users/add", adminAddUserHandler)
}
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
// 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 " + name)
})
// MATCH to /profile/kataras/friends/1
// NOT match to /profile/ , /profile/kataras ,
// NOT match to /profile/kataras/friends, /profile/kataras/friends ,
// NOT match to /profile/kataras/friends/2/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 iris.Build(); log.Fatal(http.ListenAndServe(":8080", iris))
}
Match everything/anything (symbol * (asterix))
// Will match any request which url's preffix is "/anything/"
iris.Get("/anything/*", func(c *iris.Context) { } )
// Match: /anything/whateverhere , /anything/blablabla
// Not Match: /anything , /anything/ , /something
Pure http static file server as handler using iris.Static("./path/to/the/resources/directory/")
// Will match any request which url's preffix is "/public/"
/* and continues with a file whith it's extension which exists inside the os.Gwd()(dot means working directory)+ /static/resources/
*/
iris.Any("/public/*", iris.Static("./static/resources/")) //or Get
//so simple
//Note: strip of the /public/ is handled so don't worry
Iris framework has three (3) different forms of functions in order to declare a route's handler and one(1) annotated struct to declare a complete route.
iris.Get("/user/add", func(res http.ResponseWriter, req *http.Request) {
})
iris.Get("/user/:userId", func(c *iris.Context) {
})
iris.Get("/about", http.HandlerFunc(func(res http.Response, req *req.Request) {
}))
///file: userhandler.go
import "github.com/kataras/iris"
type UserRoute struct {
iris.Annotated `get:"/profile/user/:userId"`
}
func (u *UserRoute) Handle(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
//...
iris.Templates("src/iristests/templates/*")
iris.Handle(&UserRoute{})
//...
Personally I use the external struct and the func(c *iris.Context) form . At the next chapter you will learn what are the benefits of having the Context as parameter to the handler.
Variables
Functions
Close()
WriteHTML(status int, contents string) & HTML(contents string)
The next chapters are being written this time, they will be published soon, check the docs later [[TODO chapters: Register custom error handlers, Add templates to the route, Declare middlewares]]
The iris is re-written in order to support all middlewares that are already exists for Negroni middleware
Here is a current list of compatible middlware.
Middleware | Author | Description |
---|---|---|
RestGate | Prasanga Siripala | Secure authentication for REST API endpoints |
Graceful | Tyler Bunnell | Graceful HTTP Shutdown |
secure | Cory Jacobsen | Middleware that implements a few quick security wins |
JWT Middleware | Auth0 | Middleware checks for a JWT on the Authorization header on incoming requests and decodes it |
binding | Matt Holt | Data binding from HTTP requests into structs |
logrus | Dan Buch | Logrus-based logger |
render | Cory Jacobsen | Render JSON, XML and HTML templates |
gorelic | Jingwen Owen Ou | New Relic agent for Go runtime |
gzip | phyber | GZIP response compression |
oauth2 | David Bochenski | oAuth2 middleware |
sessions | David Bochenski | Session Management |
permissions2 | Alexander Rødseth | Cookies, users and permissions |
onthefly | Alexander Rødseth | Generate TinySVG, HTML and CSS on the fly |
cors | Olivier Poitrey | Cross Origin Resource Sharing (CORS) support |
xrequestid | Andrea Franz | Middleware that assigns a random X-Request-Id header to each request |
VanGoH | Taylor Wrobel | Configurable AWS-Style HMAC authentication middleware |
stats | Florent Messa | Store information about your web application (response time, etc.) |
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
This project is licensed under the MIT license.