0

i've been trying to implement this tutorial with go-chi and especially the part about wrapping / passing an argument to a wrapper.

My goal is to be able to wrap some specific routes with a middleware with custom parameters for that route instead of having middleware that are " global " to all my routes but i'm having issues doing it.

package main

import (
    "context"
    "io"
    "net/http"

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

func main() {

    r := chi.NewRouter()
    r.Use(middleware.Logger)

    r.Get("/user", MustParams(sayHello, "key", "auth"))

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


func sayHello(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("hi"))
}

func MustParams(h http.Handler, params ...string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        q := r.URL.Query()
        for _, param := range params {
            if len(q.Get(param)) == 0 {
                http.Error(w, "missing "+param, http.StatusBadRequest)
                return // exit early
            }
        }
        h.ServeHTTP(w, r) // all params present, proceed
    })
}

i'm getting cannot use sayHello (type func(http.ResponseWriter, *http.Request)) as type http.Handler in argument to MustParams: func(http.ResponseWriter, *http.Request) does not implement http.Handler (missing ServeHTTP method)

and if i try to type assert it doing r.Get("/user", MustParams(http.HandleFunc(sayHello), "key", "auth"))

i get the error cannot use MustParams(http.HandleFunc(sayHello), "key", "auth") (type http.Handler) as type http.HandlerFunc in argument to r.Get: need type assertion

I can't seem to find a way to make it work or to be able to wrapping a single route with a middleware.

kijawi21
  • 13
  • 1
  • 2
  • Change `MustParams`' return type from `http.Handler` to `http.HandleFunc`. – Adrian Jan 11 '21 at 22:40
  • tried that too obv, `cannot use sayHello (type func(http.ResponseWriter, *http.Request)) as type http.Handler in argument to MustParams: func(http.ResponseWriter, *http.Request) does not implement http.Handler (missing ServeHTTP method)` – kijawi21 Jan 11 '21 at 22:58
  • The **return type**, not the argument type. – Adrian Jan 11 '21 at 23:08
  • do you mean this `func MustParams(h http.Handler, params ...string) http.HandlerFunc {` ? because that's what i did – kijawi21 Jan 11 '21 at 23:11
  • Yes, and you still need to call it with `http.HandleFunc(sayHello)` as the first parameter. – Adrian Jan 11 '21 at 23:18
  • were you able to make it work locally ? because i'm still getting errors `not enough arguments in call to http.HandleFunc have (func(http.ResponseWriter, *http.Request)) want (string, func(http.ResponseWriter, *http.Request))` – kijawi21 Jan 11 '21 at 23:25

1 Answers1

2

There's a function http.HandleFunc and then there's a type http.HandlerFunc. You're using the former but you need the latter.

r.Get("/user", MustParams(http.HandlerFunc(sayHello), "key", "auth"))
mkopriva
  • 35,176
  • 4
  • 57
  • 71