Guards
You can protect your routes with guards.
A guard allows you to execute logic before a certain request reaches a designated route handler.
Start by adding a guard to the server
package main
import ( "github.com/razshare/frizzante/connections" "github.com/razshare/frizzante/guards" "github.com/razshare/frizzante/routes" "github.com/razshare/frizzante/servers")
var server = servers.New() // Creates a server.
func main() { server.Guards = append(server.Guards, { // Adds a guard. Name: "No Json Allowed", // Sets the guard's name. It's useful for logs. Handler: func(connection *connections.Connection, allow func()) { // Sets the guard's handler. if connection.VerifyContentType("application/json") { // If requests uses "application/json" content... return // ..returns. This will actually terminate the connection. } allow() // Allows the request through. }, Tags: []string{"nojson", "jsonless"}, // Sets the guard's tags. }) server.AddRoute(routes.Route{ // Adds a route. Pattern: "GET /", // Sets the route's pattern. Handler: func(connection *connections.Connection) { connection.SendMessage("Hello.") // Sends text. }, Tags: []string{"nojson"}, // Sets the route's tags. Any guard that intersects // with these tags will execute before any // request reaches the route's handler. }) server.Start() // Starts the server.}
A guard protects every route whose tags intersect with at least one of its own tags.
In this case, the GET /
route intersects with the No Json Allowed
guard in nojson
, which means GET /
is protected by No Json Allowed
.
Composition
Section titled “Composition”Multiple guards can intersect in order to compose more advanced restrictions.
server.Guards = append(server.Guards, { // Adds a guard. Name: "Authorization", // Sets the guard's name. It's useful for logs. Handler: func(connection *connections.Connection, allow func()) { // Sets the guard's handler. If allow() is never invoked, // the guard will reject the request.
auth := connection.ReceiveHeader("Authorization") // Gets the "Authorization" header from the request. if !SuperAdvancedAuthorizationCheckTM(auth) { // If user is not authorized... connection.SendStatus(403) // ...sends status 403... connection.SendMessage("Not authorized.") // ...and a short message with an explanation. return // Returns. This will actually terminate the connection. } allow() // Allows the request through. }, Tags: []string{"authorization", "auth"}, // Sets the guard's tags.})
server.Guards = append(server.Guards, { // Adds a guard. Name: "Authentication", // Sets the guard's name. It's useful for logs. Handler: func(connection *connections.Connection, allow func()) { // Sets the guard's handler. If allow() is never invoked, // the guard will reject the request.
session := sessions.New(connection, State{}).Start() // Starts the session. if !session.State.SignedIn { // If the use is not signed in... connection.SendStatus(403) // ...sends status 403... connection.SendMessage("Not authenticated.") // ...and a short message with an explanation. return // Returns. This will actually terminate the connection. } allow() // Allows the request through. }, Tags: []string{"authentication", "auth"}, // Sets the guard's tags.})
server.Guards = append(server.Guards, { // Adds a route. Pattern: "GET /", // Sets the route's pattern. Handler: func(connection *connections.Connection) { // Sets the route's handler. connection.SendMessage("Hello.") // Sends text. }, Tags: []string{"auth"}, // Sets the route's tags. Any guard that intersects // with these tags will execute before any // request reaches the route's handler.})
In this case, GET /
is protected by both Authentication
and Authorization
guards because they all intersect int auth
.