Skip to main content

Router

Routing is used to define application endpoints (URIs) for responding to client requests.

A route can be registered through standard HTTP request methods, specifying a URL path and handler function (HandlerFunc). The following code demonstrates an example of registering a route: it includes the GET access method, the access path value /hello, and an HTTP handler that can respond with Hello World.

Define route
// Business handler
func hello(c slim.Context) error {
return c.String(http.StatusOK, "Hello, World!")
}

s := slim.New()
r := s.Router()

// Route
r.GET("/hello", hello)

We can use r.Any(pattern string, h slim.HandlerFunc) to register handlers for all HTTP methods; If you only need to register a route for specific methods, you can use the method r.Some(methods []string, pattern string, h HandlerFunc).

Route Pattern

We use the character / as a hierarchical delimiter for route patterns. Then, each level can be distinguished into static layers and dynamic layers as needed, ultimately forming a prefix tree-based routing tree, where each layer is called a route node.

There are mainly three types of route nodes, in order of matching priority:

  • Static nodes declared using literals, such as the pattern /users/new;
  • Parameter nodes declared starting with /: followed by a variable name, such as /:id in the pattern /users/:id is a parameter node with variable name id;
  • Wildcard nodes declared starting with /* optionally followed by a variable name, such as /* in the pattern /users/* matches all requests starting with /users/. Additionally, we can name this wildcard pattern like /users/*name, and then retrieve the value of the wildcard part through the variable name name.
Example
s := slim.Classic()
r := s.Router()

// Declare parameter node using `colon+variable name`
r.GET("/users/:id", func(c slim.Context) error {
return c.String(http.StatusOK, "/users/:id")
})

// Declare a route with a fixed path
r.GET("/users/new", func(c slim.Context) error {
return c.String(http.StatusOK, "/users/new")
})

// Declare a wildcard node using `*`
r.GET("/users/*", func(c slim.Context) error {
return c.String(http.StatusOK, "/users/*")
})

The routes defined above will match in the following priority order:

  1. /users/new
  2. /users/:id
  3. /users/*
tip

Fully static routes have higher priority than parameter routes, and parameter routes have higher priority than wildcard routes.

Route Handler

Route handlers serve as HTTP request endpoints and are used to respond to client requests.

Handler function signature
type HandlerFunc(c slim.Context) error

Route Methods

We have defined some commonly used route methods, each corresponding to different HTTP request methods:

Consistent with HTTP standard request methods
// CONNECT registers a new CONNECT route for a path with matching handler in
// the router. Panics on error.
CONNECT(pattern string, h HandlerFunc) Route
// DELETE registers a new DELETE route for a path with matching handler in
// the router. Panics on error.
DELETE(pattern string, h HandlerFunc) Route
// GET registers a new GET route for a path with matching handler in
// the router. Panics on error.
GET(pattern string, h HandlerFunc) Route
// HEAD registers a new HEAD route for a path with matching handler in
// the router. Panics on error.
HEAD(pattern string, h HandlerFunc) Route
// OPTIONS registers a new OPTIONS route for a path with matching handler
// in the router. Panics on error.
OPTIONS(pattern string, h HandlerFunc) Route
// PATCH registers a new PATCH route for a path with matching handler in
// the router. Panics on error.
PATCH(pattern string, h HandlerFunc) Route
// POST registers a new POST route for a path with matching handler in
// the router. Panics on error.
POST(pattern string, h HandlerFunc) Route
// PUT registers a new PUT route for a path with matching handler in
// the router. Panics on error.
PUT(pattern string, h HandlerFunc) Route
// TRACE registers a new TRACE route for a path with matching handler in
// the router. Panics on error.
TRACE(pattern string, h HandlerFunc) Route

Additionally, there are four methods:

// Some registers a new route for multiple HTTP methods and path with matching
// handler in the router. Panics on error.
r.Some(methods []string, pattern string, h slim.HandlerFunc) slim.Route
// Any registers a new route for all supported HTTP methods and path with matching
// handler in the router. Panics on error.
r.Any(pattern string, h slim.HandlerFunc) slim.Route
// Static registers a new route with path prefix to serve static files
// from the provided root directory. Panics on error.
r.Static(prefix, root string) Route
// File registers a new route with a path to serve a static file.
// Panics on error.
r.File(pattern, file string) Route

Route

All router methods return a route instance slim.Route describing the current registration. At this point, you can specify a name for this route through the method slim.Route#SetName, and you can also register dedicated middleware for this route using the method slim.Route#Use.

Set route properties
route := s.GET("/users/:id", handler)
route.SetName("userhome")
route.Use(AuthMiddleware)

// The above code can also be written in a chain
s.GET("/users/:id", handler).
SetName("userhome").
Use(AuthMiddleware)

Route Group

We can group routes with the same prefix, defining new sub-routes with optional middleware. Route groups can also be nested to form hierarchical relationships.

In the code below, we create an admin group, adding custom middleware for /admin/* routes.

Group based on common prefix
g := s.Route("/admin", func(r slim.RouteCollector) {
// Add authentication middleware
r.Use(func(c slim.Context, next slim.HandlerFunc) error {
// Authentication logic can be implemented here
// For example, check token, session, etc.
return next(c)
})

r.GET("/:id", GetAdmin)
// ...other routes
})

When routes share the same prefix but different routes need different middleware to filter requests, we can use the Group method:

Prefix-less grouping
s.Route("/admin", func(r slim.RouteCollector) {
// Prefix-less grouping, routes inside share middleware `Role("manager")`
r.Group(func(r slim.RouteCollector) {
r.Use(Role("manager"))
r.Get("/:id", GetAdmin)
// ...other routes
})
// ...other groups
})

Route groups are implemented using the RouteCollector interface, so route groups are just another name for route collectors.