Home > Net >  How to get url param in middleware go-chi
How to get url param in middleware go-chi

Time:12-29

I use a specific middleware for specific set of routes

r.Route("/platform", func(r chi.Router) {
    r.Use(authService.AuthMiddleware)
    r.Get("/{id}/latest", RequestPlatformVersion)
})

Now how can I access id url param inside this AuthMiddleware middleware

func (s *Service) AuthMiddleware(h http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        fmt.Println(chi.URLParam(r, "id"))
        id := chi.URLParam(r, "id")
        
        if id > 100 {
          http.Error(w, errors.New("Error").Error(), http.StatusUnauthorized)
          return
        }
    }
    return http.HandlerFunc(fn)
}

However, the id param prints as an empty string even though the middleware is being ran and a specific route is being called

CodePudding user response:

Your Put your chi.URLParam before the path param {id} and you forgot to put .ServeHTTP(w, r) at the middleware. If you don't put that thing, your request will not go inside the path inside the Route.

this is the working example:

package main

import (
    "fmt"
    "net/http"

    "github.com/go-chi/chi"
)

func AuthMiddleware(h http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        fmt.Println(chi.URLParam(r, "id"))
        h.ServeHTTP(w, r)
    }
    return http.HandlerFunc(fn)
}

func main() {
    r := chi.NewRouter()

    r.Route("/platform/{id}", func(r chi.Router) {
        r.Use(AuthMiddleware)
        r.Get("/latest", func(rw http.ResponseWriter, r *http.Request) {
            fmt.Println("here ", chi.URLParam(r, "id")) // <- here
        })
    })

    http.ListenAndServe(":8080", r)
}

I move the {id} to platform/{id} so the middleware got the id path value, and add h.ServeHTTP(w, r) inside the middleware.

try to access http://localhost:8080/platform/1/latest

the output will be:

1
here  1

UPDATE

It is not good to run the validation after the code, you must fix the way you define the path, and move the .ServeHTTP after the validation.

This is the example:

package main

import (
    "errors"
    "fmt"
    "net/http"
    "strconv"

    "github.com/go-chi/chi"
)

func AuthMiddleware(h http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        fmt.Printf("Middleware First, id: % v\n", chi.URLParam(r, "id"))
        id, _ := strconv.Atoi(chi.URLParam(r, "id"))

        if id > 100 {
            http.Error(w, errors.New("Error").Error(), http.StatusUnauthorized)
            return
        }
        h.ServeHTTP(w, r)
    }
    return http.HandlerFunc(fn)
}

func main() {
    r := chi.NewRouter()

    // This works too ()
    // r.Route("/platform/{id}", func(r chi.Router) {
    //  r.Use(AuthMiddleware)
    //  r.Get("/latest", func(rw http.ResponseWriter, r *http.Request) {
    //      fmt.Println("second: ", chi.URLParam(r, "id")) // <- here
    //  })
    // })

    // Other Solution (Wrapping Middleware)
    r.Route("/platform", func(r chi.Router) {
        r.Get("/{id}/latest", AuthMiddleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
            fmt.Println("second: ", chi.URLParam(r, "id")) // <- here
        })).ServeHTTP)
    })

    http.ListenAndServe(":8080", r)
}
  • Related