net/httpのPath Parameterパース
golang
Lastmod: 2020-10-19

net/httphandleFunc() handle() に登録できるパスは Path Parameter を認識しない。例えば、他の Web フレームワークのように、下記 /products/:id エンドポイント中の :id を変数として取得することができない。

// :idを変数としてパースできない
http.handleFunc("/products/:id", f)

Path Parameter を取得するためには、Path Parameter 抜きのエンドポイントへのリクエストを一旦ハンドルし、そのハンドラの中で Path Parameter をパースする必要がある。

func main() {
	http.handleFunc("/products/", handleProducts)
	http.ListenAndServe(":8000", nil)
}

func handleProducts(r *http.Request, w http.ResponseWriter) {
	sub := strings.TrimPrefix(r.URL.Path, "/products")
	_, id := filepath.Split(sub)
	if id != "" {
		// :idを使う...
	}
}

/products/:id リクエストへのハンドラを設定する際には、 /products ではなく /products/ へハンドラを設定する。 /products リクエストハンドラは /products/:id リクエストを受け付けられないため。ただし /products/hoge /products/hoge/fuga などの適当なエンドポイントも受け付けてしまうので、404 を返すなど適宜処理する。

備考

Handle() HandleFunc() に登録できるパスパターンは、 net/http 中の構造体 ServeMux のルールに従う。

パターンは、「/ favicon.ico」のような固定されたルート化されたパス、または「/ images /」のようなルート化されたサブツリーに名前を付けます(末尾のスラッシュに注意してください)。長いパターンは短いパターンよりも優先されるため、「/ images /」と「/ images / thumbnails /」の両方にハンドラーが登録されている場合、「/ images / thumbnails /」で始まるパスと前者のハンドラーが呼び出されます。 「/ images /」サブツリー内の他のパスのリクエストを受け取ります。

参考文献