mux.Vars not working
Asked Answered
C

2

8

I'm running on HTTPS (port 10443) and use subroutes:

mainRoute := mux.NewRouter()
mainRoute.StrictSlash(true)
mainRoute.Handle("/", http.RedirectHandler("/static/", 302))
mainRoute.PathPrefix("/static/").Handler(http.StripPrefix("/static", *fh))

// Bind API Routes
apiRoute := mainRoute.PathPrefix("/api").Subrouter()

apiProductRoute := apiRoute.PathPrefix("/products").Subrouter()
apiProductRoute.Handle("/", handler(listProducts)).Methods("GET")

And the functions:

func listProducts(w http.ResponseWriter, r *http.Request) (interface{}, *handleHTTPError) {
    vars := mux.Vars(r)

    productType, ok := vars["id"]
    log.Println(productType)
    log.Println(ok)
}

ok is false and I have no idea why. I'm doing a simple ?type=model after my URL..

Caulfield answered 12/7, 2015 at 18:26 Comment(0)
C
34

When you enter a URL like somedomain.com/products?type=model you're specifying a query string, not a variable.

Query strings in Go are accessed via r.URL.Query - e.g.

vals := r.URL.Query() // Returns a url.Values, which is a map[string][]string
productTypes, ok := vals["type"] // Note type, not ID. ID wasn't specified anywhere.
var pt string
if ok {
    if len(productTypes) >= 1 {
        pt = productTypes[0] // The first `?type=model`
    }
}

As you can see, this can be a little clunky as it has to account for the map value being empty and for the possibility of a URL like somedomain.com/products?type=model&this=that&here=there&type=cat where a key can be specified more than once.

As per the gorilla/mux docs you can use route variables:

   // List all products, or the latest
   apiProductRoute.Handle("/", handler(listProducts)).Methods("GET")
   // List a specific product
   apiProductRoute.Handle("/{id}/", handler(showProduct)).Methods("GET")

This is where you would use mux.Vars:

vars := mux.Vars(request)
id := vars["id"]

Hope that helps clarify. I'd recommend the variables approach unless you specifically need to use query strings.

Cologne answered 12/7, 2015 at 21:10 Comment(5)
What about query parameters? @CologneExorbitant
@Exorbitant "Query strings in Go are accessed via r.URL.Query"Cologne
There is a typo in the code it has to be if len(productTypes) >= 1Yacov
I expected mux.Vars(r) to return query parameters as well, but it does not seem to. Can anyone confirm?Shelli
@LukePighetti mux.Vars(r) returns the route variables from mux. Query parameters are returned via r.URL.Query.Cologne
B
4

An easier way to solve this is to add query parameters in your route through Queries, like:

apiProductRoute.Handle("/", handler(listProducts)).
                Queries("type","{type}").Methods("GET")

You can get it using:

v := mux.Vars(r)
type := v["type"]

NOTE: This might not have been possible when the question was originally posted but I stumbled across this when I encountered a similar problem and the gorilla docs helped.

Burned answered 27/9, 2017 at 13:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.