Skip to content

Commit

Permalink
Add GetVarNames() (#676)
Browse files Browse the repository at this point in the history
**Summary of Changes**

1. Added `r.GetVarNames()` function to list all vars a route might need
in order to call `r.URL()`

---------

Co-authored-by: Anonymous <anonymous@github.com>
Co-authored-by: Corey Daley <cdaley@redhat.com>
  • Loading branch information
3 people authored Aug 24, 2023
1 parent 85123bf commit 4a671cb
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,19 @@ url, err := r.Get("article").URL("subdomain", "news",
"id", "42")
```

To find all the required variables for a given route when calling `URL()`, the method `GetVarNames()` is available:
```go
r := mux.NewRouter()
r.Host("{domain}").
Path("/{group}/{item_id}").
Queries("some_data1", "{some_data1}").
Queries("some_data2", "{some_data2}").
Name("article")

// Will print [domain group item_id some_data1 some_data2] <nil>
fmt.Println(r.Get("article").GetVarNames())

```
### Walking Routes

The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example,
Expand Down
35 changes: 35 additions & 0 deletions example_route_vars_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package mux_test

import (
"fmt"
"github.com/gorilla/mux"
)

// This example demonstrates building a dynamic URL using
// required vars and values retrieve from another source
func ExampleRoute_GetVarNames() {
r := mux.NewRouter()

route := r.Host("{domain}").
Path("/{group}/{item_id}").
Queries("some_data1", "{some_data1}").
Queries("some_data2_and_3", "{some_data2}.{some_data3}")

dataSource := func(key string) string {
return "my_value_for_" + key
}

varNames, _ := route.GetVarNames()

pairs := make([]string, 0, len(varNames)*2)

for _, varName := range varNames {
pairs = append(pairs, varName, dataSource(varName))
}

url, err := route.URL(pairs...)
if err != nil {
panic(err)
}
fmt.Println(url.String())
}
34 changes: 34 additions & 0 deletions mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2879,6 +2879,40 @@ func TestContextMiddleware(t *testing.T) {
r.ServeHTTP(rec, req)
}

func TestGetVarNames(t *testing.T) {
r := NewRouter()

route := r.Host("{domain}").
Path("/{group}/{item_id}").
Queries("some_data1", "{some_data1}").
Queries("some_data2_and_3", "{some_data2}.{some_data3}")

// Order of vars in the slice is not guaranteed, so just check for existence
expected := map[string]bool{
"domain": true,
"group": true,
"item_id": true,
"some_data1": true,
"some_data2": true,
"some_data3": true,
}

varNames, err := route.GetVarNames()
if err != nil {
t.Fatal(err)
}

if len(varNames) != len(expected) {
t.Fatalf("expected %d names, got %d", len(expected), len(varNames))
}

for _, varName := range varNames {
if !expected[varName] {
t.Fatalf("got unexpected %s", varName)
}
}
}

// mapToPairs converts a string map to a slice of string pairs
func mapToPairs(m map[string]string) []string {
var i int
Expand Down
19 changes: 19 additions & 0 deletions route.go
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,25 @@ func (r *Route) GetHostTemplate() (string, error) {
return r.regexp.host.template, nil
}

// GetVarNames returns the names of all variables added by regexp matchers
// These can be used to know which route variables should be passed into r.URL()
func (r *Route) GetVarNames() ([]string, error) {
if r.err != nil {
return nil, r.err
}
var varNames []string
if r.regexp.host != nil {
varNames = append(varNames, r.regexp.host.varsN...)
}
if r.regexp.path != nil {
varNames = append(varNames, r.regexp.path.varsN...)
}
for _, regx := range r.regexp.queries {
varNames = append(varNames, regx.varsN...)
}
return varNames, nil
}

// prepareVars converts the route variable pairs into a map. If the route has a
// BuildVarsFunc, it is invoked.
func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {
Expand Down

0 comments on commit 4a671cb

Please sign in to comment.