mux icon indicating copy to clipboard operation
mux copied to clipboard

Feature/method case insensitive

Open cornejong opened this issue 2 weeks ago • 0 comments

What type of PR is this? (check all applicable)

  • [ ] Refactor
  • [x] Feature
  • [ ] Bug Fix
  • [ ] Optimization
  • [ ] Documentation Update
  • [ ] Go Version Update
  • [ ] Dependency Update

Description

This PR adds the ability to define case insensitive method matching for routes. as suggested in issue #762. To achieve this this pr adds the following:

// methodMatcher matches the request against HTTP methods without case sensitivity.
// Both the supplied methods as well as the request method will be transformed to uppercase.
type methodCaseInsensitiveMatcher []string

// methodCaseExactMatcher matches the request against HTTP methods exactly.
// No transformation of supplied methods or the request method is applied.
type methodCaseExactMatcher []string

// Explicitly apply the default (and current)  method matcher, overrides the router default
func (r *Route) MethodsDefault(methods ...string) *Route
// Explicitly apply the case insensitive method matcher, overrides the router default
func (r *Route) MethodsCaseInsensitive(methods ...string) *Route
// Explicitly apply the exact method matcher, overrides the router default
func (r *Route) MethodsCaseExact(methods ...string) *Route

// Set routeConf value for methodMatcher, for this route, to methodDefaultMatcher
func (r *Route) MatchMethodDefault() *Route
// Set routeConf value for methodMatcher, for this route, to methodCaseInsensitiveMatcher
func (r *Route) MatchMethodCaseInsensitive() *Route
// Set routeConf value for methodMatcher, for this route, to methodCaseExactMatcher
func (r *Route) MatchMethodCaseExact() *Route

// Set default method matcher for the router to methodDefaultMatcher
func (r *Router) MatchMethodDefault() *Router
// Set default method matcher for the router to methodCaseInsensitiveMatcher
func (r *Router) MatchMethodCaseInsensitive() *Router
// Set default method matcher for the router to methodCaseExactMatcher
func (r *Router) MatchMethodCaseExact() *Router


type routeConf struct {
    // ...
    // Holds the default method matcher
    methodMatcher matcher
}

// as well a the helper
func sliceToUpper(slice []string) []string 

Usage

Setting the default method matcher on the router:

r := mux.NewRouter()
r.MatchMethodDefault()          // For the default matcher
r.MatchMethodCaseInsensitive()  // For case insensitive matching
r.MatchMethodCaseExact()        // For exact matching

r.HandleFunc("/", func).Methods("GET") //  will use the default matcher set on the router

Applying a specific matcher to a single route and overriding the default method matcher of the router:

r.HandleFunc("/", func).MatchMethodDefault().Methods("GET")
r.HandleFunc("/", func).MatchMethodCaseInsensitive().Methods("GET")
r.HandleFunc("/", func).MatchMethodCaseExact().Methods("GET")
// Not the prefferd method, order of opperations is critcal here. 
// Since the Methods(...) func adds the matcher. 
// Invoking the MatchMethodCaseInsensitive() method after it will have no effect.

// OR, the more preferred method:

r.HandleFunc("/", func).MethodsDefault("GET")
// Explicitly match the methods for this route with the default matcher
r.HandleFunc("/", func).MethodsCaseInsensitive("GET")
// Explicitly match the methods for this route without case sensitivity
r.HandleFunc("/", func).MethodsCaseExact("GET")
// Explicitly match the methods for this route exactly

While using the standard Methods(...) method the default matcher for the router will be used.

Related Tickets & Documents

  • Related Issue #762
  • Closes #762

Added/updated tests?

  • [x] Yes
  • [ ] No, and this is why: please replace this line with details on why tests have not been included
  • [ ] I need help with writing tests

Run verifications and test

  • [x] make verify is passing
  • [x] make test is passing

cornejong avatar Jun 20 '24 17:06 cornejong