1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-20 03:17:04 +00:00

Publish the new version ✈️ | Look description please!

# FAQ

### Looking for free support?

	http://support.iris-go.com
    https://kataras.rocket.chat/channel/iris

### Looking for previous versions?

    https://github.com/kataras/iris#version

### Should I upgrade my Iris?

Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.

**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).

### About our new home page
    http://iris-go.com

Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!

[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.

The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!

Read more at https://github.com/kataras/iris/blob/master/HISTORY.md


Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
This commit is contained in:
kataras
2017-06-03 23:22:52 +03:00
parent 03bcadadec
commit 5e4b63acb2
330 changed files with 35786 additions and 17316 deletions

View File

@@ -0,0 +1,170 @@
package main
import (
"github.com/kataras/iris"
"github.com/kataras/iris/context"
)
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 context.Context) -> The route's handler.
//
// Third receiver should contains the route's handler(s), they are executed by order.
app.Handle("GET", "/", func(ctx context.Context) {
// navigate to the middle of $GOPATH/src/github.com/kataras/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 context.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 context.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 context.Context){}) -> for POST http method.
// app.Put("/", func(ctx context.Context){})-> for "PUT" http method.
// app.Delete("/", func(ctx context.Context){})-> for "DELETE" http method.
// app.Options("/", func(ctx context.Context){})-> for "OPTIONS" http method.
// app.Trace("/", func(ctx context.Context){})-> for "TRACE" http method.
// app.Head("/", func(ctx context.Context){})-> for "HEAD" http method.
// app.Connect("/", func(ctx context.Context){})-> for "CONNECT" http method.
// app.Patch("/", func(ctx context.Context){})-> for "PATCH" http method.
// app.Any("/", func(ctx context.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 context.Context) { // executes always last if ctx.Next()
ctx.Application().Log("response sent to " + ctx.Path())
})
// adminRoutes.Layout("/views/layouts/admin.html") // set a view layout for these routes, see more at intermediate/view examples.
// GET: http://localhost:8080/admin
adminRoutes.Get("/", func(ctx context.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 context.Context) {
// [...]
})
// POST: http://localhost:8080/admin/login
adminRoutes.Post("/login", func(ctx context.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 context.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 context.Context) {
ctx.Writef("All users")
})
// http://v1.localhost:8080/api/users/42
usersAPI.Get("/{userid:int}", func(ctx context.Context) {
ctx.Writef("user with id: %s", ctx.Params().Get("userid"))
})
}
}
// wildcard subdomains.
wildcardSubdomain := app.Party("*.")
{
wildcardSubdomain.Get("/", func(ctx context.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 context.Context) {
// [...]
ctx.Next() // to move to the next handler, or don't that if you have any auth logic.
}
func donateHandler(ctx context.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/kataras/iris#buy-me-a-cup-of-coffee")
ctx.Next() // in order to execute the next handler in the chain, look donate route.
}
func donateFinishHandler(ctx context.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().Log("donate_url value was: " + donateURL)
ctx.Writef("\n\nDonate sent(?).")
}
func notFoundHandler(ctx context.Context) {
ctx.HTML("Custom route for 404 not found http code, here you can render a view, html, json <b>any valid response</b>.")
}
// Notes:
// 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....

View File

@@ -0,0 +1,183 @@
package main
import (
"strconv"
"github.com/kataras/iris"
"github.com/kataras/iris/context"
)
func main() {
app := iris.New()
// At the previous example "routing/basic",
// we've seen static routes, group of routes, subdomains, wildcard subdomains, a small example of parameterized path
// with a single known paramete 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 context.Context)
// where context comes from github.com/kataras/iris/context.
// Until go 1.9 you will have to import that package too, after go 1.9 this will be not be necessary.
//
// Iris has the easiest and the most powerful routing process you have ever meet.
// If you're used to use the "httprouter"
// then you don't have to change a thing of a route's path.
//
// 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,
// I am calling them "macros" for shortcut.
// In the following examples we will see only the second option, which has exactly the same speed
// compared to "httprouter".
// How? It calculates its needs and if not any special regexp needed then it just
// registers the route with the underline httprouter's path syntax,
// otherwise it pre-compiles the regexp and adds the necessary middleware(s).
//
// Note: the Iris' router follows the "httprouter"'s rules for routes confliction.
//
// Standard macro types for parameters:
// +------------------------+
// | {param:string} |
// +------------------------+
// string type
// anything
//
// +------------------------+
// | {param:int} |
// +------------------------+
// int type
// only numbers (0-9)
//
// +------------------------+
// | {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().GetString("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 }
// })
// you can use the "string" type which is valid for a single path parameter that can be anything.
app.Get("/username/{name}", func(ctx context.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 context.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 context.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 context.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/kataras
app.Get("/lowercase/{name:string regexp(^[a-z]+)}", func(ctx context.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 context.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 context.Context) {
ctx.Writef("path type accepts any number of path segments, path after /myfiles/ is: %s", ctx.Params().Get("directory"))
}) // for wildcard path (any number of path segments) without validation you can use:
// /myfiles/*directory
// "{param}"'s performance is exactly the same of ":param"'s.
// alternatives -> ":param" for single path parameter and "*paramPath" for wildcard path parameter
// acquire them by ctx.Params().Get as always.
// WARNING:
// 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.
if err := app.Run(iris.Addr(":8080")); err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,107 @@
package main
import (
"io/ioutil"
"github.com/kataras/iris"
"github.com/kataras/iris/context"
)
/*
Read:
"basic"
"dynamic-path"
and "reverse" examples if you want to release Iris' real power.
*/
const maxBodySize = 1 << 20
var app *iris.Application
func init() {
app = iris.New()
}
func registerErrors() {
// set a custom 404 handler
app.OnErrorCode(iris.StatusNotFound, func(ctx context.Context) {
ctx.HTML("<h1> custom http error page </h1>")
})
}
func registerGamesRoutes() {
gamesMiddleware := func(ctx context.Context) {
println(ctx.Method() + ": " + ctx.Path())
ctx.Next()
}
// party is just a group of routes with the same prefix
// and middleware, i.e: "/games" and gamesMiddleware.
games := app.Party("/games", gamesMiddleware)
{ // braces are optional of course, it's just a style of code
// "GET" method
games.Get("/{gameID:int}/clans", h)
games.Get("/{gameID:int}/clans/clan/{clanPublicID:int}", h)
games.Get("/{gameID:int}/clans/search", h)
// "PUT" method
games.Put("/{gameID:int}/players/{clanPublicID:int}", h)
games.Put("/{gameID:int}/clans/clan/{clanPublicID:int}", h)
// remember: "clanPublicID" should not be changed to other routes with the same prefix.
// "POST" method
games.Post("/{gameID:int}/clans", h)
games.Post("/{gameID:int}/players", h)
games.Post("/{gameID:int}/clans/{clanPublicID:int}/leave", h)
games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/application", h)
games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/application/{action}", h) // {action} == {action:string}
games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/invitation", h)
games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/invitation/{action}", h)
games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/delete", h)
games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/promote", h)
games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/demote", h)
}
}
func registerSubdomains() {
mysubdomain := app.Party("mysubdomain.")
// http://mysubdomain.myhost.com
mysubdomain.Get("/", func(ctx context.Context) {
ctx.Writef("Hello from subdomain: %s , from host: %s, method: %s and path: %s", ctx.Subdomain(), ctx.Host(), ctx.Method(), ctx.Path())
})
}
func main() {
registerErrors()
registerGamesRoutes()
registerSubdomains()
// more random examples below:
app.Handle("GET", "/healthcheck", h)
// "POST" method
// this handler reads raw body from the client/request
// and sends back the same body
// remember, we have limit to that body in order
// to protect ourselves from "over heating".
app.Post("/", func(ctx context.Context) {
ctx.SetMaxRequestBodySize(maxBodySize) // set max request body that client can send.
// get request body
b, err := ioutil.ReadAll(ctx.Request().Body)
// if is larger then send a bad request status
if err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Writef(err.Error())
return
}
// send back the post body
ctx.Write(b)
})
// start the server on 0.0.0.0:8080
app.Run(iris.Addr(":8080"))
}
func h(ctx context.Context) {
ctx.HTML("<h1>Path: " + ctx.Path() + "</h1>")
}

View File

@@ -0,0 +1,35 @@
package main
import (
"github.com/kataras/iris"
"github.com/kataras/iris/context"
"github.com/kataras/iris/core/router"
)
func main() {
app := iris.New()
// need for manually reverse routing when needed outside of view engine.
// you normally don't need it because of the {{ urlpath "routename" "path" "values" "here"}}
rv := router.NewRoutePathReverser(app)
myroute, _ := app.Get("/anything/{anythingparameter:path}", func(ctx context.Context) {
paramValue := ctx.Params().Get("anythingparameter")
ctx.Writef("The path after /anything is: %s", paramValue)
})
// useful for links, altough iris' view engine has the {{ urlpath "routename" "path values"}} already.
app.Get("/reverse_myroute", func(ctx context.Context) {
myrouteRequestPath := rv.Path(myroute.Name, "any/path")
ctx.HTML("Should be <b>/anything/any/path</b>: " + myrouteRequestPath)
})
// execute a route, similar to redirect but without redirect :)
app.Get("/execute_myroute", func(ctx context.Context) {
ctx.Exec("GET", "/anything/any/path") // like it was called by the client.
})
// http://localhost:8080/reverse_myroute
// http://localhost:8080/execute_myroute
// http://localhost:8080/anything/any/path/here
app.Run(iris.Addr(":8080"))
}