🤔

go-chiでAPI+Staticサーバーを作成する

2023/11/01に公開

https://github.com/a10adotapp/blog.a10a.app/tree/main/2023/1101_go-chiでAPI%2BStaticサーバーを作成する

$ tree .
.
├── go.mod
├── go.sum
├── main.go
├── router
│   ├── helper
│   │   └── helper.go
│   └── router.go
└── static
    └── index.html

サーバーの起動部分

main.go

func main() {
	// 3000番ポートでサーバを起動
	http.ListenAndServe(":3000", router.NewRouter())
}

router/router.go

func NewRouter() *chi.Mux {
	router := chi.NewRouter()

	router.Use(middleware.Timeout(10 * time.Second))
	router.Use(middleware.Logger)

	router.Route("/api", func(r chi.Router) {
		r.Get("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// /apiへのリクエストを処理
		}))
	})

	router.Route("/", func(r chi.Router) {
		r.Get("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// /api以外のリクエストを処理
		}))
	})

	return router
}

/apiのJSONをレスポンスする部分

router/router.go

router.Route("/api", func(r chi.Router) {
	r.Get("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		fmt.Fprint(w, "{\"message\":\"hello from api\"}")
	}))
})

/api以外で静的ファイルをレスポンスする部分

main.go

//go:embed static/*
var staticFS embed.FS

func main() {
	http.ListenAndServe(":3000", router.NewRouter(staticFS))
}

router/router.go

func NewRouter(fsys fs.FS) *chi.Mux {
	tmpl, err := template.ParseFS(fsys, []string{
		"static/index.html",
	}...)
	if err != nil {
		panic(err)
	}

	router.Route("/", func(r chi.Router) {
		r.Get("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			pageData := &struct {
				Message string
			}{
				Message: "hello from server",
			}

			if err := tmpl.ExecuteTemplate(w, helper.ParseTemplateFilename(r.URL.Path), pageData); err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				w.Write([]byte(err.Error()))
			}
		}))
	})

	return router
}

Discussion