Skip to content
/ muxer Public

muxer is a lightweight HTTP router written in Go that is designed to be simple, flexible, and familiar to users of the net/http package. It provides a simple API for registering HTTP handlers and middleware functions, and matching incoming requests to the appropriate handler based on their path and HTTP method.

License

Notifications You must be signed in to change notification settings

shellfu/muxer

Repository files navigation

muxer - A lightweight HTTP router

Go Report Card GoDoc codecov

muxer is a lightweight HTTP router written in Go that is designed to be simple, flexible, and familiar to users of the net/http package. It provides a simple API for registering HTTP handlers and middleware functions, and matching incoming requests to the appropriate handler based on their path and HTTP method.

muxer uses regular expressions to match incoming request paths, and allows for named parameters to be extracted from the path and passed to the handler function. It also supports middleware functions that can be executed before the main handler, allowing for common functionality like authentication and logging to be shared across multiple routes.

Note From Author:

muxer has been in production at my company for over a year, coming up on two and is used in all of our microservices that power our backend service layer across kubernetes, cloud foundry and aws. It is my hope it brings you joy in your programming!

While you have your choice in routing, I hope this approach can be of use to you.

Table of Contents

  1. Installation
  2. Usage
  3. Routing
  4. Serving Static Files
  5. Additional Documentation

Installation

To install muxer, use the following command:

go get github.com/shellfu/muxer

Usage

Here's an example of how to use muxer:

package main

import (
	"fmt"
	"net/http"

	"github.com/shellfu/muxer"
)

func main() {
	r := muxer.NewRouter()

	r.HandleFunc(http.MethodGet, "/hello/:name", func(w http.ResponseWriter, r *http.Request) {
		params := router.Params(r)
		name := params["name"]
		fmt.Fprintf(w, "Hello, %s!", name)
	})

	http.ListenAndServe(":8080", r)
}

This example creates a new router using the NewRouter function, registers a route using the HandleFunc method, and starts an HTTP server using the ListenAndServe function.

Routes are defined using the HandleFunc method, which takes an HTTP method, a path pattern, and an HTTP handler function. The path pattern may include named parameters, indicated by a leading colon (e.g. "/users/:id"). The named parameters are extracted from the path and added to the request context, where they can be retrieved using the Params method of the Router.

muxer also supports middleware, which can be registered using the Use method of the Router. Middleware functions take an http.Handler and return a new http.Handler that performs some additional functionality before passing the request on to the next handler in the chain.

For example, the following code adds a logger middleware that logs the HTTP request method, URL, and duration:

func logger(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		h.ServeHTTP(w, r)
		log.Printf("%s %s %s", r.Method, r.URL.Path, time.Since(start))
	})
}

r.Use(logger)

This middleware function takes an http.Handler and returns a new http.Handler that logs the HTTP request method, URL, and duration before passing the request on to the next handler in the chain.

muxer also provides several built-in middleware functions, such as CORS and Gzip compression, which can be registered using the Use method and the corresponding functions from the middleware package.

Routing

The Router instance allows registering routes that match HTTP requests based on the request's URL path and HTTP method. You can register a route using the HandleRoute method, which takes an HTTP method, a path pattern, and an HTTP handler function.

To register a route with the Router instance, you can use the HandleRoute method, which takes three arguments:

  • An HTTP method (GET, POST, PUT, DELETE, etc.)
  • A path pattern (e.g. /users/:id)
  • An HTTP handler function that takes a http.ResponseWriter and a *http.Request

The path pattern can include named parameters that will be extracted from the URL path and passed to the handler function as a map. For example, in the path pattern /users/:id, :id is a named parameter that will match any string and be extracted as a key-value pair in the map passed to the handler function.

Here's an example that shows how to register a route with the Router instance:

r := muxer.NewRouter()

r.HandleRoute("GET", "/users/:id", func(w http.ResponseWriter, req *http.Request) {
    params := r.Params(req)
    id := params["id"]
    fmt.Fprintf(w, "User ID: %s", id)
})

In this example, we create a new Router instance and register a route that matches GET requests to the path /users/:id. The route's handler function extracts the value of the id parameter from the map returned by the Params method of the Router instance and writes it to the response writer.

The HandleRoute method returns an error if there is a problem compiling the regular expression that matches the path pattern. It's a good practice to handle this error and log it appropriately.

In addition to the HandleRoute method, the muxer package also provides the HandlerFunc method, which is a convenience method for registering a new route with an HTTP handler function. It takes the same arguments as HandleRoute, but the HTTP handler function is passed as an http.HandlerFunc instead of a generic http.Handler. This method is provided to make the muxer API more familiar to users of the net/http package.

Serving Static Files

While muxer doesn't provide built-in support for serving static files to avoid duplicating the functionality of http.FileServer, you can easily use http.FileServer in combination with muxer to handle static file serving. Here's how you can do it:

router := muxer.NewRouter()

fs := http.FileServer(http.Dir("/path/to/your/static/files"))
router.Handle(http.MethodGet, "/static/:filepath", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
	params := muxer.Params(req)
	req.URL.Path = params["filepath"]
	fs.ServeHTTP(w, req)
}))

In this example, an http.FileServer is created that serves files from a specified directory. Then a new route is registered in the muxer router that matches any GET requests where the path starts with "/static/". When such a request is matched, the remaining part of the path is used to identify the static file to be served.

This pattern can be adjusted to suit different needs, including serving files from multiple directories, serving files with certain content types, and more. The main idea here is to leverage the existing functionality of http.FileServer and integrate it with the routing capabilities of muxer to provide a seamless static file serving solution.

Remember to replace /path/to/your/static/files with the actual path to the directory that contains your static files.

Please note that it's always a good practice to handle any errors that may occur during the setup and usage of http.FileServer. This includes checking if the specified directory exists and is readable, and handling any errors returned by fs.ServeHTTP

Working with Params

In routes that include path parameters, such as PUT /users/:id and DELETE /users/:id, you need to extract these parameters from the request context. The muxer package provides a standalone Params function that makes this easy:

func updateUserHandler(w http.ResponseWriter, req *http.Request) {
    params := muxer.Params(req)
    id := params["id"]

    // Use the id to update the user
    fmt.Printf("Updating user with ID: %s\n", id)
}

func deleteUserHandler(w http.ResponseWriter, req *http.Request) {
    params := muxer.Params(req)
    id := params["id"]

    // Use the id to delete the user
    fmt.Printf("Deleting user with ID: %s\n", id)
}

By using the Params function, you can easily access the path parameters directly from the request context.


Additional Documentation

For more information about muxer, please refer to the following documents:

About

muxer is a lightweight HTTP router written in Go that is designed to be simple, flexible, and familiar to users of the net/http package. It provides a simple API for registering HTTP handlers and middleware functions, and matching incoming requests to the appropriate handler based on their path and HTTP method.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages