Guards
You can protect your routes with guards.
A guard is an object that is composed of an optional name, a required handler and slice of tags.
You can add guards to the server by appending to or overwriting the srv.Guards
field.
package main
import ( "main/lib/core/client" "main/lib/core/route" "main/lib/core/server" "main/lib/core/tag" "main/lib/routes/api/xml/data")
const nojson tag.Tag = 0 // Creates tag.var srv = server.New() // Creates server.
func main() { defer server.Start(srv) // Starts server. srv.Guards = []srv.Guards{ { // Adds guard. Name: "NoJson", // Sets guard name (It's useful for logs). Handler: func(c *client.Client, allow func()) { // Sets guard handler. if receive.ContentType(c) == "application/json" { // Checks content type. return // Returns - this will actually terminate the connection. } allow() // Allows request through. }, Tags: []tag.Tag{nojson}, // Sets guard tags. }, }}
You can protect a route by tagging it.
srv.Routes = []route.Route{ { // Adds route. Pattern: "GET /api/xml/data", // Sets route pattern. Handler: data.Get, // Sets route handler. Tags: []tag.Tag{nojson}, // Sets route tags. },}
In this case "GET /api/xml/data"
is tagged with nojson
, which means it’s protected by "NoJson"
.
Composition
Section titled “Composition”You can compose multiple tags in order to create more advanced restrictions.
const auth tag.Tag = 0 // Creates tag.const authentication tag.Tag = 1 // Creates tag.const authorization tag.Tag = 2 // Creates tag.
src.Guards = []guard.Guards{ { // Adds authentication guard. Name: "Authentication", // Sets guard name (useful for logs). Handler: func(c *client.Client, allow func()) { // Sets guard handler. Call allow() in order to permit the request to // advance to the next guard or to the route handler. s := session.Start(receive.SessionId(c)) // Starts session. if s.Verified && // Checks if client is verified. This "Verified" field is // usually set by a public route, like a /login page. time.Since(s.LastActivity) <= 30*time.Minute { // Checks if client has been active in the past 30 minutes. allow() // Allows the request through. return } send.Status(c, 401) // Hints to client that authentication is missing. send.Message(c, "not authenticated") // Sends a readable hint message. return // At this point allow() has not been called, so the request is blocked. }, Tags: []tag.Tag{authentication, auth}, // Sets the guard tags - use any of these tags to apply this guard to any route. }, { // Adds authorization guard. Name: "Authorization", // Sets guard name (useful for logs). Handler: func(c *client.Client, allow func()) { // Sets guard handler. s := session.Start(receive.SessionId(c)) // Starts session. if s.UserId == receive.path("user_id") { // Checks if session user id matches requested user id. allow() // Allows the request through. return } send.Status(c, 401) // Hints to client that authorization is missing. send.Message(c, "not authorized") // Sends a readable hint message. return // At this point allow() has not been called, so the request is blocked. }, Tags: []tag.Tag{authorization, auth}, // Sets the guard tags - use any of these tags to apply this guard to any route. },}
srv.Routes = []route.Route{ { // Adds route. Pattern: "GET /public", // Sets route pattern. Handler: publicHandler, // Sets route handler. // No requirements - it's public. }, { // Adds route. Pattern: "GET /dashboard", // Sets route pattern. Handler: dashboardHandler, // Sets route handler. Tags: []tag.Tag{authentication}, // Requires authentication. }, { // Adds route. Pattern: "GET /user/{user_id}/settings", // Sets route pattern. Handler: userSettingsHandler, // Sets route handler. Tags: []tag.Tag{auth}, // Requires auth, meaning both authentication and authorization. }, { // Adds route. Pattern: "DELETE /user/{user_id}", // Sets route pattern. Handler: deleteUserHandler, // Sets route handler. Tags: []tag.Tag{auth}, // Requires auth, meaning both authentication and authorization. },}
In this example "GET /dashboard"
is protected by "Authentication"
, while "GET /user/{user_id}/settings"
and "DELETE /user/{user_id}"
are protected by both "Authentication"
and "Authorization"
.