gogorillahttprouter

Chaining middleware in net/http golang


I am trying to add context to Authorization middleware. The ContextHandler is a handler which will be passed to api handlers to take care of connections and config variables. A struct Method ServeHTTP also has been added to the ContextHandler so that it satisfies the net/Http interface for handling requests properly.

CheckAuth is the middle ware which takes in the request to check token validation etc, If token is valid, executes the ServeHTTP method and if not, Returns the appropriate error in the response.

Code compiles, but i am getting error in the ServeHTTP method.

type ContextHandler struct {
    *AppContext
     Handler func(*AppContext, http.ResponseWriter, *http.Request)(int, error)

}

type AppContext struct {
   Db    *mgo.Session
   Config *simplejson.Json
}


func (ah *ContextedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

status, err := ah.handler(ah.AppContext, w, r)
if err != nil {
     switch status {
    case http.StatusNotFound:
        http.NotFound(w, r)
      case http.StatusInternalServerError:
          http.Error(w, http.StatusText(status), status)
    default:
        http.Error(w, http.StatusText(405), 405)
    }}}





func CheckAuth(h http.Handler) http.Handler {
    log.Println("Entered in CheckAuth")
    f := func( w http.ResponseWriter, r *http.Request) {
    authorizationToken := r.Header.Get("Authorization")
    if authorizationToken != ""{
        secret := []byte("somejunk")
        var credentials authorization
        token, err := jwt.ParseWithClaims(authorizationToken, &credentials, func(t *jwt.Token) (interface{}, error) {
        return []byte(secret), nil
        })

        if err == nil && token.Valid {
            //If everything is fine serve the Http request
            h.ServeHTTP( w, r)
            return 

            } else {
                  //Some response returned
                  json.NewEncoder(w).Encode(response)
                  return 
                  }
        //Check if user exists in the database 
        if dberr != nil {
           //SOmeresponse to be returned
          json.NewEncoder(w).Encode(response)
          return 
        }
      }else{
          response := simplejson.New()
          //response authorization header is missing
          json.NewEncoder(w).Encode(response)
          return 

        }
}
        return http.HandlerFunc(f)

}

func Initdb(configfile  *simplejson.Json) *mgo.Session {
   //return mongodbsession, copy and close while using it
}

In main.go file in the parent package 
func main() {
      var FileUploadContextHandler *ContextedHandler = &ContextedHandler{&context, filesystem.FileUpload}
     router.Methods("POST").Path("/decentralizefilesystem/fileupload").Name("FileUpload").Handler(CheckAuth(FileUploadContextHandler))
  }

I am getting this error
    2018/07/08 20:45:38 http: panic serving 127.0.0.1:52732: runtime error: invalid memory address or nil pointer dereference
goroutine 35 [running]:
net/http.(*conn).serve.func1(0xc4202ce140)
    /usr/local/go/src/net/http/server.go:1726 +0xd0
panic(0x6fe680, 0x92cb10)
    /usr/local/go/src/runtime/panic.go:502 +0x229
gitlab.com/mesha/Gofeynmen/vendor/gopkg.in/mgo%2ev2.(*Session).Copy(0x0, 0x7ff9485fb060)
    /home/feynman/goworkspace/src/gitlab.com/mesha/Gofeynmen/vendor/gopkg.in/mgo.v2/session.go:1589 +0x22
gitlab.com/mesha/Gofeynmen/appsettings.CheckAuth.func1(0x7ff9485fb060, 0xc420276300, 0xc4202e4200)
    /home/feynman/goworkspace/src/gitlab.com/mesha/Gofeynmen/appsettings/appsettings.go:115 +0x361
net/http.HandlerFunc.ServeHTTP(0xc420290180, 0x7ff9485fb060, 0xc420276300, 0xc4202e4200)
    /usr/local/go/src/net/http/server.go:1947 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc42024a310, 0x7ff9485fb060, 0xc420276300, 0xc4202e4200)
    /home/feynman/goworkspace/src/github.com/gorilla/mux/mux.go:162 +0xed
github.com/gorilla/handlers.loggingHandler.ServeHTTP(0x7a8120, 0xc42000e018, 0x7a7b20, 0xc42024a310, 0x7aad60, 0xc4202f0000, 0xc4202e4000)
    /home/feynman/goworkspace/src/github.com/gorilla/handlers/handlers.go:69 +0x123
github.com/gorilla/handlers.(*cors).ServeHTTP(0xc4202c4090, 0x7aad60, 0xc4202f0000, 0xc4202e4000)
    /home/feynman/goworkspace/src/github.com/gorilla/handlers/cors.go:52 +0xa3b
net/http.serverHandler.ServeHTTP(0xc4202da0d0, 0x7aad60, 0xc4202f0000, 0xc4202e4000)
    /usr/local/go/src/net/http/server.go:2694 +0xbc
net/http.(*conn).serve(0xc4202ce140, 0x7ab120, 0xc42025e100)
    /usr/local/go/src/net/http/server.go:1830 +0x651
created by net/http.(*Server).Serve
    /usr/local/go/src/net/http/server.go:2795 +0x27b

Solution

  • It's likely an attempt to dereference ah from (ah *ContextedHandler), when ah is not a pointer to a ContextedHandler.

    The types in this assignment don't match up:

    var FileUploadContextHandler *ContextedHandler =
        ContextedHandler{&context, filesystem.FileUpload}
    

    On the left side you have type *ContextedHandler. On the right side you have type ContextedHandler.

    Did you mean

    var FileUploadContextHandler *ContextedHandler =
        &ContextedHandler{&context, filesystem.FileUpload} 
    

    Or did you mean

    var FileUploadContextHandler ContextedHandler =
        ContextedHandler{&context, filesystem.FileUpload}
    

    ?


    The argument passed to the CheckAuth function appears to not match the function signature either:

    CheckAuth(FileUploadContextHandler)
    

    FileUploadContextHandler is type *ContextedHandler. The function signature is:

    func CheckAuth(h contextHandlerFunc) contextHandlerFunc
    

    The type definition of contextHandlerFunc does not appear to be part of the code you shared.


    A problem with this line:

    router.Methods("POST").Path("/decentralizefilesystem/fileupload").Name("FileUpload").Handler(CheckAuth(FileUploadContextHandler))
    

    ...would be easier to track down if you broke it up into variable assignments on several lines and then figured out which line the panic pointed to.