Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wildcards in the pattern for http.HandleFunc

Tags:

regex

go

When registering handlers in Go (language) is there any way to specify wildcards in the pattern?

For example:

http.HandleFunc("/groups/*/people", peopleInGroupHandler) 

Where the * could be any valid URL string. Or is the only solution to match /groups and figure the rest out from within the handler (peopleInGroupHandler) func?

like image 207
Mat Ryer Avatar asked Jul 03 '11 18:07

Mat Ryer


2 Answers

The patterns for http.Handler and http.HandleFunc aren't regular expressions or globs. There isn't a way to specify wildcards. They're documented here.

That said, it's not too hard to create your own handler that can use regular expressions or any other kind of pattern you want. Here's one that uses regular expressions (compiled, but not tested):

type route struct {     pattern *regexp.Regexp     handler http.Handler }  type RegexpHandler struct {     routes []*route }  func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler http.Handler) {     h.routes = append(h.routes, &route{pattern, handler}) }  func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.ResponseWriter, *http.Request)) {     h.routes = append(h.routes, &route{pattern, http.HandlerFunc(handler)}) }  func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {     for _, route := range h.routes {         if route.pattern.MatchString(r.URL.Path) {             route.handler.ServeHTTP(w, r)             return         }     }     // no pattern matched; send 404 response     http.NotFound(w, r) } 
like image 160
Evan Shaw Avatar answered Sep 17 '22 23:09

Evan Shaw


Since 2011, you can now (2014+) find other solutions.
For instance, the mux package of the Gorilla Web toolkit provides all kind of routing options:

  • Pattern matching on request paths, with optional regular expressions.
  • Matching on URL host and scheme, request method, header and query values.
  • Matching based on custom functions.
  • Use of sub-routers for easy nested routing.

It can be easily integrated to any BYOR (Bring your own Router) http library, like negroni.

Here is an example from the article "Gorilla vs Pat vs Routes: A Mux Showdown":

package main  import (   "github.com/gorilla/mux"   "log"   "net/http" )  func main() {   rtr := mux.NewRouter()   rtr.HandleFunc("/user/{name:[a-z]+}/profile", profile).Methods("GET")    http.Handle("/", rtr)    log.Println("Listening...")   http.ListenAndServe(":3000", nil) }  func profile(w http.ResponseWriter, r *http.Request) {   params := mux.Vars(r)   name := params["name"]   w.Write([]byte("Hello " + name)) } 

Sometimes better not to just use yet another "magic" package, but understand what's going on under the hood

In this instance, the "magic" is defined in "gorilla/mux/regexp.go", and tested here.
The idea is to extract named variables, assemble a regexp to be matched, create a "reverse" template to build URLs and compile regexps to validate variable values used in URL building.

like image 23
VonC Avatar answered Sep 19 '22 23:09

VonC