Routes and scopes
Routing in celerity is done using Routes and Scopes. Routes represent an endpoint in the application that can be handled. Scopes are groups of Routes that can share middleware and URL paths.
Route handlers
When creating routes you must specify a route handler which is a function that is invoked when the route is requested. The handler has the following definition:
func MyHandler (c celerity.Context) celerity.Response
The provided context object contains information about the request, as well as helper functions for generating response objects.
Handler responses
Celerity is built with JSON APIs in mind. You can return any value using the
context’s Response
function (which is aliased to R). The value passed will
automatically be serialized into JSON and used as the response.
A simple response
func MyHandler(c celerity.Context) celerity.Response {
users := GetUsers()
c.R(users)
}
Transforming responses
Sometimes it might be necessary to transform, or clean, data before responding.
In this case you can create an anonymous struct
and respond with it.
func MyHandler(c celerity.Context) celerity.Response {
user := GetUser()
profile := GetProfile()
resp := struct {
User: User `json:"users"`
Profile Profile `json:"profile"`
}{
Users: users,
Profile: profile,
}
c.R(resp)
}
Error responses
If an error occurs in the endpoint that can not be recovered from. The Fail()
function will respond with an error status and message. Fail()
acts
differently depending on the environment. When running in a development
environment the errors message will be relayed to the client. In a production
environment a generic error message is displayed.
NOTE: The HTTP status code is always set to 500.
func MyHandler(c celerity.Context) celerity.Response {
res, err := doTheThing()
if error != nil {
return c.Fail(err)
}
return c.R(res)
}
To respond with an intentional error, such as invalid data or authentication
related errors. You will want to display an error message, even in a production
environment, and set the HTTP status code. The celerity.NewErrorResponse
will
create a response object that can be returned.
func MyHandler(c celerity.Context) celerity.Response {
res, err := doTheThing()
if error != nil {
return celerity.NewErrorResponse(http.StatusBadRequest, err.Error())
}
return c.R(res)
}
Creating routes
To create a route use the Route
function or one of the HTTP method functions.
svr := celerity.New()
svr.GET("/users", func (c celerity.Context) celerity.Response {
users := GetUsers()
c.R(users)
})
Working with scopes
Scopes can logically group routes together in order to share preprocessing logic (middleware) and to help organize paths. Authenticated and unauthenticated routes for example can be grouped into selenate scopes. One scope can be given an authentication middleware and routes in the other scope will not use it.
Routes are defined just like they are on the base server. In fact, the Routing functions on the base server simply alias to an internal root scope that is generated with the server’s router.
Creating scopes
svr := celerity.New()
// unauthenticated routes
svr.Route("/login")
//authenticated routes
secured := svr.Scope("/")
secured.GET("/profile", profileHandler)
Nesting scopes
Scopes can be nested at any level. This allows freedom to create more complicated routing rules.
svr := celerity.New()
// unauthenticated routes
svr.Route("/login")
//authenticated routes
secured := svr.Scope("/")
secured.GET("/profile", profileHandler)
// administrative routes
admin := secured.Scope("/admin")
admin.GET("/stats", statsHandler)
Using middleware
Middleware allows a scope to process logic and transform the request before the route is invoked. This is useful for any type of action that is shared between routes: Such as validating authentication, adding headers, etc.
Middleware generally has a factory function which generates the middleware
handler for you and can be passed to the server or a scope, with the Use
function.
import(
"github.com/5Sigma/celerity"
"github.com/5Sigma/celerity/middleware"
)
svr := celerity.New()
svr.Use(middleware.CORSMiddleware())
Celerity comes with a number of built in middlewares that can be easily added to the server. Alternatively you can easily create your own middleware.