Skip to content

Commit

Permalink
added route metadata with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Corné de Jong committed May 26, 2024
1 parent cfec64d commit 73bcd01
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
2 changes: 2 additions & 0 deletions mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ var (
// Do not run this function from `init()` in importable packages.
// Changing this value is not safe for concurrent use.
RegexpCompileFunc = regexp.Compile
// ErrMetadataKeyNotFound is returned when the specified metadata key is not present in the map
ErrMetadataKeyNotFound = errors.New("key not found in metadata")
)

// NewRouter returns a new router instance.
Expand Down
46 changes: 46 additions & 0 deletions route.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ type Route struct {
// Error resulted from building a route.
err error

// The meta data associated with this route
metadata map[any]any

// "global" reference to all named routes
namedRoutes map[string]*Route

Expand Down Expand Up @@ -122,6 +125,49 @@ func (r *Route) BuildOnly() *Route {
return r
}

// MetaData -------------------------------------------------------------------

// Metadata is used to set metadata on a route
func (r *Route) Metadata(key any, value any) *Route {
if r.metadata == nil {
r.metadata = make(map[any]any)
}

r.metadata[key] = value
return r
}

// GetMetadata returns the metadata map for route
func (r *Route) GetMetadata() map[any]any {
return r.metadata
}

// MetadataContains returns whether or not the key is present in the metadata map
func (r *Route) MetadataContains(key any) bool {
_, ok := r.metadata[key]
return ok
}

// GetMetadataValue returns the value of a specific key in the metadata map. If the key is not present in the map mux.ErrMetadataKeyNotFound is returned
func (r *Route) GetMetadataValue(key any) (any, error) {
value, ok := r.metadata[key]
if !ok {
return nil, ErrMetadataKeyNotFound
}

return value, nil
}

// GetMetadataValueOr returns the value of a specific key in the metadata map. If the key is not present in the metadata the fallback value is returned
func (r *Route) GetMetadataValueOr(key any, fallbackValue any) any {
value, ok := r.metadata[key]
if !ok {
return fallbackValue
}

return value
}

// Handler --------------------------------------------------------------------

// Handler sets a handler for the route.
Expand Down
88 changes: 88 additions & 0 deletions route_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package mux

import (
"errors"
"net/http"
"reflect"
"regexp"
"sync"
"testing"
Expand Down Expand Up @@ -64,3 +66,89 @@ func testNewRouter(_ testing.TB, handler http.Handler) {
r.Queries("orgID", "{orgID:[0-9]*?}")
r.Host("{subdomain}.domain.com")
}

func TestRouteMetadata(t *testing.T) {
router := NewRouter()
rw := NewRecorder()

expectedMap := make(map[any]any)
expectedMap["key"] = "value"

router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
route := CurrentRoute(r)
metadata := route.GetMetadata()

if !reflect.DeepEqual(metadata, expectedMap) {
println(metadata)
t.Fatalf("Expected map does not equal the metadata map")
}

}).Metadata("key", "value")

router.HandleFunc("/single-value", func(w http.ResponseWriter, r *http.Request) {
route := CurrentRoute(r)
value, err := route.GetMetadataValue("key")
if err != nil {
t.Fatalf("Expected metadata value to be present, but gave error: %s", err)
}

stringValue, ok := value.(string)
if !ok {
t.Fatalf("Expected metadata value to be string, but was: %s", reflect.TypeOf(value))
}

if stringValue != "value" {
t.Fatalf("Expected metadata value to be '%s', but got '%s'", "value", stringValue)
}

_, err = route.GetMetadataValue("key2")
if err == nil {
t.Fatalf("Expected metadata key not to be present and error, but error was nil")
}

if !errors.Is(err, ErrMetadataKeyNotFound) {
t.Fatalf("Expected error to be ErrMetadataKeyNotFound but got: %s", err)
}

}).Metadata("key", "value")

router.HandleFunc("/single-value-fallback", func(w http.ResponseWriter, r *http.Request) {
route := CurrentRoute(r)
value := route.GetMetadataValueOr("key", "value-fallback")

stringValue, ok := value.(string)
if !ok {
t.Fatalf("Expected metadata value to be string, but was: %s", reflect.TypeOf(value))
}

if stringValue != "value" {
t.Fatalf("Expected metadata value to be '%s', but got '%s'", "value", stringValue)
}

fallbackValue := route.GetMetadataValueOr("key2", "value2")
fallbackStringValue, ok := fallbackValue.(string)
if !ok {
t.Fatalf("Expected metadata value to be string, but was: %s", reflect.TypeOf(value))
}

if fallbackStringValue != "value2" {
t.Fatalf("Expected metadata value to be '%s', but got '%s'", "value2", fallbackStringValue)
}

}).Metadata("key", "value")

t.Run("get metadata map", func(t *testing.T) {
req := newRequest("GET", "/")
router.ServeHTTP(rw, req)
})

t.Run("get metadata value", func(t *testing.T) {
req := newRequest("GET", "/single-value")
router.ServeHTTP(rw, req)
})

t.Run("get metadata value or fallback", func(t *testing.T) {
req := newRequest("GET", "/single-value-fallback")
router.ServeHTTP(rw, req)
})
}

0 comments on commit 73bcd01

Please sign in to comment.