What routes is my http.ServeMux listening for?

Featured image for sharing metadata for article

As I've been looking at adding Go 1.22+'s new net/http routing to oapi-codegen so folks could use the new lightweight functionality built into the standard library, I found that I wanted to make sure that my routes were all configured correctly.

I found this StackOverflow answer by hsrv which worked prior to Go 1.22's release, but does not since the release of enhanced routing.

Note that as this relies on reflection and the use of internal, unexported fields, it's likely to break at any time, as we saw with the release of Go 1.22!

Pre-Go 1.22

The behaviour for pre-Go 1.22 is:

package main

import (
	"fmt"
	"net/http"
	"reflect"
)

func main() {
	mux := http.NewServeMux()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {})
	mux.HandleFunc("/pets", func(w http.ResponseWriter, r *http.Request) {
	})

	m := reflect.ValueOf(mux).Elem().FieldByName("m")
	keys := m.MapKeys()

	fmt.Println("Listening for routes:")
	for _, v := range keys {
		fmt.Println(v)
	}
}

When we run this, we can see:

$ go version
go version go1.21.7 linux/amd64
$ go run .
Listening for routes:
/
/pets

Go 1.22

The new behaviour found in Go 1.22 is:

package main

import (
	"fmt"
	"log"
	"net/http"
	"reflect"
)

func main() {
	mux := http.NewServeMux()

	mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {})
	mux.HandleFunc("GET /pets/{id}", func(w http.ResponseWriter, r *http.Request) {
		log.Printf("Called pet %s", r.PathValue("id"))
	})

	m := reflect.ValueOf(mux).Elem().FieldByName("mux121")
	keys := m.FieldByName("m").MapKeys()

	fmt.Println("Listening for routes:")
	for _, v := range keys {
		fmt.Println(v)
	}
}

We can see this with Go 1.22:

$ go version
go version go1.22.0 linux/amd64
$ go run .
Listening for routes:
GET /
GET /pets/{id}

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#blogumentation #go.

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.