Routing
Basic Routes
Routes are defined by specifying a URI pattern and Callback
to the router.
// Respond with "Hello World!" to GET request with the path /hi
router.Get("/hi", func(res h.Response) h.Result {
return res.Data("Hello World!")
})
All common HTTP verbs have a corresponding method.
r.Get(uri string, callback h.Callback)
r.Post(uri string, callback h.Callback)
r.Put(uri string, callback h.Callback)
r.Patch(uri string, callback h.Callback)
r.Delete(uri string, callback h.Callback)
// Even less common verbs
r.Options(uri string, callback h.Callback)
r.Head(uri string, callback h.Callback)
r.Connect(uri string, callback h.Callback)
r.Trace(uri string, callback h.Callback)
There is also a Match
method to match multiple HTTP verbs, and an Any
method
to match all HTTP verbs.
r.Match([]string{"GET", "CUSTOM"}, "/", func(res h.Response) h.Result {
// ...
})
r.Any("/", func(res h.Response) h.Result {
// ...
})
Callback Function
The second argument to create a route is the Callback
, which is called whenever an
HTTP request is received that matches the URI pattern. Callback can receive any arguments,
that can be resolved by the IoC container.
For example, you can access settings from the Config
object.
r.Get("/", func(res h.Response, c *hemlock.Config) h.Result {
return res.Data("Running on port: "+c.HTTP.Port)
})
Or access user input from the request.
r.Get("/", func(res h.Response, req h.Request) h.Result {
return res.Dataf("Query param foo: "+req.Query("foo"))
})
Redirects
For simple redirects, the Redirect
method can be used to redirect the client to another
URI.
r.Redirect("/old/page", "/new/page", 302)
Views
A view can also be
r.View("/", "home.html", "base.html", )
Route Parameters
Basic URL parameters can be added using the {name}
notation. These parameters
can be accessed by specifying them as arguments at the end of the Callback
.
Any route parameters are appended to the Callback
arguments when the route is invoked.
r.Get(
"/hi/{name}/{message}",
func(res h.Response, name, message string) h.Result {
return res.Dataf("Hi %s! %s.", name, message)
},
)
Regular Expression
Patterns can also contain a regular expression.
Here is an example that uses a regular expression pattern to differentiate numerical user IDs from usernames.
r.Get("/users/{id:[0-9]+}", useByID) // Only match numbers
r.Get("/users/{id}", userByUsername) // Match everything else
Middleware
Both the Use
and With
method can be used to assign middleware.
The Use
method applies middleware directly to the router or route reference.
r.Use(func(req h.Request, res h.Response, next h.Next) h.Result {
// ...
}
The With
method is similar to Use
but creates a new router instance with the applied
middleware.
r.With(adminMiddleware).Get("/admin/dashboard", adminPanel)
Named Routes
Routes can be assigned names which can be used to reference them later on.
r.Get("/users", listUsers).Name("users.list")
r.Get("/users/{id}", showUser).Name("users.show")
For example, a URL can be constructed for named routes.
<a href="{{ route "users.list" }}">
List Users
</a>
<a href="{{ route "users.show" "id" "123" }}">
Show User
</a>
Requests can also be redirected to named routes.
r.Get("/account", func(res h.Response) h.Result {
return res.RedirectRoute("users.list", nil)
)
r.Get("/accounts/{id}", func(res h.Response, id string) h.Result {
return res.RedirectRoute("users.show", map[string]string{"id": id})
)
Grouping Routes
The Group
method creates a new child router instance. All routes defined on the new
router will have the previous filters applied.
r.Host("admin.gohemlock.com").Prefix("/admin").Group(func(r h.Router) {
r.Use(adminMiddleware)
r.Get("/dashboard", adminPanel) // [GET] /admin/panel
r.Put("/revoke/{username}", adminBan) // [PUT] /admin/revoke/gschier
})
RESTful Routes
The Group
method is useful for combining routes related to the same resource.
r.Prefix("/tasks").Group(func(r h.Router) {
r.Use(authedMiddleware)
r.Get("/", users.List) // [GET] /tasks
r.Post("/", users.Create) // [POST] /tasks
r.Prefix("/{id}").Group(func(r h.Router) {
r.Get("/", users.Show) // [GET] /tasks/gschier
r.Delete("/", users.Delete) // [DELETE] /tasks/gschier
r.Patch("/", users.Update) // [PATCH] /tasks/gschier
})
})
Advanced Usage
There are a few more methods that offer precise control over route creation.
Use Callback
to match any URI on the current router which most commonly paired with
the Prefix
method.
r.Prefix("/docs").Callback(serveMarkdown)
Methods
also adds an additional level of control.
r.Methods("GET", "HEAD").Prefix("/docs").Callback(serveMarkdown)
// Or a more realistic advanced example...
r.Prefix("/docs").Methods("GET", "HEAD").Group(func(r h.Router) {
r.Use(adminOnlyMiddleware)
r.Use(cachedMiddleware)
// Use `Callback` to match any route within the route group
// [GET] /docs
// [HEAD] /docs/foo.md
// [GET] /docs/foo/bar.md
// ...
r.Callback(serveMarkdown)
})