Simple, dependency-free, and Express-styled HTTP Router written in Go.
- Simple and easy to use
- Expressjs-style routing
- Relies only on the Go standard library
- Uses net/http ServeMux under the hood
- Static files handling
- Common middlewares available out of the box
- Go 1.22 or higher
go get github.com/ferdiebergado/go-express
- Import the router.
import router "github.com/ferdiebergado/go-express"
- Create a router.
router := router.NewRouter()
- Register global middlewares.
Global middlewares are registered by calling the Use() method on the router.
router.Use(RequestLogger)
go-express has some commonly-used middlewares available out of the box, just import it from the middleware package.
import (
"github.com/ferdiebergado/go-express/router"
"github.com/ferdiebergado/go-express/middleware"
)
func main() {
router := router.NewRouter()
router.Use(middleware.RequestLogger)
router.Use(middleware.StripTrailingSlashes)
router.Use(middleware.PanicRecovery)
}
- Register routes.
Similar to express, the http methods are available as methods in the router. The method accepts the path and the handler as arguments.
router.Get(path, handler)
Example:
router.Get("/todos", TodoHandler)
The handler is a function that accepts an http.ResponseWriter and a pointer to an http.Request as arguments.
func Handler(w http.ResponseWriter, r *http.Request)
Example:
func TodoHandler(w http.ResponseWriter, r *http.Request) {
w.write([]byte("Todos"))
}
Optionally, you can register path-specific middlewares by passing them as arguments after the handler.
router.Post("/todos", CreateTodoHandler, SessionMiddleware, AuthMiddleware)
In here, the route has two specific middlewares: SessionMiddleware and AuthMiddleware.
You can pass any number of middlewares to a route.
- Start an http server with the router.
http.ListenAndServe(":8080", router)
go-express makes it easy to serve static files from a specified directory. Simply provide the name of the directory containing the static files to be served to the ServeStatic method of the router.
router.ServeStatic("assets")
This will serve files from the "assets" directory at "/assets/". Now, any request the starts with /assets/ will serve files from this directory, e.g. /assets/styles.css.
You can then add this to the head tag of your html:
<head>
<link rel="stylesheet" src="/assets/styles.css">
<script src="/assets/js/app.js" defer>
</head>
By default, go-express returns a 404 status code and plain status text when an unregistered route is requested. To customize this behavior, pass an http handler function to the NotFound method of the router.
Example:
router.NotFound(func(w http.ResponseWriter, r *http.Request){
templates := template.Must(template.ParseGlob("templates/*.html"))
var buf bytes.Buffer
if err := templates.ExecuteTemplate(&buf, "404.html", nil); err != nil {
log.Prinf("execute template: %w", err)
return
}
_, err = buf.WriteTo(w)
if err != nil {
log.Printf("write to buffer: %w", err)
return
}
})
Middlewares are functions that accept an http.Handler and returns another http.Handler.
func Middleware(next http.Handler) http.Handler
Example:
func RequestLogger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
duration := time.Since(start)
log.Printf("%s %s %s %d", r.Method, r.URL.Path, r.Proto, duration)
})
}
package main
import (
"net/http"
router "github.com/ferdiebergado/go-express"
"github.com/ferdiebergado/go-express/middleware"
)
func main() {
// Create the router.
router := router.NewRouter()
// Register global middlewares.
router.Use(middleware.RequestLogger)
router.Use(middleware.StripTrailingSlashes)
router.Use(middleware.PanicRecovery)
// Serve static files.
router.ServeStatic("assets")
// Register routes.
router.Get("/api/todos", ListTodos)
router.Post("/api/todos", CreateTodo, AuthMiddleware)
router.Put("/api/todos/{id}", UpdateTodo, AuthMiddleware)
router.Delete("/api/todos/{id}", DeleteTodo, AuthMiddleware)
// Start an http server with the router.
http.ListenAndServe(":8080", router)
}
func ListTodos(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Todo list"))
}
func CreateTodo(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
}
func UpdateTodo(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
w.Write([]byte("Todo with id "+id+" updated"))
}
func DeleteTodo(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
// Check for the Authorization header
if authHeader == "" || authHeader != "Bearer valid-token" { // replace "valid-token" with actual validation logic
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Call the next handler in the chain
next.ServeHTTP(w, r)
})
}
go-express is open-sourced software licensed under MIT License.