From 146d179e6f6bdf203a9922e7b29ad67e8993f3a2 Mon Sep 17 00:00:00 2001 From: Ben Hoyt Date: Sun, 25 Jun 2023 21:18:45 +1200 Subject: [PATCH 1/2] Try adding a test with github.com/jba/muxpatterns --- go.mod | 1 + go.sum | 36 ++++++++++++++- main.go | 18 ++++---- main_test.go | 2 +- muxpatterns/route.go | 103 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 muxpatterns/route.go diff --git a/go.mod b/go.mod index 9016e75..779714c 100644 --- a/go.mod +++ b/go.mod @@ -6,4 +6,5 @@ require ( github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 github.com/go-chi/chi v4.1.2+incompatible github.com/gorilla/mux v1.7.4 + github.com/jba/muxpatterns v0.2.0 ) diff --git a/go.sum b/go.sum index c199cf9..aa58fd3 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,41 @@ github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/go-chi/chi v1.0.0 h1:s/kv1cTXfivYjdKJdyUzNGyAWZ/2t7duW1gKn5ivu+c= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/jba/muxpatterns v0.2.0 h1:Hh5KZaEeaQPMzedDr3XgZBpW2BhYohCB5vf0FgXTyG4= +github.com/jba/muxpatterns v0.2.0/go.mod h1:77+op56At17SXLuQrR46FWJybINlMcj2E/KrDhS5JiY= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/exp v0.0.0-20230519143937-03e91628a987 h1:3xJIFvzUFbu4ls0BTBYcgbCGhA63eAOEMxIHugyXJqA= +golang.org/x/exp v0.0.0-20230519143937-03e91628a987/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/main.go b/main.go index c182402..bc2fc29 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,7 @@ import ( "github.com/benhoyt/go-routing/chi" "github.com/benhoyt/go-routing/gorilla" "github.com/benhoyt/go-routing/match" + "github.com/benhoyt/go-routing/muxpatterns" "github.com/benhoyt/go-routing/pat" "github.com/benhoyt/go-routing/reswitch" "github.com/benhoyt/go-routing/retable" @@ -50,14 +51,15 @@ func main() { } var routers = map[string]http.Handler{ - "chi": chi.Serve, - "gorilla": gorilla.Serve, - "match": http.HandlerFunc(match.Serve), - "pat": pat.Serve, - "reswitch": http.HandlerFunc(reswitch.Serve), - "retable": http.HandlerFunc(retable.Serve), - "shiftpath": http.HandlerFunc(shiftpath.Serve), - "split": http.HandlerFunc(split.Serve), + "chi": chi.Serve, + "gorilla": gorilla.Serve, + "match": http.HandlerFunc(match.Serve), + "muxpatterns": muxpatterns.Serve, + "pat": pat.Serve, + "reswitch": http.HandlerFunc(reswitch.Serve), + "retable": http.HandlerFunc(retable.Serve), + "shiftpath": http.HandlerFunc(shiftpath.Serve), + "split": http.HandlerFunc(split.Serve), } var routerNames = func() []string { diff --git a/main_test.go b/main_test.go index 0ef6791..374dc19 100644 --- a/main_test.go +++ b/main_test.go @@ -89,7 +89,7 @@ func TestRouters(t *testing.T) { } router.ServeHTTP(recorder, request) if recorder.Code != test.status { - t.Fatalf("expected status %d, got %d", test.status, recorder.Code) + t.Fatalf("expected status %d, got %d (%q)", test.status, recorder.Code, recorder.Body.String()) } if test.status == 200 { body := recorder.Body.String() diff --git a/muxpatterns/route.go b/muxpatterns/route.go new file mode 100644 index 0000000..692010b --- /dev/null +++ b/muxpatterns/route.go @@ -0,0 +1,103 @@ +// Routing based on github.com/jba/muxpatterns (proposed enhancements to http.ServeMux) + +package muxpatterns + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/jba/muxpatterns" +) + +var ( + Serve http.Handler + + // Wouldn't use a global for this in "real life" -- this is only needed + // because we have to call mux.PathValue(r, "name") below instead of + // r.PathValue("name") in the actual proposal. + mux *muxpatterns.ServeMux +) + +func init() { + r := muxpatterns.NewServeMux() + + r.HandleFunc("GET /{$}", home) + r.HandleFunc("GET /contact", contact) + r.HandleFunc("GET /api/widgets", apiGetWidgets) + r.HandleFunc("POST /api/widgets", apiCreateWidget) + // TODO: seems to have a bug where "POST /api/widgets/" matches and gives slug "/" + r.HandleFunc("POST /api/widgets/{slug}", apiUpdateWidget) + r.HandleFunc("POST /api/widgets/{slug}/parts", apiCreateWidgetPart) + r.HandleFunc("POST /api/widgets/{slug}/parts/{id}/update", apiUpdateWidgetPart) + r.HandleFunc("POST /api/widgets/{slug}/parts/{id}/delete", apiDeleteWidgetPart) + r.HandleFunc("GET /{slug}", widgetGet) + r.HandleFunc("GET /{slug}/admin", widgetAdmin) + r.HandleFunc("POST /{slug}/image", widgetImage) + + mux = r + Serve = r +} + +func home(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "home\n") +} + +func contact(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "contact\n") +} + +func apiGetWidgets(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "apiGetWidgets\n") +} + +func apiCreateWidget(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "apiCreateWidget\n") +} + +func apiUpdateWidget(w http.ResponseWriter, r *http.Request) { + slug := mux.PathValue(r, "slug") + fmt.Fprintf(w, "apiUpdateWidget %s\n", slug) +} + +func apiCreateWidgetPart(w http.ResponseWriter, r *http.Request) { + slug := mux.PathValue(r, "slug") + fmt.Fprintf(w, "apiCreateWidgetPart %s\n", slug) +} + +func apiUpdateWidgetPart(w http.ResponseWriter, r *http.Request) { + slug := mux.PathValue(r, "slug") + idStr := mux.PathValue(r, "id") + id, err := strconv.Atoi(idStr) + if err != nil || id <= 0 { + http.NotFound(w, r) + return + } + fmt.Fprintf(w, "apiUpdateWidgetPart %s %d\n", slug, id) +} + +func apiDeleteWidgetPart(w http.ResponseWriter, r *http.Request) { + slug := mux.PathValue(r, "slug") + idStr := mux.PathValue(r, "id") + id, err := strconv.Atoi(idStr) + if err != nil || id <= 0 { + http.NotFound(w, r) + return + } + fmt.Fprintf(w, "apiDeleteWidgetPart %s %d\n", slug, id) +} + +func widgetGet(w http.ResponseWriter, r *http.Request) { + slug := mux.PathValue(r, "slug") + fmt.Fprintf(w, "widget %s\n", slug) +} + +func widgetAdmin(w http.ResponseWriter, r *http.Request) { + slug := mux.PathValue(r, "slug") + fmt.Fprintf(w, "widgetAdmin %s\n", slug) +} + +func widgetImage(w http.ResponseWriter, r *http.Request) { + slug := mux.PathValue(r, "slug") + fmt.Fprintf(w, "widgetImage %s\n", slug) +} From 154b52afa74bf8f1631bd4e43308a20002e7b856 Mon Sep 17 00:00:00 2001 From: Ben Hoyt Date: Wed, 19 Jul 2023 08:19:18 +1200 Subject: [PATCH 2/2] Update to latest muxpatterns version (tests pass now!) --- go.mod | 2 +- go.sum | 4 ++-- muxpatterns/route.go | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 779714c..d5a7b26 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,5 @@ require ( github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 github.com/go-chi/chi v4.1.2+incompatible github.com/gorilla/mux v1.7.4 - github.com/jba/muxpatterns v0.2.0 + github.com/jba/muxpatterns v0.0.0-20230718112453-42aff74f7665 ) diff --git a/go.sum b/go.sum index aa58fd3..0c073b0 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxm github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/jba/muxpatterns v0.2.0 h1:Hh5KZaEeaQPMzedDr3XgZBpW2BhYohCB5vf0FgXTyG4= -github.com/jba/muxpatterns v0.2.0/go.mod h1:77+op56At17SXLuQrR46FWJybINlMcj2E/KrDhS5JiY= +github.com/jba/muxpatterns v0.0.0-20230718112453-42aff74f7665 h1:ZKXLO5DXBeTeJyN04eCsDLt4zDJ6V62Hih7URrVoqSU= +github.com/jba/muxpatterns v0.0.0-20230718112453-42aff74f7665/go.mod h1:77+op56At17SXLuQrR46FWJybINlMcj2E/KrDhS5JiY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= diff --git a/muxpatterns/route.go b/muxpatterns/route.go index 692010b..2f5abca 100644 --- a/muxpatterns/route.go +++ b/muxpatterns/route.go @@ -26,7 +26,6 @@ func init() { r.HandleFunc("GET /contact", contact) r.HandleFunc("GET /api/widgets", apiGetWidgets) r.HandleFunc("POST /api/widgets", apiCreateWidget) - // TODO: seems to have a bug where "POST /api/widgets/" matches and gives slug "/" r.HandleFunc("POST /api/widgets/{slug}", apiUpdateWidget) r.HandleFunc("POST /api/widgets/{slug}/parts", apiCreateWidgetPart) r.HandleFunc("POST /api/widgets/{slug}/parts/{id}/update", apiUpdateWidgetPart)