Search code examples
gogorilla

mux is having empty parameters in the url


I have this main:

func main() {
    r := _routerprovider.GetRouter()
    srv := &http.Server{
        Handler:      r,
        Addr:         "127.0.0.1:8000",
        WriteTimeout: 60 * time.Second,
        ReadTimeout:  15 * time.Second,
    }
    fmt.Println("Running in port 8000!")
    err := srv.ListenAndServe()
    if err != nil {
        log.Fatalln(err.Error())
    }
}

And this is router:

func (h HandlerProvider) GetRouter() *mux.Router {
    r := mux.NewRouter()
    r.HandleFunc("/health", Health).Methods("GET")
    r.HandleFunc("/users", GetUsers).Methods("GET")
    r.HandleFunc("/users", CreateUser).Methods("POST")
    r.HandleFunc("/people", GetPeople).Methods("GET")
    r.HandleFunc("/peoplebyid", GetPeopleByID).Methods("GET")
    return r
}

No matter what I do, mux.Vars always returns an empty map. What am I doing wrong? This is a sample handler:

func GetPeopleByID(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    id, ok := params["id"]
    if !ok {
        ErrorHandler(w, r, fmt.Errorf("Error!"), 400)
        return
    }
    idasnumber, err := strconv.Atoi(id)
    if err != nil {
        ErrorHandler(w, r, fmt.Errorf("Error!"), 400)
        return
    }
    value, ok := services.PeopleDict[idasnumber]

    bs, _ := json.MarshalIndent(value, "", "  ")
    w.Write(bs)
}

Solution

  • mux.Vars() is only populated when matched in route (so Gorilla mux knows where to look for them). Matching in route is done by using either {name} or {name:pattern} placeholder in place where variable value is expected in route.

    So for following route:

    r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
    

    you'd have vars keys category and id set with their respective values:

    vars := mux.Vars(r)
    fmt.Fprintf(w, "Category: %v\n", vars["category"])
    fmt.Fprintf(w, "Id: %v\n", vars["id"])
    

    In your code you can fix /peoplebyid this way (depending on what is id) to make your GetPeopleById() handler work:

    func (h HandlerProvider) GetRouter() *mux.Router {
    // ...
    r.HandleFunc("/people/{id:[0-9]+}", GetPeopleByID).Methods("GET")
    // ...
    }
    

    See Gorilla Mux documentation on how to use vars here: https://github.com/gorilla/mux#examples, specifically section starting with:

    Paths can have variables. They are defined using the format {name} or {name:pattern}. If a regular expression pattern is not defined, the matched variable will be anything until the next slash.