[Go] chiで静的ファイルを配信したい時

goで作ったhttpサーバーは、標準ライブラリだけで静的ファイルを配信することもできる。

以下は ./static 以下にあるファイルを配信するサンプル。

package main

import (
    "net/http"
)

func main() {
    mux := http.NewServeMux()
    fileServer := http.FileServer(http.Dir("./static"))

    mux.Handle("/static/", http.StripPrefix("/static/", fileServer))
    server := http.Server{
        Addr:    ":8080",
        Handler: mux,
    }
    server.ListenAndServe()
}

こういう風にすれば良いんだけど、chiと組み合わせる時に少し苦戦した。

chiはルーティングを設定するとき

r.Get("/ping", pingHandler)

func pingHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello World!")
}

みたいに handlerを指定するので、 http.StripPrefix("/static/", fileServer) をぶち込んでもうまくいかない。

なので、

package main

import (
	"net/http"

	"os"

	"github.com/go-chi/chi"
)

func main() {
	r := chi.NewRouter()
        fileServer := http.FileServer(http.Dir("./static/"))
	r.Get("/static/",
		func (w http.ResponseWriter, r *http.Request) {
				http.StripPrefix("/static/", fileServer).ServeHTTP(w, r)
		},
	)

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

という風に変換を挟んであげれば動くようになる。なるのだが、今度は /static にはアクセスできても、その配下のファイルには404でアクセスできない。

なぜなら /static にしかルーティングしていないから。

結論としては、chi はワイルドカードの指定に対応しているので、

package main

import (
	"net/http"

	"os"

	"github.com/go-chi/chi"
)

func main() {
	r := chi.NewRouter()
        fileServer := http.FileServer(http.Dir("./static/"))
	r.Get("/static/*",
		func (w http.ResponseWriter, r *http.Request) {
				http.StripPrefix("/static/", fileServer).ServeHTTP(w, r)
		},
	)

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

こういう風にワイルドカードを指定すれば良い。