package main import ( "context" "fmt" "net/http" "regexp" "slices" ) type URLParam struct{} var routes = []struct { methods []string regex *regexp.Regexp handler http.HandlerFunc }{ {[]string{"GET"}, url(""), index}, {[]string{"GET"}, url("/static/.+"), static}, {[]string{"GET"}, url("/(.+\\.css)"), css}, {[]string{"GET"}, url("/([^/]+)"), html}, } func url(s string) *regexp.Regexp { return regexp.MustCompile("^" + s + "/?$") } func getParam(r *http.Request, i int) string { return r.Context().Value(URLParam{}).([]string)[i] } func route(w http.ResponseWriter, r *http.Request) { for _, rt := range routes { matches := rt.regex.FindStringSubmatch(r.URL.Path) if len(matches) > 0 { if !slices.Contains(rt.methods, r.Method) { w.Header().Set("Allow", r.Method) http.Error( w, "405 method not allowed", http.StatusMethodNotAllowed, ) return } fmt.Println(r.Method, r.URL.Path) rt.handler(w, r.WithContext( context.WithValue(r.Context(), URLParam{}, matches[1:]), )) return } } http.NotFound(w, r) }