Skip to content

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".

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".