Chaining middleware in net/http golang

2.1k Views Asked by At

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
1

There are 1 best solutions below

5
On BEST ANSWER

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.